What's new in CDI 2.0 (Øredev 2016)

What's new in CDI 2.0 (Øredev 2016)

Slides of the talk I gave at Øredev, 2016.

C5f6e8dffbb19acf405198c8fb917337?s=128

Mark Paluch

November 09, 2016
Tweet

Transcript

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

    @mp911de Tweet your questions: #cdi2oredev
  2. Mark Paluch @mp911de ‣Software Craftsman ‣Spring Data Engineer @ Pivotal

    ‣EG for CDI 2.0 (JSR365)
  3. 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) Q1/2017 CDI 2.0 (Release)
  4. CanDI

  5. Road towards JavaEE 8 • Java 8 baseline • Spec

    split: Core/SE/EE CDI Specification CDI Core CDI for Java SE CDI for Java EE
  6. Events

  7. @Observes

  8. @ObservesAsync

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

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

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

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

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

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

    scopes: Request, Application • Custom scopes depend on the implementation
  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. Java SE

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

    Goal: Bootstrap API
  24. 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();
 }
  25. 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();
 }
  26. 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();
 }
  27. Portable Extensions

  28. SPI

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

    verbose to create • AnnotatedTypes, Beans, BeanAttributes, InjectionPoints, and ObserverMethods • Builder and Configurator-style
  30. public class MyExtension {
 public void afterBeanDiscovery( @Observes AfterBeanDiscovery event)

    {
 event.addBean() .beanClass(MyService.class) .scope(RequestScoped.class) .name("myservice"); } } Add a Bean
  31. public class MyExtension {
 public void afterBeanDiscovery( @Observes AfterBeanDiscovery event)

    {
 event.addBean() .beanClass(MyService.class) .scope(RequestScoped.class) .name("myservice"); } } Add a Bean
  32. public class MyExtension {
 public <T> void processAnnotatedType(@Observes @WithAnnotations(UseCase.class) ProcessAnnotatedType<T>

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

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

    producer method • InterceptionProxyFactory a possible answer @Produces 
 @Transactional
 public MyService produceService() {
 ... 
 }
  35. AOP on produced Bean @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionProxyFactory<MyService> ipf)

    {
 
 ipf.configure()
 .filterMethods(m -> m.getJavaMember().getName().equals("save"))
 .findFirst()
 .ifPresent(m -> m.add(new AnnotationLiteral<Transactional>() {}));
 
 return ipf.createInterceptionProxy(new MyService());
 }
  36. AOP on produced Bean @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionProxyFactory<MyService> ipf)

    {
 
 ipf.configure()
 .filterMethods(m -> m.getJavaMember().getName().equals("save"))
 .findFirst()
 .ifPresent(m -> m.add(new AnnotationLiteral<Transactional>() {}));
 
 return ipf.createInterceptionProxy(new MyService());
 }
  37. Proxy matters

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

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

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

    • non-final classes • accessible, non-final instance methods
  41. Enabling proxying @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionProxyFactory<MyService> ipf) {
 


    ipf.ignoreFinalMethods(); 
 return ipf.createInterceptionProxy(new MyService());
 }
  42. Enabling proxying @Produces
 @RequestScoped
 public MyService createTransactional(InterceptionProxyFactory<MyService> ipf) {
 


    ipf.ignoreFinalMethods(); 
 return ipf.createInterceptionProxy(new MyService());
 }
  43. Get in touch Slides – Speakerdeck(mp911.de/cdi2oredev) 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