CDI In Real Life
Upcoming SlideShare
Loading in...5
×
 

CDI In Real Life

on

  • 694 views

This talk will present advance feature in CDI to include legacy code. It also shows how to create extension and use DeltaSpike to register beans

This talk will present advance feature in CDI to include legacy code. It also shows how to create extension and use DeltaSpike to register beans

Statistics

Views

Total Views
694
Views on SlideShare
692
Embed Views
2

Actions

Likes
2
Downloads
21
Comments
0

1 Embed 2

http://www.linkedin.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    CDI In Real Life CDI In Real Life Presentation Transcript

    • CDI in Real Life Antoine Sabot-Durand Senior Software developer Red Hat @antoine_sd
    • Antoine Sabot-Durand • Senior Software Developer @Red Hat ! • Java & OSS : • CDI 1.1 EG member • Tech Lead on Agorava • JDF / Fuse commiter ! • @antoine_sd 2
    • Agenda • CDI in 5 minutes • CDI in real life 1 (code) • Focus on CDI extensions • CDI in real life II (code++) • CDI ecosystem • What’s up in CDI 1.1 • Q&A 3
    • CDI in (almost) 5 minutes
    • Context & Dependency Injection • Yet Another DI solution, but... • #annotationsEverywhere #noXml • Typesafe • Context Management • CDI is the evolution engine of Java EE thanks to portable extension • A standard way to integrate new or legacy libs in Java EE • Three implementations • JBoss Weld : RI implementation • Apache OpenWebBeans • Caucho Candi 5
    • Dependency Injection @Inject 6
    • Dependency Injection public class HelloService {!     public String hello() {!         return "Hello World!";!     }! } 7
    • Dependency Injection in constructor public class MyBean {! !     private HelloService service;! !     @Inject!     public MyBean(HelloService service) {!         this.service = service;!     }!     public void displayHello() {!         display( service.hello();!     }! } 8
    • Dependency Injection in setter public class MyBean {! !     private HelloService service;! !     @Inject!     public void setService(HelloService service) {!         this.service = service;!     }!     public void displayHello() {!         display( service.hello();!     }! } 9
    • Dependency Injection in field public class MyBean {! !     @Inject HelloService service;! !     public void displayHello() {!         display( service.hello();!     }! } 10
    • Qualifiers public class MyBean {!     @Inject @French HelloService service;!     public void displayHello() {!         display( service.hello();!     }! }! public class MyBean {!     @Inject @English HelloService service;!     public void displayHello() {!         display( service.hello();!     }! } 11
    • Qualifiers @Qualifier! @Retention(RUNTIME)! @Target({FIELD, TYPE, METHOD, PARAMETER}) ! public @interface French {}! ! @Qualifier! @Retention(RUNTIME)! @Target({FIELD, TYPE, METHOD, PARAMETER}) ! public @interface English {} 12
    • Qualifiers @French! public class FrenchHelloService implements HelloService {!     public String hello() {!         return "Bonjour tout le monde!";!     }! }! ! @English! public class EnglishHelloService implements HelloService {!     public String hello() {!         return "Hello World!";!     }! } 13
    • Qualifiers @Qualifier! @Retention(RUNTIME)! @Target({FIELD, TYPE, METHOD, PARAMETER}) ! public @interface Language {! !     Languages value();! ! @Nonbinding String description() default "";! !     public enum Languages { !         FRENCH, ENGLISH!     }! } 14
    • Reserved Qualifiers @Default! @Any! @Named 15
    • Programmatic lookup public class MyBean {! !     @Inject Instance<HelloService> service;! !     public void displayHello() {!         display( service.get().hello() );!     }! } 16
    • Programmatic lookup public class MyBean {! !     @Inject Instance<HelloService> service;! !     public void displayHello() {!         if (!service.isUnsatisfied()) {!             display( service.get().hello() );!         }!     }! } 17
    • Programmatic lookup public class MyBean {! !     @Inject @Any Instance<HelloService> services;! !     public void displayHello() {!         for (HelloService service : services) {!             display( service.hello() );!         }!     }! } 18
    • Programmatic lookup public class MyBean {! !     @Inject @Any Instance<HelloService> services;! !     public void displayHello() {!         display( !             service.select(! new AnnotationLiteral()<French> {})!                 .get() );!     }! } 19
    • Contexts • Manage bean lifecycle • context helps container to choose when a bean should be generated and destroyed it enforces the fact that a given bean is a singleton for a given context Built-in CDI contexts : @Dependent (default) @RequestScoped! @SessionScoped! @ConversationScoped! @ApplicationScoped! @Singleton! You can create your own scope • • • • • • • • • 20
    • Contexts @SessionScoped! public class CartBean {! !     public void addItem(Item item) {! ...!     } ! } 21
    • Contexts @ThreadScoped! public class CartBean {! !     public void addItem(Item item) {! ...!     } ! } 22
    • Producers @Produces! public MyNonCDIClass myProducer() {! return new MyNonCdiClass();! }! ...! @Inject! MyNonCDIClass bean;! 23
    • Producers @Produces! @PersistenceContext! private EntityManager em; 24
    • Producers @Produces! @RequestScoped! public FacesContext produceFacesContext() {! return FacesContext.getCurrentInstance();! } 25
    • Producers @Produces! public Logger produceLog(InjectionPoint injectionPoint) {! return Logger.getLogger(injectionPoint.getMember()! .getDeclaringClass().getName());! } 26
    • Decorators @Decorator! public class HelloDecorator implements HelloService {! !     @Inject @Delegate HelloService service;! !     public String hello() {!         return service.hello() + "-decorated";!     }! } @Inject HelloService service; 27
    • Decorators activation in CDI 1.0 <?xml version="1.0" encoding="UTF-8"?>! <beans xmlns="http://java.sun.com/xml/ns/javaee"!    xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"!    xsi:schemaLocation="! http://java.sun.com/xml/ns/javaee! http://java.sun.com/xml/ns/javaee/ beans_1_0.xsd">!   <decorators>!     <class>foo.bar.HelloDecorator</class>!   </decorators>! </beans> 28
    • Interceptors @Interceptor @Loggable! public class LogInterceptor {!     @AroundInvoke!     public Object log(InvocationContext ic) ! throws Exception {!         System.out.println("Entering " ! + ic.getMethod().getName());!         try {!             return ic.proceed(); !         } finally {!             System.out.println("Exiting " ! + ic.getMethod().getName());!         }!     } ! } 29
    • Interceptors @InterceptorBinding! @Target({METHOD, TYPE}) ! @Retention(RUNTIME)! public @interface Loggable {} 30
    • Interceptors @Loggable! public class MyBean extends Application {! !     @Inject HelloService service;! !     public void displayHello() {!         display( service.hello();!     }! } 31
    • Interceptors activation in CDI 1.0 <?xml version="1.0" encoding="UTF-8"?>! <beans xmlns="http://java.sun.com/xml/ns/javaee"!    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"!    xsi:schemaLocation="! http://java.sun.com/xml/ns/javaee! http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">!   <interceptors>!     <class>foo.bar.LogInterceptor</class>!   </interceptors>! </beans> 32
    • Events @Inject Event<String> evt;! ...! evt.fire("Hello"); @Inject Event<Post> evt;! ...! evt.fire(! new Post(! "John Doe ", "Hello", )); 33
    • Events public void receiveEvt(@Observes String evt) {!     System.out.println("Received : " + evt);! } public void receiveEvt(@Observes Post evt) {!     System.out.println("Received : " ! + evt.message());! } 34
    • CDI In Real Life 1
    • Meet Booxle • This startup want to provide encrypted storage services • Dev decided to build a POC with CDI • Code used in POC is not from the last Hype • javax.crypto.Cipher and javax.crypto.SecretKey from JDK 1.4 • java.io.OutputStream / java.io.InputStream from JDK 1.0 • You can get the code on github • https://github.com/antoinesd/cdi-irl Each step is a branch in the git repo and have an Arquillian test to check devs Let’s start to branch step_0 • 36
    • Step 0 : Because there must be a start • We only have a producer for javax.crypto.CypherOutputStream It is produced to send encrypted data to a File with a basic symetric encryption algorythm : Blowfish • ! • The Produced Outputstream is injected in the test class ! • The only test checks that a file is created when sending text to the stream 37
    • Step 1 : It’s time to read • We introduce a producer for javax.crypto.CypherInputStream • So we can test reading in our file ! • In order to read the encrypted data we need tho share the same encryption key • So we added a producer for a javax.crypto.SecretKey in ApplicationScope • The produced key is automatically injected by CDI in producers method parameters ! • Let’s have a second test that checks we read the same thing that we wrote 38
    • Step 2 : Deciding filename at Injection • We want to provide different file to read and write to. • For that we create a qualifier @ForFile which has one • • • @NonBinding String parameter containing a filepath In our producer we add the InjectionPoint object containing information on injection point In producers by analyzing the annotation in InjectionPoint we find the filename Test stays the same except injection are qualified with @ForFile(<filename>) 39
    • Step 3 : Deciding filename at Runtime • We want to choose our file at runtime. • So we need to create our @ForFileAnnotation at Runtime • and access a @ForFile instance and no more a known at compile value stored in injected field annotation ! • In the producer we add an extractFileName method that looks for ForFile Qualifier instance and its value • Test become a bit more tricky since we have to create qualifier at runtime and use programmatic lookup to resolve bean 40
    • Step 4 : Service class • Cleaning the code by using a Service Class ! • We move our code to AccessFileService bean ! • Producer is kept for our SecretKey ! • Now if we want to support multiple encryption algorithms we can : • Create producers for other keys • Or build an extension... 41
    • CDI extensions
    • CDI Extensions for what ? • A CDI extension can : • Create / modify : • Beans • Injection Target • Injection Points • Cancel beans creation • More generally extensions can modify all CDI context at launch time 43
    • To understand extensions • Once application is • • • bootstrapped, the Bean Manager is in read only mode (no dynamic bean registration) Extensions are launch during bootsrap and are based on CDI events You only have to @Observes built-in CDI event to create your extensions Learn the different events fired at boot time on next slide 44
    • CDI 1.0 Lifecycle Process Bean Process Observer Method Undeploy Application Scan Archive Process Producer After Bean Discovery Before Shutdown Process Annotated Type Process Injection Target After Deployment Validation Application Running Before Bean Discovery 45
    • CDI 1.1 Lifecycle Before Bean Discovery Process Injection Target Process Producer After Deployment Validation Application Running Scan Archive Process Injection Point Process Bean Attributes After Bean Discovery Before Shutdown Process Bean Process Observer Method Undeploy Application Process Annotated Type After Type Discovery 46
    • How to build a CDI extension • Create a class implementing javax.enterprise.inject.spi.Extension ! • Add some method that observes CDI lifecyle events to modify Bean Manager meta data ! • Add file :
 META-INF/services/ javax.enterprise.inject.spi.Extension
 47
    • Simple example: @Veto  <X> void processAnnotatedType(@Observes final ProcessAnnotatedType<X> pat, BeanManager beanManager) {!         final AnnotatedType<X> annotatedType = pat.getAnnotatedType();!         final Class<X> javaClass = annotatedType.getJavaClass();!         final Package pkg = javaClass.getPackage();! !         // Support for @Veto!         if (annotatedType.isAnnotationPresent(Veto.class) || (pkg != null && pkg.isAnnotationPresent(Veto.class))) {!             pat.veto();!             log.info("Preventing " + javaClass + " from being installed as bean due to @Veto annotation");!             return;!         }! } 48
    • CDI In Real Life 1I
    • Step 5 : Extension to create Beans... • To have a solution to choose encryption algorithm we • add @ForAlgo Qualifier We create a CDI extension to : Detect Algo requested at injection points Gather Algo of explicit produced Secret keys to avoid automatic creation Create beans for secret key and AccessFile for each algorithm detected • • • 50
    • CDI Eco-system 51
    • What’s new in CDI 1.1 ! • Add global enablement of interceptors, global enablement of decorators • • • • • • • • using the @Priority annotation Add support for @AroundConstruct lifecycle callback for constructors Allow binding interceptors to constructors Add EventMetadata to allow inspection of event metadata Add @Vetoed annotation Add AlterableContext allowing bean instances to be explicitly destroyed Add class exclusion filters to beans.xml to prevent scanning of classes and packages Add CDI utility class allowing easy access to the current CDI container Add AfterTypeDiscovery event, allowing extensions to register additional types after type discovery 52
    • Q&A