Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

CDI 2.0 is coming

907 views

Published on

New features coming in CDI 2.0, talk given during Java One 2016
- Java SE support
- Async events
- Ordered events
- Meta data configurators
- Interceptors on producers

Published in: Software

CDI 2.0 is coming

  1. 1. @antoine_sd @cdispec#CDI2 CDI II is coming Antoine Sabot-Durand Red Hat CDI spec lead
  2. 2. MicroProfile 1.0 Released! Microservice Collaboration and Innovation in the Java Community microprofilelunch.com, Thursday 11:30am - 2:00pm Learn more at microprofile.io MicroProfile BOF, Tuesday 10:30 - 11:30, Hilton Lombard Room
 (3rd tower, 6th floor)
  3. 3. @antoine_sd @cdispec#CDI2 Me, Myself and I Antoine Sabot-Durand Software Engineer at Red Hat CDI spec lead CDI evangelist Follow me: @antoine_sd Follow CDI: @cdispec
  4. 4. @antoine_sd @cdispec#CDI2 Agenda Flashback on CDI & CDI 2.0 status CDI 2.0 new features Java SE support Enhancing events Metadata configurators Interceptor and Decorators on Produced / custom beans (coming) Questions and Feedback
  5. 5. Previously on CDI
  6. 6. @antoine_sd @cdispec#CDI2 CDI Timeline Dec 2009 June 2013 Apr 2014 Sep 2014 CDI1.0 (Java EE 6) CDI1.1 (Java EE 7) CDI1.2 (1.1 MR) CDI2.0 Starts jan 2017 CDI2.0 released
  7. 7. @antoine_sd @cdispec#CDI2 CDI 1.0 - December 2009 A well-defined lifecycle for stateful objects bound to lifecycle contexts Where the set of contexts is extensible A type-safe dependency injection mechanism without verbose configuration Dependencies can be selected at development or deployment time Type-safe decorators and interceptors An event notification model An SPI allowing portable extensions to integrate cleanly with the container
  8. 8. @antoine_sd @cdispec#CDI2 CDI 1.1 / 1.2 – June 2013 / April 2014 Add automatic enablement of CDI in Java EE Add introspection with event, bean, decorator and interceptor meta data Ease access to bean manager from outside CDI with CDI class Add global enablement of interceptors using the @Priority annotation Add Unmanaged allowing easy access to non-contexutal instances Spec clarification
  9. 9. @antoine_sd @cdispec#CDI2 CDI 1.2 - April 2014 Clarification in the spec regarding: CDI Lifecycle Events Reworking Bean defining annotation to avoid conflict with other JSR 330 frameworks Clarification on conversation resolution OSGi official support in the API
  10. 10. @antoine_sd @cdispec#CDI2 CDI 2.0 status JSR 365 started in September 2014 EDR1 released in 2015 EDR2 released in august. Weld 3 Aplha 17 is the RI for EDR2 Release expected in January 2017
  11. 11. @antoine_sd @cdispec#CDI2 cdi-spec.org
  12. 12. @antoine_sd @cdispec#CDI2 CDI 2.0 new features
  13. 13. @antoine_sd @cdispec#CDI2 Java SE support using CDI outside Java EE
  14. 14. @antoine_sd @cdispec#CDI2 Java SE support - Why? To align on many other Java EE spec which support Java SE bootstrapping To boost CDI adoption for Spec and Frameworks To provide a mean of building new stacks out of Java EE
  15. 15. @antoine_sd @cdispec#CDI2 What did we do? CDI Specification CDI Core CDI for Java EECDI for Java SE
  16. 16. @antoine_sd @cdispec#CDI2 public static void main(String[] args) {
 
 SeContainer container = SeContainerInitializer.newInstance()
 .disableDiscovery()
 .addBeanClasses(MyService.class)
 .initialize();
 
 MyService service = container.select(MyService.class).get();
 
 service.sayHello();
 
 container.close();
 } Java SE bootstrap API
  17. 17. @antoine_sd @cdispec#CDI2 Enhancing events Making popular feature even more popular
  18. 18. @antoine_sd @cdispec#CDI2 Enhancing events CDI events are a very loved feature We took a very long time to see how to enhance them In CDI 2.0 we are introducing Event ordering Asynchronous events
  19. 19. @antoine_sd @cdispec#CDI2 Events ordering By adding a @Priority (from commons annotations) on an observer. The lowest value is first Observers with no explicit priority have a middle range priority Allowing observer to be called last Observer with the same priority are called in an undefined order No priority on async events
  20. 20. @antoine_sd @cdispec#CDI2 public void observer1(@Observes @Priority(1) Payload p) { } public void observer2(@Observes @Priority(2) Payload p) { } Events ordering
  21. 21. @antoine_sd @cdispec#CDI2 public class MyExtension implements Extension {
 
 public void firstPat(@Observes @Priority(1) ProcessAnnotatedType<?> pat) { …
 }
 public void secondPat(@Observes @Priority(2) ProcessAnnotatedType<?> pat) { …
 }
 
 } Events ordering in extensions
  22. 22. @antoine_sd @cdispec#CDI2 CDI 1.x: Sync / Async Sync / Async is not specified The immutable status of the payload is not specified Implementations use a Sync model The payload is mutated in some implementations / framework Going async “blindly” might raise problems…
  23. 23. @antoine_sd @cdispec#CDI2 @Inject
 Event<Payload> event;
 public void someBSCriticalBusinessMethod() {
 event.fire(new Payload());
 } Synchronous events - firing pattern
  24. 24. @antoine_sd @cdispec#CDI2 public void callMe(@Observes Payload payload) {
 // Do something with the event } Synchronous events - observing pattern
  25. 25. @antoine_sd @cdispec#CDI2 Events are sync in CDI 1 Right now: All the observers are called in the firing thread In no particular order (at least not specified) The payload may be mutated
  26. 26. @antoine_sd @cdispec#CDI2 Events and contexts Contexts: Two contexts are critical: transactions and HTTP requests / sessions Events are aware of those contexts In an all-sync world, everything is fine But in an async world, we will be in trouble
  27. 27. @antoine_sd @cdispec#CDI2 Asynchronous Events So designing backward compatible async events is more tricky than it looks: A currently sync event should remain sync Going sync / async should be a decision taken from the firing side Being sync should be possible from the observing side
  28. 28. @antoine_sd @cdispec#CDI2 @Inject
 Event<Payload> event;
 public void someEvenMoreCriticalBusinessMethod() { 
 event.fireAsync(new Payload());
 } Async events - firing pattern
  29. 29. @antoine_sd @cdispec#CDI2 public void callMe(@ObservesAsync Payload payload) {
 // I am called in another thread } Async events - observing pattern
  30. 30. @antoine_sd @cdispec#CDI2 Sync vs Async Events in a nutshell callMe(@Observes payload) callMe(@ObservesAsync payload) event.fire(payload) Sync call Not notified event.fireAsync(payload) Not notified Async call
  31. 31. @antoine_sd @cdispec#CDI2 @Inject
 Event<PanelUpdater> event;
 public void someOtherCriticalBusinessMethod() { 
 event.fireAsync(new PanelUpdater(green), 
 executor); } Adding an Executor to fireAsync
  32. 32. @antoine_sd @cdispec#CDI2 @Inject
 Event<PanelUpdater> event;
 public void someOtherCriticalBusinessMethod() { 
 event.fireAsync(new PanelUpdater(green), SwingUtilities::invokeLater);
 } Async event in the GUI thread
  33. 33. @antoine_sd @cdispec#CDI2 @Inject
 Event<PanelUpdater> event;
 public void someOtherCriticalBusinessMethod() { 
 CompletionStage<PanelUpdater> stage = 
 event.fireAsync(new PanelUpdater(green), SwingUtilities::invokeLater);
 } Handling exceptions
  34. 34. @antoine_sd @cdispec#CDI2 Handling exceptions Exception in one async observer doesn’t stop execution as in sync observer One of the reasons why firing async event doesn’t trigger sync observers Event.fireAsync returns a CompletionStage Allowing integration of async events in standard Java 8 async pipeline
  35. 35. @antoine_sd @cdispec#CDI2 Handling exceptions The Exception in fireAsync returned CompletionStage is CompletionException It holds all the exceptions in the suppressed exception set
  36. 36. @antoine_sd @cdispec#CDI2 Handling exceptions Exception handling is done with the Standard Java 8 async api, with: stage.whenComplete() to deal with result or exception stage.handle() same as above but allows transformation of stage stage.exceptionally() to only treat exception case
  37. 37. @antoine_sd @cdispec#CDI2 SPI enhancement New configurators for meta data
  38. 38. @antoine_sd @cdispec#CDI2 Configurators for meta-data Some meta-data are very verbose to create AnnotatedType Bean InjectionPoint ObserverMethod If you only need to add info to an existing meta-data, it’s very boring
  39. 39. @antoine_sd @cdispec#CDI2 Example with CDI 1.2 I have a legacy framework I want to adapt it for CDI I need to detect all @CacheContext annotations on fields… ...And transform them in injection point I’ll use an extension to replace @CacheContext annotation by @Inject in AnnotatedTypes
  40. 40. @antoine_sd @cdispec#CDI2 Example 1/7 First we need to implement an AnnotatedType to decorate the original one and modify AnnotatedField set
  41. 41. @antoine_sd @cdispec#CDI2 public class AutoInjectingAnnotatedType<X> implements AnnotatedType<X> {
 
 private final AnnotatedType<X> delegate;
 private final Set<AnnotatedField<? super X>> fields;
 
 public AutoInjectingAnnotatedType(AnnotatedType<X> delegate) {
 this.delegate = delegate;
 fields = new HashSet<>();
 for (AnnotatedField<? super X> field : delegate.getFields()) {
 if (field.isAnnotationPresent(CacheContext.class))
 fields.add(new AutoInjectingAnnotatedField(field));
 else
 fields.add(field);
 }
 }
 … Example 2/7
  42. 42. @antoine_sd @cdispec#CDI2 …
 public Set<AnnotatedField<? super X>> getFields() {
 return fields;
 }
 public Class<X> getJavaClass() {
 return delegate.getJavaClass();
 }
 // 7 more similar methods 
 }
 Example 3/7
  43. 43. @antoine_sd @cdispec#CDI2 Example 4/7 Then we need to do the same for AnnotatedField to add @Inject to the field annotations set public class AutoInjectingAnnotatedField<X> implements AnnotatedField<X> {
 
 private final Set<Annotation> annotations;
 private final AnnotatedField<X> delegate;
 
 public AutoInjectingAnnotatedField(AnnotatedField<X> delegate) {
 this.delegate = delegate;
 annotations = new HashSet<>(delegate.getAnnotations());
 annotations.add(new InjectLiteral());
 }
 …
  44. 44. @antoine_sd @cdispec#CDI2 public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
 if (annotationType.equals(Inject.class))
 return (T) new InjectLiteral();
 return delegate.getAnnotation(annotationType);
 }
 
 public Set<Annotation> getAnnotations() {
 return annotations;
 }
 ... Example 5/7
  45. 45. @antoine_sd @cdispec#CDI2 public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
 if (annotationType.equals(Inject.class))
 return true;
 return delegate.isAnnotationPresent(annotationType);
 } public Set<Type> getTypeClosure() {
 return delegate.getTypeClosure();
 }
 // 4 similar methods 
 } Example 6/7
  46. 46. @antoine_sd @cdispec#CDI2 Example 7/7 Finaly we need to write the extension to use our custom AnnotatedType and AnnotatedField public class AutoInjectExtension implements Extension {
 
 public <T> void CreateIP( @Observes @WithAnnotations(CacheContext.class) ProcessAnnotatedType<T> pat) {
 pat.setAnnotatedType( new AutoInjectingAnnotatedType<T>(pat.getAnnotatedType()));
 }
 }
  47. 47. @antoine_sd @cdispec#CDI2 In CDI 2.0 We introduced configurators, helping creation of these metadata This configurators are accessible thru container lifecycle events They are automatically built by the container at the end of observer invocation
  48. 48. @antoine_sd @cdispec#CDI2 In CDI 2.0 All the previous code fits in this extension public class AutoInjectExtension implements Extension {
 
 public <T> void CreateIP( @Observes @WithAnnotations(CacheContext.class) ProcessAnnotatedType<T> pat) {
 pat.configureAnnotatedType().filterFields( f -> f.isAnnotationPresent(CacheContext.class) )
 .forEach(f -> f.add(InjectLiteral.INSTANCE)); }
 }
  49. 49. @antoine_sd @cdispec#CDI2 AOP enhancement Support AOP on custom or produced bean
  50. 50. @antoine_sd @cdispec#CDI2 Support AOP on producer In CDI 1.x you cannot bind an interceptor to a produced bean When you write: @Transactional is applied to producer method @Produces
 @Transactional public MyService produceService() { ... }
  51. 51. @antoine_sd @cdispec#CDI2 Support AOP on producer Answer is probably the new InterceptionProxyFactory This factory uses an AnnotatedType to know where adding interceptor bindings in the class Could also be used in Custom Bean create method public interface InterceptionProxyFactory<T> {
 
 InterceptionProxyFactory<T> ignoreFinalMethods();
 
 AnnotatedTypeConfigurator<T> configure();
 
 <T> T createInterceptionProxy(T InstanceToWrap);
 
 }
  52. 52. @antoine_sd @cdispec#CDI2 @Produces
 @RequestScoped
 public MyClass createJpaEmAssumed(InterceptionProxyFactory<MyClass> ipf) {
 AnnotatedTypeConfigurator<MyClass> atc = ipf.configure();
 
 atc.filterMethods(m -> m.getJavaMember().getName().equals("doSomething"))
 .findFirst() .ifPresent(m -> m.add(new AnnotationLiteral<Transactional>() { }));
 
 return ipf.createInterceptionProxy(new MyClass());
 
 } Add @transaction on one produced bean method
  53. 53. @antoine_sd @cdispec#CDI2 CDI 2.0 needs you CDI 2.0 specification is open to everyone Come on join us on the mailing list and IRC channel All infos on http://cdi-spec.org or by following to @cdispec on twitter The more we are the more we’ll deliver
  54. 54. @antoine_sd @cdispec#CDI2 Which JSR you’ll use 365 days a year? … JSR 365

×