Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

CDI 2.0 (JSR 365)

CDI 2.0 (JSR 365)

Overview of CDI 2.0 introduced in Java EE 8 Java Day Tokyo 2017

Akihiro Nishikawa

May 17, 2017
Tweet

More Decks by Akihiro Nishikawa

Other Decks in Technology

Transcript

  1. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 2.0 (JSR 365) Contexts and Dependency Injection for Java 2.0 Akihiro Nishikawa Cloud Technology Business Unit Oracle Corporation Japan 17, May, 2017 Java Day Tokyo 2017 #JavaDayTokyo
  2. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 2
  3. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Program Agenda 3 What’s CDI ? What’s new in CDI 2.0? Summary 1 2 3
  4. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | What’s CDI? • Lifecycle for stateful objects bound to lifecycle contexts • Type-safe dependency injection mechanism • Event notification • Integration with the Unified Expression Language (EL) • ... 5 Major theme of CDI is “loose coupling”
  5. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 2.0 (JSR-365) • Major evolution of the CDI 1.2 (JSR 346) specification • Spec Lead – Antoine Sabot-Durand (Red Hat Inc.) (@antoine_sd) • Reference Implementation – Weld : http://download.jboss.org/weld/3.0.0.Final/ 6 http://www.cdi-spec.org (@cdispec)
  6. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 8 CDI Timeline December 2009 CDI 1.0 (Java EE 6) June 2013 CDI 1.1 (Java EE 7) April 2014 CDI 1.2 (1.1 Maintenance Release) September 2014 CDI 2.0 starts… May 2017 CDI 2.0
  7. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 1.0 (JSR-299) • 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 9 Contexts and Dependency Injection for the Java EE platform 1.0
  8. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 1.1/1.2 (JSR-346) • Add automatic enablement of CDI in Java EE (beans.xml is not required) • 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 of CDI Lifecycle and Events 10 Contexts and Dependency Injection for the Java EE platform 1.1/1.2
  9. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 1.1/1.2 (JSR-346) • Reworking Bean defining annotation to avoid conflict with other JSR 330 frameworks • Clarification on conversation resolution • OSGi official support in the API 11 Contexts and Dependency Injection for the Java EE platform 1.1/1.2
  10. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 12 CDI is associated with the following specs DI (Dependency Injection) EJB (Enterprise JavaBeans) Bean Validation Interceptors Managed Beans Common Annotation CDI JSF (JavaServer Faces)
  11. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Major Changes • Spec was split into 3 parts • Java SE Support – Using CDI outside Java EE • Alignment on Java 8 features (streams, lambdas, repeating qualifiers) • Event enhancement • Configurators for major SPI elements • Possibility to configure or veto observer methods • Add built-in annotation literals • Make possible to apply interceptor on producers 14
  12. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Why the spec was split? • To align on many other Java EE spec which support Java SE bootstrapping – JAX-RS, JPA... • To boost CDI adoption for Spec and Frameworks – Java SE has been already supported by Weld, Apache OpenWebBeans, Apache DeltaSpike and so on, but API is different from each implementation. – Programming model should be defined to avoid user confusion. • To provide a mean of building new stacks out of Java EE (MicroProfile) 17
  13. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Name was changed... • JSR 346 Contexts and Dependency Injection for Java EE • JSR 365 Contexts and Dependency Injection for Java 18
  14. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Java SE support Using CDI outside Java EE 19
  15. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 1.x • Not specified • Depending upon each implementation – Weld – Apache DeltaSpike – ... CDI 2.0 • Standard API is specified • Must explicitly boot CDI container 20 API to boot CDI in Java SE
  16. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | API to boot CDI in Java SE import javax.enterprise.inject.se.SeContainer; import javax.enterprise.inject.se.SeContainerInitializer; public class Sample { public static void main(String... args) { try (SeContainer container = SeContainerInitializer .newInstance() .initialize()) { ... } } } 21
  17. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | SeContainer interface • Handle for CDI Interface – The handle is used to access the BeanManager • AutoCloseable • Extends javax.enterprise.inject.Instance – Able to use SeContainer to look up Instance programatically – If no qualifier is passed to SeContainer#select(), the @Default qualifier is assumed. – If no required type is given, the required type is the same as the parent’s one. • Able to use CDI#current() 23 javax.enterprise.inject.se.SeContainer
  18. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Controlling the classpath try (SeContainer container = SeContainerInitializer.newInstance() .addPackages(Pojo.class) .disableDiscovery() .initialize()) { ... } 24 When adding Beans explicitly, bean discovery should be disabled
  19. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Configurable try (SeContainer container = SeContainerInitializer.newInstance() .addExtensions() .enableDecorators() .selectAlternativeStereotypes() .selectAlternatives() .addProperty() .initialize()) { ... } 25 Able to add Alternatives, Stereotypes, Decorators, and Extensions
  20. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Request Context Management • In Java SE, most of built-in contexts is unavailable… –Request context –Session context –Conversation context –... 26 Why is this feature required?
  21. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Request Context Management • Start and stop request context programmatically through built-in bean • Provide built-in Interceptor to handle it automatically • This feature is also available for Java EE. 27 How to manage request contexts
  22. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Request Context Management @ApplicationScoped public class MyBean { @Inject RequestContextController requestContextController; public void doRequest(String body) { boolean started = requestContextController.activate(); ... if( started ) { requestContextController.deactivate(); } } } 28 1) Built-in Beans to activate/deactivate Request Context
  23. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Request Context Management @ApplicationScoped public class MyBean { @ActivateRequestContext public void doRequest(String body) { // Request context is activated during this invocation ... } } Priority Interceptor.Priority.PLATFORM_BEFORE + 100 (100) 29 2) Built-in Interceptor for automatically processing
  24. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Java 8 Alignment • Use Java 8 feature and functionalities heavily – Functional Interface – Stream • For example, Instance directly supports Stream API – Previously, unable to use Stream API along with Instance • Custom libraries using CDI 1.x might be built again to align with CDI 2.0 31
  25. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Example @Inject @Any private Instance<Object> objects; public void onBean(@Observers AfterBeanDiscovery abd) { abd.addBean().produceWith(instance -> new Object()) .destroyWith((o, cc) -> {}); objects.stream().filter(Objects::nonNull) .forEach(o->o.notify()); ... 32 Builder-based Bean Configuration, Lambda expression, and Stream API
  26. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Repeating Qualifier • Able to qualify classes and methods using the same annotation – Supported by language level • In case of get all annotations… 33 javax.enterprise.inject.spi.Annotated.getAnnotations()
  27. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Event Enhancement Event ordering Asynchronous events 34
  28. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Event Ordering • Event ordering using @Priority – The lowest value is first – Observers with no explicit priority have a middle range priority for allowing observer to be called last – Observer with the same priority are called in an undefined order • Only applicable to synchronous events – @Priority does not work for ordering asynchronous events 35
  29. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Event Ordering import javax.enterprise.inject.spi.ObserverMethod; import javax.interceptor.Interceptor; ... // ObserverMethod.DEFAULT_PRIORITY // = Interceptor.Priority.APPLICATION + 500 System.out.println(ObserverMethod.DEFAULT_PRIORITY); // 2500 System.out.println(Interceptor.Priority.APPLICATION); // 2000 36 Default Priority
  30. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Event Ordering public void observer1( @Observes @Priority(1) Payload p) { ... } public void observer2( @Observes @Priority(2) Payload p) { ... } 37 Example 1
  31. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Event Ordering public class MyExtension implements Extension { public void firstProcessAnnotatedType( @Observes @Priority(1) ProcessAnnotatedType<?> pat) { ... } public void secondProcessAnnotatedType( @Observes @Priority(2) ProcessAnnotatedType<?> pat) { ... } } 38 Example 2 – along with portable extensions
  32. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Events in CDI 1.x • Sync/Async is not specified, but implementation uses Synchronous model – Observers are called in the firing thread (i.e. synchronous event) without particular order specified • Immutable status of the payload is not specified – Payload is mutated in some implements and framework • Observers may inject beans • Observers are aware of Transactional and security contexts 39
  33. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Synchronous Events @Inject Event<Payload> event; public void syncCaller() { // Fire an event synchronously event.fire(new Payload()); } public void syncCallee(@Observes Payload p) { // Do something } 40 Firing and Observing events
  34. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events • Unable to mutate payload • Unable to access CDI contexts state at the firing point • Not transactional Event#fireAsync() @ObservesAsync 41 CDI 2.0
  35. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events @Inject Event<Payload> event; public void asyncCaller() { // Fire an event asynchronously event.fireAsync(new Payload()); } public void syncCallee(@ObservesAsync Payload p) { // Do something } 42 Firing and observing events
  36. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events @Inject Event<PanelUpdater> event; public void someMethod() { event.fireAsync( new PanelUpdater(green), executor); ... } 43 Example 1 – Executor
  37. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events @Inject Event<PanelUpdater> event; public void someMethod() { event.fireAsync( new PanelUpdater(green), SwingUtilities::invokeLater ); ... } 44 Example 2 – Asynchronous event in GUI thread
  38. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events • Exception raised in one async observer does not stop execution as in sync observer. – One of the reasons why firing async event does not trigger sync observers. • Event.fireAsync returns CompletionStage – Exception in fireAsync returned CompletionStage is CompletionException, which holds all the exceptions in the suppressed exception set. • Allowing integration of async events in standard Java 8 async pipeline. 45 Exception handling
  39. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events @Inject Event<PanelUpdater> event; public void someMethod() { ... CompleteionStage<PanelUpdater> stage = event.fireAsync( new PanelUpdater(green), SwingUtilities::invokeLater ); ... } 46 Example 3 – Exception handing
  40. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Asynchronous Events • stage.whenComplete() – To handle result or exception • stage.handle() – Same as above but allows transformation of stage. • stage.exceptionally() – Used in the only case for treating exception 47 Exception handling with standard Java 8 Asynchronous API
  41. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 48 Synchronous Events and Asynchronous Events event.fire() @Observes event.fireAsync() @ObservesAsync
  42. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Are you planning migration to asynchronous events? • Simple replacement might raise problems! • Recommendation – In case of using sync events as of now, you should keep as it is. – Some limitation should be recognized. – Going sync/async should be a decision taken from firing side. – Being sync should be possible from observing side. 49
  43. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Threading and Events in Java SE • Async events – Able to use Custom Executor • Sync events – Always within the same thread – When observers handle synchronous event in Java SE, request scope activation might be required. 50 @Inject Event <Pojo> event; @ActivateRequestContext public void syncSender() { event.fire(event); ... } public void syncReceiver( @Observes Pojo event ) { ... }
  44. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Previous • BeanManager#fireEvent() CDI 2.0 • BeanManager#getEvent() – Able to get Event object – Event is typed to Object and implicitly annotated with @Default qualifier • BeanManager#fireEvent() is deprecated since CDI 2.0. 51 Programmatic Events
  45. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 53 Indeed AnnotationLiteral is helpful if there is no member in an annotation. Standard Annotation Instances Annotation instance = new AnnotationLiteral<ApplicationScoped>(){};
  46. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 54 But we have to create a class when an annotation has members... Standard Annotation Instances public class NamedLiteral extends AnnotationLiteral<Named> implements Named{ private String value; public NamedLiteral(String value) { this.value = value; } @Override public String value() { return null; } }
  47. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | • javax.enterprise.inject. – Any – Default – New – Specialized – Vetoed • javax.enterprise.util. – Nonbinding • javax.enterprise.inject. – Alternative – Typed • javax.enterprise.context. – Initialized – Destroyed – RequestScoped – SessioScoped – ApplicationScoped – Dependent – ConversationScoped 55 Built-in annotation literals
  48. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Built-in annotation literals Default defaultLiteral = new Default.Literal(); // No members ApplicationScoped literal = ApplicationScoped.Literal.INSTANCE; // If annotation have members Initialized initializedForApplicationScoped = new Initialized.Literal(ApplicationScoped.class); Initialized initializedForRequestScoped = Initialized.Literal.of(RequestScoped.class); 56 Example
  49. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Configurators for metadata • AnnotatedType • InjectionPoint • Bean • ObserverMethod 58 Even if adding info to an existing metadata, quite verbose work is required.
  50. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 59 In CDI 1.2 Configurators for metadata I want to modify some legacy framework which contains @CacheContext annotations in order to adapt CDI. What should I do? If I were you, I would create some extension to replace @CacheContext annotation with @Inject in AnnotatedTypes... But Do I have to create huge codes to do so? Exactly...
  51. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Configurators interfaces • AnnotatedType – AnnotatedTypeConfigurator • InjectionPoint – InjectionPointConfigurator • BeanAttributes – BeanAttributesConfigurator • Bean – BeanConfigurator • ObserverMethod – ObserverMethodConfigurator • Producer – ProducerConfigurator 60 Newly introduced in CDI 2.0
  52. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 61 In CDI 2.0 Configurators for meta-data What do you do when you want to adapt CDI to some legacy framework? If I were you, I would create metadata with “configurators”, which are accessible through container lifecycle events and automatically built by the container at the end of observer invocation. Oh, it sounds nice…
  53. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | CDI 2.0 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)); } } 62
  54. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Application Lifecycle Events (fired only one time) • Startup – BeforeBeanDiscovery – AfterTypeDiscovery – AfterBeanDiscovery – AfterDeploymentValidation • Shutdown – BeforeShutdown Bean Discovery Events (might be fired multiple times) – ProcessAnnotatedType – ProcessInjectionPoint – ProcessInjectionTarget – ProcessBeanAttributes – ProcessBean – ProcessProducer – ProcessObserverMethod 64 Container lifecycle events
  55. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Directing requests Type Discovery Search service providers Bean Discovery 65 Container Startup Application Lifecycle Events BeforeBeanDiscovery Detect deployment problems AfterTypeDiscovery AfterBeanDiscovery AfterDeploymentValidation
  56. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | destroy all contexts 66 Container Shutdown Application Lifecycle Events BeforeShutdown
  57. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Add new methods in ProcessObserverMethod public interface ProcessObserverMethod<T, X> { ... // Replaces the ObserverMethod public void setObserverMethod(ObserverMethod<T> observerMethod); // Returns a ObserverMethodConfigurator initialized with the ObserverMethod processed by this event public ObserverMethodConfigurator<T> configureObserverMethod(); // forces the container to ignore the ObserverMethod public void veto(); } 67 javax.enterprise.inject.spi.ProcessSyntheticObserverMethod<T, X>
  58. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | 69 Able to apply @Transactional to a producer method Interceptor is not bound to a produced Bean in CDI 1.x @Produces @Transactional public MyService produceService() { ... }
  59. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | IntereptionFactory Interface public interface InterceptionFactory<T> { InterceptionProxyFactory<T> ignoreFinalMethods(); AnnotatedTypeConfigurator<T> configure(); <T> T createInterceptedInstance(T InstanceToWrap); } 70 javax.enterprise.inject.spi.InterceptionFactory<T>
  60. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Add @transactional on one produced bean method @Produces @RequestScoped public MyClass createJpaEmAssumed(InterceptionFactory<MyClass> f) { AnnotatedTypeConfigurator<MyClass> atc = f.configure(); atc.filterMethods(m -> m.getJavaMember() .getName() .equals("doSomething")) .findFirst() .ifPresent(m -> m.add( new AnnotationLiteral<Transactional>(){ })); return f.createInterceptedInstance(new MyClass()); } 71 CDI 2.0
  61. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Programmatic lookup – Instance Enhancement Instance obj; ... if( !obj.isAmbiguous() && !obj.isUnsatisfied() ) { ... } 73 Previous isUnsatisfied() Returns true if there is no bean found, or false otherwise. isAmbiguous() Returns true if there is more than one bean found, or false otherwise.
  62. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Programmatic lookup – Instance Enhancement Instance obj; ... if(obj.isResolvable()) { ... } 74 CDI 2.0 isResolvable() Returns true if there is exactly one bean found, or false otherwise.
  63. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Key takeaway • Able to use CDI 2.0 on Java EE as well as Java SE. • Enhancements and new features help increase developer productivity. • Weld 3.0, reference Implementation of CDI, will be integrated with GlassFish 5 soon! 76
  64. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Deprecated methods When? Method Alternatives CDI 2.0 BeanManager#fireEvent() BeanManager#getEvent() CDI 1.1 BeanManager#createInjectionTarget() BeanManager#getInjectionTargetFactory() CDI 1.1 javax.enterprise.inject .spi.Bean#isNullable() No alternatives CDI 1.1 AnnotatedMember#isStatic() Check with AnnotatedMember#getJavaMember().getModi fiers() CDI 1.1 BeforeBeanDiscovery#addAnnotatedType( AnnotatedType<?> type) eforeBeanDiscovery#addAnnotatedType( AnnotatedType<?> type, String id) 78
  65. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.

    | Safe Harbor Statement The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 79