Il y a quelques semaines, pendant les vacances de la Toussaint, Antonio est passé au Bordeaux JUG. Et pour le projet MEGA-SECRET que désormais vous connaissez, et parce qu’aussi j’avais envie de découvrir CDI, je suis donc venu au Bordeaux JUG. Superbe soirée, c’était les 3 ans du Bordeaux JUG.
Avant tout, Xavier Hanin de 4SH et aussi président du Bordeaux JUG, fait une rétrospective des 3 dernières années. Plus de 30 présentations, en 3 ans le Bordeaux JUG s’est bien développé. La première présentation était celle de Christophe Jollivet, président du Tours JUG. Dernièrement, pour aider à financer l’association, le Bordeaux JUG propose à ses membres de cotiser librement et d’aider l’association en adhérant. Le prix était vraiment modique, et permet d’aider l’équipe d’organisation.
Après cela, un visage bien connu monte sur scène, Antonio Goncalves. Depuis quelques mois, avec Zouheir et José, on fait des séances Skype une fois par semaine, et il nous est arrivé de nous voir 4 fois par semaine pour voir les sponsors. Mon fils en fait connait la voix de Docteur Love, et ma fille reconnaît la photo « du ParisJUG », comprenez : Antonio….
Bref.
Ce soir on va parler CDI. Context and Dependency Injection.
Injection, rien d’illégal là-dedans. Le principe de l’Inversion de contrôle ne date pas d’hier. En 1998, les ingénieurs de SUN avec les bases de J2EE sont les premiers dans le monde Java à poser le principe de l’IoC. Le contrôle et la gestion du cycle de vie est effectué en dehors de votre code, au lieu de vous demander de gérer tout cela. Apache Avalon est l’un des premiers frameworks en 1999 à poser les bases de l’IoC et de la SoC (Separation of Concern). Ce couplage lâche et léger permet donc d’injecter des composants et de gérer le cycle de vie des composants.
Aujourd’hui en 2011 (je sais que vous lisez cela du futur, genre on est en 2030 et vous venez de découvrir cet ancien manuscrit)… en 2011 donc nous en sommes à CDI version 1.0
Pour commencer, Antonio présente en quelques mots ce qu’est une Dépendance.
Lorsqu’une class Java depend d’une autre class Java, vous pouvez l’instancier avec ce bon vieux new. Cela fonctionne mais apporte un couplage riche et fort. Le cycle de vie d’une classe est alors gérée par une autre classe.
Si vous souhaitez découpler votre code, le pattern IoC est là pour effectuer ce travail pour vous. Ce principe permet alors d’avoir à l’exécution une implémentation différente. Pour cela, utilisons une interface dans notre classe principale, et nous passerons une impl ou une autre lors de la construction de l’objet. Si vous avez plus de 18 ans et que vous codez en Java, vous voyez ce que je veux dire (enfin Antonio dit ça… moi j’écris).
Le pattern Factory ou un autre pattern comme le Service Locator permet aussi d’instancier des objets. A partir de là, pourquoi ne pas demander à injecteur de donner des dépendances à un client ? Par exemple une source de données pour accéder à une base ?
Des injecteurs de dépendances il y en a pleins : Apache Avalon, Spring Framework, Pico container, Nano Container, Hivemind Apache, Seam, Google Guice…
Antonio rappelle que l’injection de dépendance n’arrive qu’en 2009 avec JEE6. Dans Java EE 5 on injectait des ressources.
@Resource @PersistenceContext
Dans Java EE6 on injecte tout dans tout, et surtout avec ce qu’il va nous montrer ensuite.
Java EE 6 c’est aussi la JSR 330 et le @Inject, qui permet d’injecter un peu près tout dans tout, sans complexité accidentelle et sans une soupe de XML.
Pour faire cela, on a eu droit à 2 spécifications. Il y a eu un peu de tension au sein du JCP. La spécification CDI s’est coupée en 2, en raison de Google et Spring. Et la JSR-330 est née avec @Inject. javax.inject
@Inject @Named @Singleton @Qualifier @Scope
La JSR-330 c’est simplement 5 Pages de spécifications. Elle ne donne pas de sémantique à l’D.I ce qui est assez ennuyant. D’ailleurs c’est une spécification non portable, assez contreversée. La sémantique est donnée par CDI. Spring utilise son algo. CDI utilise son algo d’Injection différent… Bref les entreprises sont d’accord sur les annotations, pas forcément sur l’utilisation qu’il en est fait.
Le JCP a travaillé plus loin, et CDI est né sous la forme de la JSR 299 avec de la sémantique. CDI est important dans Java EE 6, c’est une spécification et une implémentation qui permet dès aujourd’hui d’écrire des applications d’entreprise « à la Spring » sans ce framework.
Pour que l’injection fonctionne, il faut un container. Il n’est pas nécessaire d’avoir un conteneur lourd, encore que les conteneurs sont de plus en plus légers. Prenez un Tomcat, ajoutez CDI et ça marche. Un fichier beans.xml placé dans le WAR permet à CDI de détecter simplement vos beans. Antonio montre un peu de code, et le moins que l’on puisse dire, c’est que c’est super simple.
@Default et @Inject
On peut mettre son propre nom comme @MyOwnName -> qualifier une annotation avec @Qualifier.
Avec CDI il est facile d’injecter un pojo et de le qualifier avec une annotation. C’est du strong typing. Ce type fort est intéressant car contrairement à une configuration par XML, le code ne compilera pas si vous vous êtes trompé dans votre tissage de dépendances. Par contre c’est bien du couplage lâche car on peut utiliser une interface. Pas de référence à l’implémentation.
Ok mais si on a plus de XML, ne risque-t-on pas avec CDI de se retrouver avec 20 annotations ?
Oui mais avec une annotation on peut faire du code, utiliser un Enum par exemple.
On peut faire de l’injection sur les Fields, sur les constructeurs, et par setters. Par contre un seul constructeur peut être annoté, logique.
Jusqu’ici nous n’avons pas vu d’XML. CDI c’est clairement une autre approche, plus proche du métal. Les alternatives sont des classes annotées @Alternative utilisés par exemple pour faire un mock.
Les alternatives ne sont pas activés par défaut. Dans le beans.xml on active explicitement une alternative pour par exemple faire passer des tests unitaires et d’intégrations.
Enfin on peut déclarer des @Stereotype pour avoir un seul Mock @Alternative. A travers les différents exemples de code, l’ensemble est assez simple et facile à lire. Vous pouvez aller assez loin, comme déclarer par exemples des Stereotypes afin de modéliser des comportements communs et récurrents dans votre application.
Enfin il est aussi possible d’injecter autre chose que des Beans. Par exemple on peut injecter une String. Imaginez un générateur d’identifiant unique par exemple. Antonio montre du code, l’utilisation d’annotations de son projet pour renforcer le typage lors de l’injection. Sympa.
@Produces @ThirteenDigits
On peut donc vraiment injecter tout dans tout avec CDI.
Pour terminer, CDI ce n’est pas que de l’injection de dépendance. Vous pouvez aussi aller plus loin et déclarer des intercepteurs (à la AOP) avec l’annotation @AroundAvoke. Ces intercepteurs ne sont pas activés par défaut, vous lez activez via le fichier beans.xml. Ces intercepteurs sont intéressants car cela permet d’appliquer le pattern Decorator sur son code, et de l’outiller de l’exterieur.
Enfin pour ce qui est des implémentations de référence, nous avons pour l’instant :
– Weld par Redhat JBoss, implémentation de référence de la spécification CDI.
– CanDI est l’implémentation de Caucho Resin 4.0
Que faut-il retenir de CDI ?
– Plus simple et plus fortement typé dans l’approche que l’approche Spring+XML.
– Prêt à être utilisé en production.
– Relativement simple
– Fonctionne aussi dans des conteneurs légers comme Apache Tomcat et sans doute avec le Web Profile
– Intéressant pour les applications d’entreprise basées sur JEE6.
Pour le reste, Antonio a montré beaucoup de code, et retranscrire là en direct live était impossible. Si vous avez l’occasion de le voir à une conférence, allez voir CDI pour vous faire une idée de ce que l’on peut faire avec.
Bonjour touilleur,
@introduction
@deception
quelle déception: dans un temps non lointain, j’avais plaisir à lire ces articles techniques et critiques mais depuis un certain temps tout à changer.
@play
@Spring(version=roots)
@CDI(année zéro)
On rentre dans le monde du Play! et on ne parle que de ça: la planète peut s’arrêter de tourner, Play! continuera et la quantité d’autres outils passent à la trappe. Puis on découvre CDI et rebelote: c’est le meilleur outil du monde, oubliant des années d’utilisation de Spring et à quel point ce framework a permis de sauver la langage Java. Il reste d’ailleurs encore aujourd’hui beaucoup facile à utiliser que CDI.
@Courage
Maintenant que ton blog est devenu une référence, le challenge est difficile à relever mais j’ai confiance: garde ton indépendance, reste libre !
Bon vent
@salutations
@Eric merci. Si j’écrivais dans un magazine informatique, et que j’avais la prétention d’être journaliste, je pourrai être objectif et indépendant. Un blog au contraire, c’est complètement subjectif, engagé et passionné.
J’ai trouvé que CDI proposait ce qui manquait dans la stack Java, et que Spring avait comblé. CDI c’est Spring IoC et Dependency Injection. Par contre, ce n’est pas Spring Webflow, Spring Faces, Spring Security et d’autres outils de Spring qui sont, et qui restent encore, d’excellents outils.
Est-ce que ça va mieux ?
Ca va mieux mais je n’aime toujours pas CDI 😉
En fait la spec JSR-330, c’est juste une javadoc!
Sauf que CDI n’applique pas vraiment strategy, c’est une super factory.
Injection de map : pas possible,
injection de liste : assez limité (pas de controle sur l’ordre).
impossible d’avoir n instances d’une meme classes construites avec des injections différentes. factory!=strategy.
J’ai posé un message là dessus sur le forum weld, qui confirme un peu tout ça : http://seamframework.org/143579.lace
Y a que le xml qui permet de gérer des injections non devinables d’après le code, le zero-xml est un peu dogmatique je trouve. Du coup on se retrouve à ce que CDI ne propose pas ce que Spring propose depuis la version 1.0 et qui sert vraiment dans des applications d’entreprises réelles.
Mais bon, on fait avec et c’est joli quand meme, par contre sur un EJB la gestion de l’état devient un peu curieuse puisqu’on a des annotations EJB et des annotations CDI.
Sinon sur JSR 330 on peut quand meme avoir toutes les injections (qualifier, injection de liste meme si c’est pas avec Instance, etc…) à l’exception des @Produce et des @Alternative, certes.