Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 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) Jul 2018 CDI 2.0 SP1 (Bugfix)

Slide 4

Slide 4 text

CanDI

Slide 5

Slide 5 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 6

Slide 6 text

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

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Events

Slide 9

Slide 9 text

@Observes

Slide 10

Slide 10 text

@ObservesAsync

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

@Priority

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

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

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 23

Slide 23 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 24

Slide 24 text

Java SE

Slide 25

Slide 25 text

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

Slide 26

Slide 26 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 27

Slide 27 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 28

Slide 28 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 29

Slide 29 text

Portable Extensions

Slide 30

Slide 30 text

SPI

Slide 31

Slide 31 text

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

Slide 32

Slide 32 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 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Proxy matters

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Proxy injection

Slide 43

Slide 43 text

Proxy injection

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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