CDI 2.0

C5f6e8dffbb19acf405198c8fb917337?s=47 Mark Paluch
September 07, 2017

CDI 2.0

Contexts and Dependency Injection has become an integral part of Java to leverage dependency injection and bean management aside of EJB. The current CDI 1.2 is widely used amongst Java Enterprise 7 applications. The Expert Group formed in Fall 2014 to work on the next version of the specification and released the CDI 2.0 spec in early 2017, which will be part of Java Enterprise 8.

Links:
* Code: https://github.com/mp911de/cdi-2.0

C5f6e8dffbb19acf405198c8fb917337?s=128

Mark Paluch

September 07, 2017
Tweet

Transcript

  1. What's New in CDI 2.0 JSR 365 Mark Paluch •

    @mp911de
  2. CDI Timeline Dec 2009 CDI 1.0 (Java EE 6) Jun

    2013 CDI 1.1 (Java EE 7) Apr 2014 CDI 1.2 (M R) Sep 2014 CDI 2.0 (Kickoff) May 2017 CDI 2.0 (Release) Sept 2017? Java EE 8
  3. CanDI

  4. Community Survey 1. Asynchronous method invocation 2. Add asynchronous event

    support 3. @Startup for CDI 4. Bootstrapping the container outside Java EE 5. AOP for produced or custom beans
 6. Mutable container at runtime 7. Security support 8. Observers ordering 9. Enhance SPI to give better access to all metadata 10. Better EAR support Source: https://jcp.org/aboutJava/communityprocess/ec-public/materials/2015-06-1516/JSR-365-Review.pdf
  5. @ApplicationScoped class UserService { User createUser() { return …; }

    } class UserServlet extends HttpServlet { @Inject UserService service; }
  6. @ApplicationScoped class UserService { void onUserCreated(@Observes UserEvent event) { }

    } class UserServlet extends HttpServlet { @Inject UserService service; } class UserServiceFactory { @Produces @ApplicationScoped UserService createService() { return new UserService(); } }
  7. Road towards JavaEE 8 • Java 8 baseline • Spec

    split: Core/SE/EE CDI Specification CDI Core CDI for Java SE CDI for Java EE
  8. Java SE

  9. Java SE • Currently: Implementation-specific in Weld/ OpenWebBean • Spec

    Goal: Bootstrap API
  10. SeContainerInitializer initializer = SeContainerInitializer .newInstance()
 .disableDiscovery()
 .addBeanClasses(MyApp.class)
 .addPackages(MyOtherServices.class)
 .addExtensions(MyExtension.class);
 


    try (SeContainer container = initializer.initialize()) {
 
 MyApp service = container.select(MyService.class).get();
 service.runMyApplication();
 }
  11. SeContainerInitializer initializer = SeContainerInitializer .newInstance()
 .disableDiscovery()
 .addBeanClasses(MyApp.class)
 .addPackages(MyOtherServices.class)
 .addExtensions(MyExtension.class);
 


    try (SeContainer container = initializer.initialize()) {
 
 MyApp service = container.select(MyService.class).get();
 service.runMyApplication();
 }
  12. SeContainerInitializer initializer = SeContainerInitializer .newInstance()
 .disableDiscovery()
 .addBeanClasses(MyApp.class)
 .addPackages(MyOtherServices.class)
 .addExtensions(MyExtension.class);
 


    try (SeContainer container = initializer.initialize()) {
 
 MyApp service = container.select(MyService.class).get();
 service.runMyApplication();
 }
  13. Events

  14. @Observes

  15. @Priority

  16. Ordered Events • Add @Priority to event observers • Aids

    observer ordering • Total global order determined when the event is fired
  17. Observer Ordering public void observer(@Observes @Priority(2500) MyEvent event) {
 System.out.println("Default

    priority");
 }
  18. public void earlier(@Observes @Priority(2499) MyEvent event) {
 // yay! I'm

    first
 System.out.println("Notified before all other observers");
 }
 public void observer(@Observes MyEvent event) {
 System.out.println("Default priority");
 } public void later(@Observes @Priority(2501) MyEvent event) {
 System.out.println("Notified after all other observers");
 }
  19. public void earlier(@Observes @Priority(2499) MyEvent event) {
 // yay! I'm

    first
 System.out.println("Notified before all other observers");
 }
 public void observer(@Observes MyEvent event) {
 System.out.println("Default priority");
 } public void later(@Observes @Priority(2501) MyEvent event) {
 System.out.println("Notified after all other observers");
 }
  20. public void earlier(@Observes @Priority(2499) MyEvent event) {
 // yay! I'm

    first
 System.out.println("Notified before all other observers");
 }
 public void observer(@Observes MyEvent event) {
 System.out.println("Default priority");
 } public void later(@Observes @Priority(2501) MyEvent event) {
 System.out.println("Notified after all other observers");
 }
  21. public void earlier(@Observes @Priority(2499) MyEvent event) {
 // yay! I'm

    first
 System.out.println("Notified before all other observers");
 }
 public void observer(@Observes MyEvent event) {
 System.out.println("Default priority");
 } public void later(@Observes @Priority(2501) MyEvent event) {
 System.out.println("Notified after all other observers");
 }
  22. @ObservesAsync

  23. Asynchronous Events • Notify event observers asynchronously • One or

    more different threads • Decoupled from synchronous events
  24. Firing Async Events @Inject
 private Event<MyEventPayload> event;
 public void triggerEvent()

    {
 event.fireAsync(new MyEventPayload());
 }
  25. Firing Async Events @Inject
 private Event<MyEventPayload> event;
 public void triggerEvent()

    {
 event.fireAsync(new MyEventPayload());
 }
  26. Observing Async Events public void observer(@ObservesAsync MyEvent payload) {
 System.out.println("Yay,

    I'm called async!");
 }
  27. How it works @Observes @ObservesAsync event.fire(…) Sync call Not notified

    event.fireAsync(…) Not notified Async call
  28. Asynchronous Events • Exceptions and Synchronization with CompletionStage • Active

    scopes: Request, Application • Custom scopes depend on the implementation
  29. Portable Extensions

  30. Meta-Data Builder API • Standardized API • CDI 1.0+: Very

    verbose to create • AnnotatedTypes, Beans, BeanAttributes, InjectionPoints, and ObserverMethods • Builder and Configurator-style
  31. class AfterBeanDiscoveryExtension implements Extension {
 void afterBeanDiscovery( @Observes AfterBeanDiscovery event)

    {
 event.addBean() .types(MyService.class) .scope(RequestScoped.class) .createWith(ctx -> …) .name("myservice"); } } Add a Bean
  32. class AfterBeanDiscoveryExtension implements Extension {
 void afterBeanDiscovery( @Observes AfterBeanDiscovery event)

    {
 event.addBean() .types(MyService.class) .scope(RequestScoped.class) .createWith(ctx -> …) .name("myservice"); } } Add a Bean
  33. class ProcessAnnotatedTypeExtension implements Extension {
 <T> void processAnnotatedType(@Observes @WithAnnotations(UseCase.class) ProcessAnnotatedType<T>

    pat) {
 
 pat.configureAnnotatedType() .methods() 
 .forEach(m -> m.add(CacheableLiteral.INSTANCE));
 } } Add annotation to Methods
  34. class ProcessAnnotatedTypeExtension implements Extension {
 <T> void processAnnotatedType(@Observes @WithAnnotations(UseCase.class) ProcessAnnotatedType<T>

    pat) {
 
 pat.configureAnnotatedType() .methods() 
 .forEach(m -> m.add(CacheableLiteral.INSTANCE));
 } } Add annotation to Methods
  35. AOP on produced Bean • CDI 1.0+: Interceptor applied to

    producer method • CDI 2.0: InterceptionFactory @Produces 
 @Transactional
 public MyService produceService() {
 ... 
 }
  36. AOP on produced Bean @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionFactory<MyService> ify)

    {
 
 ify.configure()
 .filterMethods(m -> m.getJavaMember().getName().equals("save"))
 .forEach(m -> m.add(new AnnotationLiteral<Transactional>() {}));
 
 return ify.createInterceptionProxy(new MyService());
 }
  37. AOP on produced Bean @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionFactory<MyService> ify)

    {
 
 ify.configure()
 .filterMethods(m -> m.getJavaMember().getName().equals("save"))
 .forEach(m -> m.add(new AnnotationLiteral<Transactional>() {}));
 
 return ify.createInterceptionProxy(new MyService());
 }
  38. Proxy matters

  39. Proxy injection @Inject
 private MyService myService; This is a proxy

    instance
  40. Proxy injection @Inject @Named("myBean")
 private ConcurrentHashMap<String, String> myService; /** Implementation

    for put and putIfAbsent */
 final V putVal(K key, V value, boolean onlyIfAbsent)
  41. Normal-scoped beans • Must be proxyable • accessible, no-args constructor

    • non-final classes • accessible, non-final instance methods
  42. Enabling proxying @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionFactory<MyService> ify) {
 


    ify.ignoreFinalMethods(); 
 return ify.createInterceptedInstance(new MyService());
 }
  43. Enabling proxying @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionFactory<MyService> ify) {
 


    ify.ignoreFinalMethods(); 
 return ify.createInterceptedInstance(new MyService());
 }
  44. Wrap-up • Baseline to Java 8, part of Java EE

    8 • Weld 3.0 (May 2017) • OpenWebBeans 3.0 (July 2017) • Major changes in Java SE, Events, SPI
  45. Get in touch Slides – Speakerdeck(mp911.de/cdi-20) Code: github.com/mp911de/cdi-2.0 Web: cdi-spec.org

    Mailing list: cdi-dev@lists.jboss.org IRC: irc://freenode.net/#cdi-dev Twitter: @cdispec // @mp911de Github: github.com/cdi-spec CDI 2.0 JCP page: jcp.org/en/jsr/summary?id=365