Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

CanDI

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

@ApplicationScoped class UserService { User createUser() { return …; } } class UserServlet extends HttpServlet { @Inject UserService service; }

Slide 6

Slide 6 text

@ApplicationScoped class UserService { void onUserCreated(@Observes UserEvent event) { } } class UserServlet extends HttpServlet { @Inject UserService service; } class UserServiceFactory { @Produces @ApplicationScoped UserService createService() { return new UserService(); } }

Slide 7

Slide 7 text

Road towards JavaEE 8 • Java 8 baseline • Spec split: Core/SE/EE CDI Specification CDI Core CDI for Java SE CDI for Java EE

Slide 8

Slide 8 text

Java SE

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Events

Slide 14

Slide 14 text

@Observes

Slide 15

Slide 15 text

@Priority

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

Observer Ordering public void observer(@Observes @Priority(2500) MyEvent event) {
 System.out.println("Default priority");
 }

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

@ObservesAsync

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Observing Async Events public void observer(@ObservesAsync MyEvent payload) {
 System.out.println("Yay, I'm called async!");
 }

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Portable Extensions

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

AOP on produced Bean • CDI 1.0+: Interceptor applied to producer method • CDI 2.0: InterceptionFactory @Produces 
 @Transactional
 public MyService produceService() {
 ... 
 }

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

Proxy matters

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Proxy injection @Inject @Named("myBean")
 private ConcurrentHashMap myService; /** Implementation for put and putIfAbsent */
 final V putVal(K key, V value, boolean onlyIfAbsent)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Get in touch Slides – Speakerdeck(mp911.de/cdi-20) Code: github.com/mp911de/cdi-2.0 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