Upgrade to Pro — share decks privately, control downloads, hide ads and more …

@Inject everywhere

@Inject everywhere

Présentation de CDI et de ses extensions au BreizhJUG le 1er février 2012

mathieuancelin

May 22, 2012
Tweet

More Decks by mathieuancelin

Other Decks in Programming

Transcript

  1. Mathieu ANCELIN • Ingénieur d’étude @SERLI • Java & OSS

    • JOnAS, GlassFish, Weld, etc ... • Poitou-Charentes JUG • Membre de l’expert group CDI 1.1 (JSR-346) • @TrevorReznik
  2. Evènements CDI • Modèle d’évènement intégré basé sur le pattern

    Observer • Un ‘producteur’ d’évènements • Un ou plusieurs consommateurs • Sélection des cibles grâce aux types d’évènements et aux qualifiers •Système synchrone !!!
  3. Evènements CDI @Inject Event<String> evt; @Inject Event<Message> evtMess; evt.fire("Hello World");

    evtMess.fire(new Message("Hello")); public void listenAllStrings(@Observes String evt) { } public void listenAllMessages(@Observes Message message) { }
  4. Evènements CDI @Inject @Old Event<String> evt; evt.fire("Hello Old Man"); public

    void listenOldString(@Observes @Old String evt) { }
  5. Evènements CDI @Inject @Old @For(Person.JOHN_DOE) Event<String> evt; evt.fire("Hello Old John

    Doe"); public void listenAllString(@Observes String evt) { } public void listenOldString(@Observes @Old String evt) { } public void listenOldStringForJohnDoe(@Observes @Old @For(Person.JOHN_DOE) String evt) { }
  6. Evènements CDI public class Configuration { public boolean loggingEnabled =

    false; public boolean someOptimizationEnabled = false; public boolean someStuffEnabled = false; }
  7. Evènements CDI public class Configuration { public boolean loggingEnabled =

    false; public boolean someOptimizationEnabled = false; public boolean someStuffEnabled = false; } @Inject Event<Configuration> configEvt; public void customConfiguration() { Configuration config = new Configuration(); configEvent.fire(configuration); }
  8. Evènements CDI public class Configuration { public boolean loggingEnabled =

    false; public boolean someOptimizationEnabled = false; public boolean someStuffEnabled = false; } public void configure(@Observes Configuration configuration) { configuration.loggingEnabled = true; configuration.someStuffEnabled = true; } @Inject Event<Configuration> configEvt; public void customConfiguration() { Configuration config = new Configuration(); configEvent.fire(configuration); }
  9. Evènements CDI if (config.loggingEnabled) { /** Do stuff **/ }

    if (config.someOptimizationEnabled) { /** Do stuff **/ } if (config.someStuffEnabled) { /** Do stuff **/ } public class Configuration { public boolean loggingEnabled = false; public boolean someOptimizationEnabled = false; public boolean someStuffEnabled = false; } public void configure(@Observes Configuration configuration) { configuration.loggingEnabled = true; configuration.someStuffEnabled = true; } @Inject Event<Configuration> configEvt; public void customConfiguration() { Configuration config = new Configuration(); configEvent.fire(configuration); }
  10. Extensions CDI • Première spécification à fournir un moyen permettant

    d’étendre Java EE de façon standard • API d’extension permettant de : • Ajouter/Supprimer des beans • Ajouter un scope • Modifier les méta-données d’un bean • Remplir des points d’injection • etc ...
  11. • Basé sur le pattern Service Provider Interface • Implémenter

    l’interface (vide) Extension • Observer les évènements provenant du conteneur pour modifier le déploiement • Enregistrer l’extension • Ajouter un fichier META-INF/services/ javax.enterprise.inject.spi.Extension contenant le nom complet de la classe d’extension Comment ça marche ?
  12. Evènements observables • BeforeBeanDiscovery • ProcessAnnotatedType • ProcessInjectionTarget • ProcessBean

    • ProcessObserverMethod • ProcessProducer • AfterBeanDiscovery • AfterDeploymentValidation • BeforeShutDown
  13. Types d’extensions • Extension purement orientée outillage • cdi-aop •

    Extension d’intégration • cdi-actors • Extension Runtime • play-cdi public class AOPConfig { public void configure(@Observes AOPConfigEvent config) { config.add( intercept(Service.class) .onAllMethodsReturning(String.class) ); } } public void intercept(@Observes @Return(String.class) @MethodName("doSomething") @MethodAnnotated(CutHere.class) Before before) { if (getHourOfTheDay() == 0) { before.preventAndReturn( "Impossible d'utiliser cette méthode maintenant"); } else { logger.info("Méthode " + before.getMethod() + " accédée par " + before.getParameter(0)); } }
  14. Types d’extensions • Extension purement orientée outillage • cdi-aop •

    Extension d’intégration • cdi-actors • Extension Runtime
  15. Types d’extensions @Inject @To(actor=Master.class) ActorEvent<Calculate> master; master.fire(new Calculate(4, 10000, 10000));

    @ActorConfig("master") @ApplicationScoped public static class Master extends CDIActor { public void listenCalculate(@Observes Calculate message) { ... } }
  16. Types d’extensions • Extension purement orientée outillage • cdi-aop •

    Extension d’intégration • cdi-actors • Extension Runtime • play-cdi
  17. Types d’extensions public class Application extends Controller { @Inject static

    MyBean myBean; public static void index() { myBean.currentUserId = session.get("id"); DataFromSomewhere data = myBean.getData(); render(data); } } @RequestScoped public class MyBean { @Inject @FromWS DataClient; public String currentUserId; public DataFromSomewhere getData() { ... } }
  18. JBoss Weld • Implémentation de référence de CDI 1 et

    CDI 1.1 (construit en parallèle de la spec.) • Projet plutôt mature • Utilisé dans plusieurs serveurs d’applications • Bonne communauté, réactive • Gros travail d’évangélisation JBoss
  19. OpenWebBeans • Implémentation open-source Apache • Utilisé dans Géronimo et

    TomEE • Projet semble mature • mais utilisation ? • Contributeurs très impliqués dans CDI
  20. CanDI • Implémentation Caucho • Utilisée dans Resin • En

    tant qu’implémentation CDI pour les utilisateurs • En interne dans le serveur d’application
  21. JBoss Seam • Solder • Cron Module • Faces Module

    • Errai CDI • International Module • JMS Module • Mail Module • Persistence Module • Remoting Module • Reports Module • REST Module • Security Module • Social Module • Spring Module • Validation Module • Wicket Module
  22. Apache DeltaSpike • Extensions portables CDI • Projet permettant d’unifier

    les efforts autour des extensions CDI • JBoss Seam 3 • MyFaces CODI • CDISource • Créer un standard de-facto maintenu par la communauté Java • Environnement de test basé sur Arquillian
  23. Java SE • Bootstrapper un conteneur CDI dans un environnement

    Java SE • Problématiques • Déploiement des beans • Lookup des beans • Solutions propriétaires • Weld-SE, OWB - CanDI ?
  24. Java SE public class NumberGuessFrame extends javax.swing.JFrame { @Inject Game

    game; @Inject MessageGenerator msgGenerator; public void start(@Observes ContainerInitialized event) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { initComponents(); setVisible(true); } }); } } main-class: org.jboss.weld.environment.se.StartMain
  25. Java SE Weld weld = new Weld(); WeldContainer container =

    weld.initialize(); Instance<Object> instance = container.instance(); instance.select(Mybean.class).get();
  26. Servlet • Bootstrapper un conteneur CDI dans un conteneur de

    Servlets • Possibilités existantes : • Weld-Servlet • Intégration JSF • Seam-Solder • OWB servlet plugin • CanDI ?
  27. Servlet • Injection dans les servlets • HttpSession, HttpRequest, HttpResponse

    • RequestParam, Context, Cookies, Cookie-params, Principal • Ajout de quelques filtres et listeners dans le web.xml si • Pas de configuration si environnement servlet 3.0 • Events bridge • Servlet lifecycle, etc ...
  28. OSGi • Projet Weld-OSGi : OSGi sans se prendre la

    tête • Le meilleur des deux mondes • dynamique, typesafe, annotations, etc ... • Extension CDI pour utiliser le modèle de programmation CDI dans un environnement OSGi • Développé par l’équipe R&D de SERLI • A la demande de l’équipe JBoss Weld • Faire disparaitre le modèle de programmation OSGi au profit du standard CDI (mais compatible) • Pas besoin de connaître OSGi
  29. OSGi • Une super plateforme pour créer des applications Java

    dynamiques et modulaires • Très stable et mature mais les APIs datent un peu Modules Cycle de vie Services Environnement Java Bundles
  30. Modules / Bundles manifest manifest Bundle-SymbolicName: com.foo.bar Bundle-SymbolicName: com.sample.app Export-Package:

    com.sample.app.api; version=1.2.0 Import-Package: com.sample.app.api; version=[1.2.0-2.0.0)
  31. Cycle de vie Installed Resolved Uninstalled Starting Active Stopping install

    update refresh stop start update refresh resolve uninstall uninstall
  32. CDI embarqué EmbeddedCDIContainer cdi = new EmbeddedContainer(bundleContext).initialize(); MyService service =

    cdi.instance().select(MyService.class).get(); service.doSomething(); cdi.stop();
  33. CDI embarqué ou EmbeddedCDIContainer cdi = new EmbeddedContainer(bundleContext).initialize(); MyService service

    = cdi.instance().select(MyService.class).get(); service.doSomething(); cdi.stop();
  34. CDI embarqué ou WeldContainer weld = new WeldContainer(bundleContext).initialize(); MyService service

    = weld.instance().select(MyService.class).get(); service.doSomething(); weld.stop(); EmbeddedCDIContainer cdi = new EmbeddedContainer(bundleContext).initialize(); MyService service = cdi.instance().select(MyService.class).get(); service.doSomething(); cdi.stop();
  35. CDI embarqué ou public void start(@Observes BundleContainerInitialized event) {} public

    void stop(@Observes BundleContainerShutdown event) {} WeldContainer weld = new WeldContainer(bundleContext).initialize(); MyService service = weld.instance().select(MyService.class).get(); service.doSomething(); weld.stop(); EmbeddedCDIContainer cdi = new EmbeddedContainer(bundleContext).initialize(); MyService service = cdi.instance().select(MyService.class).get(); service.doSomething(); cdi.stop();
  36. Utilitaires OSGi • Injection du bundle courant • Injection du

    bundleContext courant • Injection des/d’une méta-données courantes • Injection des fichiers spécifiques au bundle (dans le conteneur) • Autres utilitaires au fur et à mesure
  37. Utilitaires OSGi @Inject Bundle bundle; @Inject BundleContext context; @Inject @BundleHeaders

    Map<String, String> headers; @Inject @BundleHeader("Bundle-SymbolicName") String symbolicName; @Inject @BundleDataFile("text.txt") File text; • Injection du bundle courant • Injection du bundleContext courant • Injection des/d’une méta-données courantes • Injection des fichiers spécifiques au bundle (dans le conteneur) • Autres utilitaires au fur et à mesure
  38. Publication de services • Publication déclarative • Publication dynamique @Publish

    @ApplicationScoped @Lang(EN) public class MyServiceImpl implements MyService { ... } @Inject Instance<MyService> instance; @Inject ServiceRegistry registry; MyService service = instance.get(); Registration<MyService> reg = registry.register(service); ... reg.unregister();
  39. Injection de services • Injection dynamique directe @Inject @OSGiService MyService

    service; service.doSomething(); // échoue si pas de service disponible
  40. Injection de services • Injection dynamique directe @Inject @OSGiService MyService

    service; service.doSomething(); // échoue si pas de service disponible @Inject @OSGiService MyService service; P R O X Y Provider InjectionPoint create() get()
  41. Injection de services service.doSomething() P R O X Y get()

    OSGi service registry unget() actual service doSomething()
  42. Injection de services • Injection programmatique - whiteboard pattern @Inject

    Service<MyService> service; for (MyService actualService : service.first()) { actualService.doSomething(); // appelé sur 0-1 service } for (MyService actualService : service) { actualService.doSomething(); // appelé sur 0-n service(s) } service.get().doSomething(); // peut échouer, non dynamique service.size(); service.isUnsatisfied(); service.isAmbiguous();
  43. Injection de services • Injection programmatique - whiteboard pattern @Inject

    Service<MyService> service; for (MyService actualService : service.first()) { actualService.doSomething(); // appelé sur 0-1 service } for (MyService actualService : service) { actualService.doSomething(); // appelé sur 0-n service(s) } service.get().doSomething(); // peut échouer, non dynamique service.size(); service.isUnsatisfied(); service.isAmbiguous();
  44. Injection de services - filtres @Publish @Lang(EN) @Country(US) public class

    MyServiceImpl implements MyService { ... } @Inject @OSGiService @Filter("(&(lang=*)(country=US))") MyService service;
  45. Injection de services - filtres @Publish @Lang(EN) @Country(US) public class

    MyServiceImpl implements MyService { ... } @Inject @Filter("(&(lang=*)(country=US))") Service<MyService> service;
  46. Injection de services - filtres @Publish @Lang(EN) @Country(US) public class

    MyServiceImpl implements MyService { ... } @Inject @Filter("(&(lang=*)(country=US))") Service<MyService> service; @Inject @OSGiService @Lang(EN) @Country(US) MyService service;
  47. Injection de services - filtres @Publish @Lang(EN) @Country(US) public class

    MyServiceImpl implements MyService { ... } @Inject @Filter("(&(lang=*)(country=US))") Service<MyService> service; @Inject @Lang(EN) @Country(US) Service<MyService> service;
  48. Services requis • Permet de cibler l’utilisation de services uniquement

    lorsqu’ils sont disponibles • Fonctionne de façon atomique au niveau du bundle • plus tard, possibilité de cibler des services particuliers
  49. Services requis @Inject @OSGiService @Required MyService service; Weld-OSGi service registry

    public void start( @Observes Valid evt) {} public void stop( OSGi service registry listener services events required service registration dependencies validation events Bean B Bean A
  50. Services requis @Inject @OSGiService @Required MyService service; public void start(@Observes

    Valid evt) { System.out.println("service is available"); service.doSomething(); } public void stop(@Observes Invalid evt) { System.out.println("service is unavailable"); }
  51. Services requis @Inject @Required Service<MyService> service; public void start(@Observes Valid

    evt) { System.out.println("service is available"); service.get().doSomething(); } public void stop(@Observes Invalid evt) { System.out.println("service is unavailable"); }
  52. Services requis @Inject @Required Service<MyService> service; public void start(@Observes Valid

    evt) { System.out.println("service is available"); service.get().doSomething(); } public void stop(@Observes Invalid evt) { System.out.println("service is unavailable"); } bundle complet
  53. @Inject @OSGiService @Required MyService service; public void start(@Observes @Specification(MyService.class) ServiceAvailable

    evt) { System.out.println("service is available"); service.doSomething(); } public void stop(@Observes @Specification(MyService.class) ServiceUnavailable evt) { System.out.println("service is unavailable"); } Services requis
  54. @Inject @Required Service<MyService> service; public void start(@Observes @Specification(MyService.class) ServiceAvailable evt)

    { System.out.println("service is available"); service.get().doSomething(); } public void stop(@Observes @Specification(MyService.class) ServiceUnavailable evt) { System.out.println("service is unavailable"); } Services requis
  55. Evènements OSGi • OSGi génère un certains nombre d’évènements pour

    interagir avec la couche cycle de vie et la couche services • évènements bundles • évènements services
  56. Evènements OSGi - bundles • Evènements disponibles • BundleInstalled •

    BundleResolved • BundleStarting • BundleStarted • BundleStopping • BundleStopped • BundleUninstalled • BundleUpdated • BundleUnresolved Installed Resolved Uninstalled Starting Active Stopping install update refresh stop start update refresh resolve uninstall uninstall
  57. Evènements OSGi - services void bindService(@Observes ServiceArrival evt) {} •

    Evènements disponibles • ServiceArrival • ServiceDeparture • ServiceChanged
  58. Evènements OSGi - services void bindService(@Observes @Filter("(lang=US)") ServiceArrival evt) {}

    • Evènements disponibles • ServiceArrival • ServiceDeparture • ServiceChanged
  59. Evènements OSGi - services void bindService(@Observes @Specification(MyService.class) ServiceArrival evt) {}

    • Evènements disponibles • ServiceArrival • ServiceDeparture • ServiceChanged
  60. Evènements OSGi - services void bindService(@Observes @Specification(MyService.class) @Filter("(lang=US)") ServiceArrival evt)

    {} • Evènements disponibles • ServiceArrival • ServiceDeparture • ServiceChanged
  61. Communication inter-bundles • Communication entre différents bundles (gérés par Weld-OSGi)

    via le système d’évènements CDI Bundle A Bundle C Bundle B Weld-OSGi fire() broadcast() broadcast()
  62. GWT • Projet JBoss Errai (Seam) • Invocation des beans

    CDI depuis des clients GWT • Invocations RPC • Publish/Subscribe • CDI events • Exposer les modèles métier aux clients GWT (@ExposeEntity) • Injection de dépendance côté client • http://www.jboss.org/errai
  63. GWT/Errai App. Server (CDI) GWT Bus d’évènement (avec topics) Servlet

    2.5 Comet (Jetty, Grizzly, JBoss, Tomcat) Servlet 3 (Async)
  64. Invocation RPC @Service @ApplicationScoped public class AccountServiceRPC implements AccountService {

    public Fraud watchActivity( AccountActivity activity) { return new Fraud(System.currentTimeMillis()); } }
  65. Invocation RPC @Service @ApplicationScoped public class AccountServiceRPC implements AccountService {

    public Fraud watchActivity( AccountActivity activity) { return new Fraud(System.currentTimeMillis()); } }
  66. Invocation RPC public class FraudClientRPC extends LayoutPanel { @Inject Caller<AccountService>

    service; HTML responsePanel; ... @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity()); } }); ... } }
  67. Invocation RPC public class FraudClientRPC extends LayoutPanel { @Inject Caller<AccountService>

    service; HTML responsePanel; ... @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity()); } }); ... } } @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { (new AccountActivity()); } }); ... }
  68. Invocation RPC public class FraudClientRPC extends LayoutPanel { @Inject Caller<AccountService>

    service; HTML responsePanel; ... @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity()); } }); ... } } @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { (new AccountActivity()); } }); ... } service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity());
  69. Invocation RPC public class FraudClientRPC extends LayoutPanel { @Inject Caller<AccountService>

    service; HTML responsePanel; ... @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity()); } }); ... } } @PostConstruct public void buildUI() { Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { (new AccountActivity()); } }); ... } service.call(new RemoteCallback<Fraud>() { public void callback(Fraud fraud) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } }).watchActivity(new AccountActivity());
  70. Publish/Suscribe @Service @ApplicationScoped public class AccountServicePubSub implements MessageCallback { @Inject

    RequestDispatcher dispatcher; public void callback(Message activity) { MessageBuilder.createMessage() .toSubject("FraudClientPubSub") .signalling() .with("fraudTimeStamp", System.currentTimeMillis()) .noErrorHandling() .sendNowWith(dispatcher); }); } }
  71. Publish/Suscribe @Service @ApplicationScoped public class AccountServicePubSub implements MessageCallback { @Inject

    RequestDispatcher dispatcher; public void callback(Message activity) { MessageBuilder.createMessage() .toSubject("FraudClientPubSub") .signalling() .with("fraudTimeStamp", System.currentTimeMillis()) .noErrorHandling() .sendNowWith(dispatcher); }); } }
  72. Publish/Suscribe public class FraudClientRPC extends LayoutPanel { @Inject MessageBus bus;

    HTML responsePanel; @PostConstruct public void buildUI() { }
  73. Publish/Suscribe public class FraudClientRPC extends LayoutPanel { @Inject MessageBus bus;

    HTML responsePanel; @PostConstruct public void buildUI() { } bus.subscribe("BroadcastReceiver", new MessageCallback() { public void callback(CommandMessage message) { responsePanel.setText("Fraud detected: " + message.get(Long.class, "fraudTimeStamp"); } });
  74. Publish/Suscribe public class FraudClientRPC extends LayoutPanel { @Inject MessageBus bus;

    HTML responsePanel; @PostConstruct public void buildUI() { } bus.subscribe("BroadcastReceiver", new MessageCallback() { public void callback(CommandMessage message) { responsePanel.setText("Fraud detected: " + message.get(Long.class, "fraudTimeStamp"); } }); Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { MessageBuilder.createMessage() .toSubject("AccountServicePubSub") .signalling() .noErrorHandling() .sendNowWith(bus); } });
  75. Publish/Suscribe public class FraudClientRPC extends LayoutPanel { @Inject MessageBus bus;

    HTML responsePanel; @PostConstruct public void buildUI() { } bus.subscribe("BroadcastReceiver", new MessageCallback() { public void callback(CommandMessage message) { responsePanel.setText("Fraud detected: " + message.get(Long.class, "fraudTimeStamp"); } }); Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { MessageBuilder.createMessage() .toSubject("AccountServicePubSub") .signalling() .noErrorHandling() .sendNowWith(bus); } });
  76. CDI Events @ApplicationScoped public class AccountService { @Inject @Detected Event<Fraud>

    event; public void watchActivity( @Observes AccountActivity activity) { Fraud fraud = new Fraud(System.currentTimeMillis()); event.fire(fraud); } }
  77. CDI Events @ApplicationScoped public class AccountService { @Inject @Detected Event<Fraud>

    event; public void watchActivity( @Observes AccountActivity activity) { Fraud fraud = new Fraud(System.currentTimeMillis()); event.fire(fraud); } }
  78. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } @PostConstruct public void buildUI() { }
  79. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } @PostConstruct public void buildUI() { }
  80. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { event.fire(new AccountActivity()); } }); @PostConstruct public void buildUI() { }
  81. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { event.fire(new AccountActivity()); } }); @PostConstruct public void buildUI() { }
  82. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { event.fire(new AccountActivity()); } }); public void processFraud(@Observes @Detected Fraud fraudEvent) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } @PostConstruct public void buildUI() { }
  83. CDI Events public class FraudClient extends LayoutPanel { @Inject Event<AccountActivity>

    event; HTML responsePanel; ... } Button button = new Button("Create activity", new ClickHandler() { public void onClick(ClickEvent clickEvent) { event.fire(new AccountActivity()); } }); public void processFraud(@Observes @Detected Fraud fraudEvent) { responsePanel.setText("Fraud detected: " + fraudEvent.getTimestamp()); } @PostConstruct public void buildUI() { }
  84. GAE • Projet Capedwarf • Créé par Ales Justin (lead

    Weld) • Faire fonctionner CDI sur GAE • Quelques workaround pour contrer les APIs défendues • Accès aux API GAE via CDI • Utiliser les API GAE sur JBoss AS 7 • Permettre de switcher entre AS7 et GAE de manière transparente
  85. Wicket • Module Seam d’intéropérabilité avec Wicket • Fonctionnalités •

    CDI • Injection de dépendances • Scopes • Evènements CDI • Support des conversations • http://seamframework.org/Seam3/ WicketModule
  86. Wicket • L’application Wicket doit hériter de ‘org.jboss.seam.wicket.SeamWicket’ • A

    partir de ce point, l’application devient «injectable» • Possibilité d’injection une ‘Conversation’ et de la gérer manuellement
  87. Spring • Module Seam d’intéropérabilité avec Spring • Fonctionnalités •

    Bootstrap de context Spring (SE et Web) • Utilisation de beans Spring depuis CDI • Utilisation de beans CDI depuis Spring • Bridge Spring Security • Bridge CDI events • http://seamframework.org/Seam3/SpringModule
  88. public class SpringProducer { @Produces @SpringContext @Web ApplicationContext context; @Produces

    @SpringContext @Configuration(locations = "classpath*:applicationContext.xml") ApplicationContext context; @Produces @SpringBean(fromContext = "context2") SimpleBean simpleBean; @Produces @SpringBean ComplicatedBean complicatedBean; } Spring
  89. public class SpringProducer { @Produces @SpringContext @Web ApplicationContext context; @Produces

    @SpringContext @Configuration(locations = "classpath*:applicationContext.xml") ApplicationContext context; @Produces @SpringBean(fromContext = "context2") SimpleBean simpleBean; @Produces @SpringBean ComplicatedBean complicatedBean; } Spring
  90. Spring <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cdi="http://www.jboss.org/schema/seam/spring" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.jboss.org/schema/seam/spring http://www.jboss.org/schema/seam/spring/seam-spring.xsd"> <cdi:bean-reference

    id="cdiBean" type="org.jboss.seam.spring.test.injection.CdiBean"/> <cdi:bean-reference id="thirdCdiBean" type="org.jboss.seam.spring.test.injection.ThirdCdiBean"> <cdi:qualifier type="org.jboss.seam.spring.test.injection.CdiQualifierWithAttributes"> <cdi:attribute name="name" value="myBean"/> </cdi:qualifier> </cdi:bean-reference> </beans>
  91. Spring <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cdi="http://www.jboss.org/schema/seam/spring" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.jboss.org/schema/seam/spring http://www.jboss.org/schema/seam/spring/seam-spring.xsd"> <cdi:bean-reference

    id="cdiBean" type="org.jboss.seam.spring.test.injection.CdiBean"/> <cdi:bean-reference id="thirdCdiBean" type="org.jboss.seam.spring.test.injection.ThirdCdiBean"> <cdi:qualifier type="org.jboss.seam.spring.test.injection.CdiQualifierWithAttributes"> <cdi:attribute name="name" value="myBean"/> </cdi:qualifier> </cdi:bean-reference> </beans>
  92. Spring <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cdi="http://www.jboss.org/schema/seam/spring" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.jboss.org/schema/seam/spring http://www.jboss.org/schema/seam/spring/seam-spring.xsd"> <cdi:bean-reference

    id="cdiBean" type="org.jboss.seam.spring.test.injection.CdiBean"/> <cdi:bean-reference id="thirdCdiBean" type="org.jboss.seam.spring.test.injection.ThirdCdiBean"> <cdi:qualifier type="org.jboss.seam.spring.test.injection.CdiQualifierWithAttributes"> <cdi:attribute name="name" value="myBean"/> </cdi:qualifier> </cdi:bean-reference> </beans>
  93. Ruby • Projet Torquebox • JRuby au dessus de JBoss

    AS 7 • Support de Rack, Rails, Sinatra, etc ... • Interopérable avec les features Java EE • Transactions, JMS, Cache, Session, Jobs • CDI, Resources injection, Authentication
  94. Ruby @ApplicationScoped public class TwitterClient { @Inject Twitter twitter; private

    List<User> users; private List<Status> statuses; private QueryResult search; public void loadTweets() throws TwitterException { statuses = twitter.getFriendsTimeline(); } public void loadFriends() throws TwitterException { IDs followersIDs = twitter.getFollowersIDs(-1); users = twitter.lookupUsers(followersIDs.getIDs()); } public void loadSearch() throws TwitterException { Query query = new Query("#BreizhJUG"); search = twitter.search(query); } // getters }
  95. Ruby class WelcomeController < ActionController::Base protect_from_forgery include TorqueBox::Injectors include_class "com.foo.bar.TwitterClient"

    def index @rails_msg = "Hello from Rails!" end end def followers twitter = inject(com.foo.bar.TwitterClient) @twitter_followers = twitter.get_users end
  96. Ruby class WelcomeController < ActionController::Base protect_from_forgery include TorqueBox::Injectors include_class "com.foo.bar.TwitterClient"

    def index @rails_msg = "Hello from Rails!" end end def search twitter = inject(com.foo.bar.TwitterClient) @twitter_search = twitter.get_search end def followers twitter = inject(com.foo.bar.TwitterClient) @twitter_followers = twitter.get_users end
  97. Ruby class WelcomeController < ActionController::Base protect_from_forgery include TorqueBox::Injectors include_class "com.foo.bar.TwitterClient"

    def index @rails_msg = "Hello from Rails!" end end def search twitter = inject(com.foo.bar.TwitterClient) @twitter_search = twitter.get_search end def followers twitter = inject(com.foo.bar.TwitterClient) @twitter_followers = twitter.get_users end def tweets twitter = inject(com.foo.bar.TwitterClient) @twitter_tweets = twitter.get_statuses end
  98. Ruby class WelcomeController < ActionController::Base protect_from_forgery include TorqueBox::Injectors include_class "com.foo.bar.TwitterClient"

    def index @rails_msg = "Hello from Rails!" end end def search twitter = inject(com.foo.bar.TwitterClient) @twitter_search = twitter.get_search end def followers twitter = inject(com.foo.bar.TwitterClient) @twitter_followers = twitter.get_users end def tweets twitter = inject(com.foo.bar.TwitterClient) @twitter_tweets = twitter.get_statuses end
  99. Autre ? • Il est assez simple de supporter un

    nouvel environnement • Deux «parties» nécessaires • Bootstrap du container et déploiement des classes/beans • Spécifique à l’implémentation • Devrait être standardisé • Extension CDI • Lien avec l’environnement (uni/bi-directionnel)
  100. @Inject • Guice (version Android, RoboGuice) • Implémentation de référence

    JSR-330 • Spring (depuis version 3.0) • Tapestry IoC • PicoContainer • JBoss MicroContainer • Eclipse E4 • ...
  101. CDI 1.1 • Tout est sur github :-) • Conteneur

    embarquable et lookup externe • TODO : boot, bean deployment • Ordre des intercepteurs • ProcessModule, ProcessInjectionPoint • Exclusion déclarative des beans • Service handlers • Lifecycle events • Injection statique et des enums
  102. Conclusion • CDI c’est cool ;-) • Pas seulement réservé

    à Java EE • Peut fonctionner n’importe où • C’est standard (quasiment) • Préférez le à d’autres solutions • Modèle de programmation commun