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

What's New in CDI 2.0 at JUG HH

Mark Paluch
November 08, 2018

What's New in CDI 2.0 at JUG HH

Slides to the talk I gave at JUG Hamburg.

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

Mark Paluch

November 08, 2018
Tweet

More Decks by Mark Paluch

Other Decks in Programming

Transcript

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

    View Slide

  2. Mark Paluch
    @mp911de
    ‣Software Craftsman
    ‣Spring Data Engineer @ Pivotal
    ‣EG for CDI 2.0 (JSR365)

    View Slide

  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)
    May 2017
    CDI 2.0
    (Release)
    Jul 2018
    CDI 2.0
    SP1 (Bugfix)

    View Slide

  4. CanDI

    View Slide

  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

    View Slide

  6. JavaEE 8 Implementations
    • IBM OpenLiberty 18
    • GlassFish 5
    • WildFly 14

    View Slide

  7. View Slide

  8. Events

    View Slide

  9. @Observes

    View Slide

  10. @ObservesAsync

    View Slide

  11. Asynchronous Events
    • Notify event observers asynchronously
    • One or more different threads
    • Decoupled from synchronous events

    View Slide

  12. Firing Async Events
    @Inject

    private Event event;

    public void triggerEvent() {

    event.fireAsync(new MyEventPayload());

    }

    View Slide

  13. Firing Async Events
    @Inject

    private Event event;

    public void triggerEvent() {

    event.fireAsync(new MyEventPayload());

    }

    View Slide

  14. Observing Async Events
    public void observer(@ObservesAsync MyEvent payload) {

    System.out.println("Yay, I'm called async!");

    }

    View Slide

  15. How it works
    @Observes @ObservesAsync
    event.fire(…)
    Sync call Not notified
    event.fireAsync(…)
    Not notified Async call

    View Slide

  16. Asynchronous Events
    • Exceptions and Synchronization with
    CompletionStage
    • Active scopes: Request, Application
    • Custom scopes depend on the implementation

    View Slide

  17. @Priority

    View Slide

  18. Ordered Events
    • Add @Priority to event observers
    • Aids observer ordering
    • Total global order determined when the event is fired

    View Slide

  19. Observer Ordering
    public void observer(@Observes @Priority(2500) MyEvent event) {

    System.out.println("Default priority");

    }

    View Slide

  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");

    }

    View Slide

  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");

    }

    View Slide

  22. 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");

    }

    View Slide

  23. 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");

    }

    View Slide

  24. Java SE

    View Slide

  25. Java SE
    • Currently: Implementation-specific in Weld/
    OpenWebBean
    • Spec Goal: Bootstrap API

    View Slide

  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();

    }

    View Slide

  27. 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();

    }

    View Slide

  28. 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();

    }

    View Slide

  29. Portable Extensions

    View Slide

  30. SPI

    View Slide

  31. CDI Extensions
    • http://www.cdi-spec.org/
    ecosystem/

    View Slide

  32. Meta-Data Builder API
    • Standardized API
    • CDI 1.0+: Very verbose to create
    • AnnotatedTypes, Beans, BeanAttributes, InjectionPoints, and
    ObserverMethods
    • Builder and Configurator-style

    View Slide

  33. public class MyExtension {

    public void afterBeanDiscovery(
    @Observes AfterBeanDiscovery event) {

    event.addBean()
    .beanClass(MyService.class)
    .scope(RequestScoped.class)
    .name("myservice");
    }
    }
    Add a Bean

    View Slide

  34. public class MyExtension {

    public void afterBeanDiscovery(
    @Observes AfterBeanDiscovery event) {

    event.addBean()
    .beanClass(MyService.class)
    .scope(RequestScoped.class)
    .name("myservice");
    }
    }
    Add a Bean

    View Slide

  35. public class MyExtension {

    public void processAnnotatedType(@Observes
    @WithAnnotations(UseCase.class) ProcessAnnotatedType pat) {


    pat.configureAnnotatedType()
    .methods() 

    .forEach(m -> m.add(CacheableLiteral.INSTANCE));

    }
    }
    Add annotation to Methods

    View Slide

  36. public class MyExtension {

    public void processAnnotatedType(@Observes
    @WithAnnotations(UseCase.class) ProcessAnnotatedType pat) {


    pat.configureAnnotatedType()
    .methods() 

    .forEach(m -> m.add(CacheableLiteral.INSTANCE));

    }
    }
    Add annotation to Methods

    View Slide

  37. AOP on produced Bean
    • CDI 1.0+: Interceptor applied to producer method
    • InterceptionFactory a possible answer
    @Produces 

    @Transactional

    public MyService produceService() {

    ... 

    }

    View Slide

  38. AOP on produced Bean
    @Produces

    @RequestScoped

    public MyService createTransactional(InterceptionFactory ipf) {


    ipf.configure()

    .filterMethods(m -> m.getJavaMember().getName().equals("save"))

    .findFirst()

    .ifPresent(m -> m.add(new AnnotationLiteral() {}));


    return ipf.createInterceptedInstance(new MyService());

    }

    View Slide

  39. AOP on produced Bean
    @Produces

    @RequestScoped

    public MyService createTransactional(InterceptionFactory ipf) {


    ipf.configure()

    .filterMethods(m -> m.getJavaMember().getName().equals("save"))

    .findFirst()

    .ifPresent(m -> m.add(new AnnotationLiteral() {}));


    return ipf.createInterceptedInstance(new MyService());

    }

    View Slide

  40. Proxy matters

    View Slide

  41. Proxy injection
    @Inject

    private MyService myService;
    This is a proxy instance

    View Slide

  42. Proxy injection

    View Slide

  43. Proxy injection

    View Slide

  44. Proxy injection
    @Inject
    @Named("myBean")

    private ConcurrentHashMap myService;
    /** Implementation for put and putIfAbsent */

    final V putVal(K key, V value, boolean onlyIfAbsent)

    View Slide

  45. Normal-scoped beans
    • Must be proxyable
    • accessible, no-args constructor
    • non-final classes
    • accessible, non-final instance methods

    View Slide

  46. Enabling proxying
    @Produces

    @RequestScoped

    public MyService createTransactional(InterceptionFactory factory) {


    factory.ignoreFinalMethods();

    return factory.createInterceptedInstance(new MyService());

    }

    View Slide

  47. Enabling proxying
    @Produces

    @RequestScoped

    public MyService createTransactional(InterceptionFactory factory) {


    factory.ignoreFinalMethods();

    return factory.createInterceptedInstance(new MyService());

    }

    View Slide

  48. Get in touch
    Web: cdi-spec.org
    Mailing list: [email protected]
    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

    View Slide