This presentation provides an introduction to CDI (Contexts and Dependency Injection), covering the basic and intermediate features. It was authored by Antoine Sabot-Durand, the co-spec lead for CDI.
2. ANTOINE SABOT-DURAND
• Senior Software Engineer @Red Hat
• Java & OSS :
• CDI co-spec lead
• CDI community development
• Tech Lead on Agorava
• @antoine_sd
3. WHAT IS CDI ?
• Java EE dependency injection standard
• Strong typed and type safe
• Context management
• Observer pattern included (Event bus)
• Highly extensible
4. A BIT OF HISTORY
Dec 2009 June 2013 Apr 2014 Sep 2014
CDI
1.0
(Java
EE
6)
CDI
1.1
(Java
EE
7)
CDI
1.2
(1.1
MR)
CDI
2.0
Starts
Q1 2016
CDI
2.0
released
6. CDI ACTIVATION
• In CDI 1.0, you must add a beans.xml file to your archive
• Since CDI 1.1, it’s activated by default:
• All classes having a “bean defining annotation” become a bean
• You can still use beans.xml file to activate CDI explicitly or
deactivate it
7. THE CDI BEAN
• In Java EE 6 and 7 everything is a Bean including (EJB session beans)
• beans are basic components
• They are managed by the container
• They all have a lifecycle
• They can be intercepted (AOP)
• They can be injected
• Accessible from outside CDI code.
9. THIS IS A BEAN
public class HelloService {
public String hello() {
return "Hello World!";
}
}
10. DI IN CONSTRUCTOR
public class MyBean {
private HelloService service;
@Inject
public MyBean(HelloService service) {
this.service = service;
}
}
11. DI IN INITIALISER METHOD
public class MyBean {
private HelloService service;
@Inject
public void initService(HelloService service) {
this.service = service;
}
}
12. DI IN FIELD
public class MyBean {
@Inject
private HelloService service;
public void displayHello() {
display(service.hello();
}
}
13. NOTYPE ERASURE IN CDI
public class MyBean {
@Inject Service<User> userService;
@Inject Service<Staff> staffService;
}
14. NOTYPE ERASURE IN CDI
public class MyBean {
@Inject Service<User> userService;
@Inject Service<Staff> staffService;
}
This works
15. TYPES OF A BEAN
• A bean will be a candidate for all “injection point” whose type
belongs to its types set
• Bean types set contains its type, all its implementing interfaces and all
its ancestors including Object.
• Bean types can be restricted by using @Typed annotation (Object is
always in the set)
16. TYPES OF A BEAN
public class HelloService {
//Types set : HelloService, Object
}
public class FrenchHelloService extends GenericService implements HelloService {
//Types set : FrenchHelloService, GenericService, HelloService, Object
}
@Typed({HelloService.class,GenericService.class})
public class FrenchHelloService extends GenericService implements HelloService {
//Types set : GenericService, HelloService, Object
}
18. TWO SERVICE IMPLEMENTATIONS…
public interface HelloService {
public String hello();
}
public class FrenchHelloService implements HelloService {
public String hello() {
return "Bonjour tout le monde!";
}
}
public class EnglishHelloService implements HelloService {
public String hello() {
return "Hello World!";
}
}
20. …TO BE DISTINGUISHED.
@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!";
}
}
21. QUALIFIED INJECTION POINTS
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();
}
}
22. QUALIFIERS CAN HAVE MEMBERS
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, PARAMETER})
public @interface Language {
Languages value();
@Nonbinding String description() default "";
public enum Languages {
FRENCH, ENGLISH
}
}
23. QUALIFIERS WITH MEMBERS 1/2
@Language(FRENCH)
public class FrenchHelloService implements HelloService {
public String hello() {
return "Bonjour tout le monde!";
}
}
@Language(ENGLISH)
public class EnglishHelloService implements HelloService {
public String hello() {
return "Hello World!";
}
}
24. QUALIFIERS WITH MEMBERS 2/2
public class MyBean {
@Inject @Language(ENGLISH) HelloService service;
public void displayHello() {
display( service.hello();
}
}
public class MyBean {
@Inject @Language(FRENCH) HelloService service;
public void displayHello() {
display( service.hello();
}
}
25. MULTIPLE QUALIFIERS
public class MyBean {
@Inject @French
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements HelloService {
}
26. MULTIPLE QUALIFIERS
public class MyBean {
@Inject @French @Console
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements HelloService {
}
27. MULTIPLE QUALIFIERS
public class MyBean {
@Inject @French @Console @Secured
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements HelloService {
}
28. MULTIPLE QUALIFIERS
public class MyBean {
@Inject @French @Console @Secured
HelloService service;
}
@French @Secured
public class FrenchHelloService implements HelloService {
}
29. MULTIPLE QUALIFIERS
public class MyBean {
@Inject @French @Console @Secured
HelloService service;
}
@French @Secured
public class FrenchHelloService implements HelloService {
}
32. SOMETIMES CALLED “LAZY INJECTION”
public class MyBean {
@Inject Instance<HelloService> service;
public void displayHello() {
display( service.get().hello() );
}
}
33. CHECK BEAN EXISTENCE AT RUNTIME
public class MyBean {
@Inject Instance<HelloService> service;
public void displayHello() {
if (!service.isUnsatisfied()) {
display( service.get().hello() );
}
}
}
34. LOOP ON ALL BEANS OF A GIVENTYPE
public class MyBean {
@Inject @Any Instance<HelloService> services;
public void displayHello() {
for (HelloService service : services) {
display( service.hello() );
}
}
}
35. SELECT A QUALIFIER AT RUNTIME
public class MyBean {
@Inject @Any Instance<HelloService> services;
public void displayHello() {
display(
service.select(
new AnnotationLiteral()<French> {})
.get() );
}
}
37. CONTEXTS MANAGE BEANS LIFECYCLE
• They helps container to choose when a bean should be instantiated and destroyed
• They enforce the fact that a given bean is a singleton for a given context
• Built-in CDI contexts :
• @Dependent (default)
• @ApplicationScoped, @SessionScoped, @RequestScoped
• @ConversationScoped
• @Singleton
• You can create your own scope
44. CREATING BEAN FROM ANY CLASS
@Produces
public MyNonCDIClass myProducer() {
return new MyNonCdiClass();
}
...
@Inject
MyNonCDIClass bean;
45. DISPOSER ARE OPTIONAL
@Produces
public MyNonCDIClass myProducer() {
return new MyNonCdiClass();
}
// Will be call at the instance end of life
public void releaseMyInstance(@Disposes MyNonCdiClass inst) {
inst.clean();
}
46. PRODUCERS MAY HAVE A SCOPE
@Produces
@RequestScoped
public FacesContext produceFacesContext() {
return FacesContext.getCurrentInstance();
}
47. GETTING INFO FROM INJECTION POINT
@Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember()
.getDeclaringClass().getName());
}
48. REMEMBER :“NOTYPE ERASURE”
@Produces
public <K, V> Map<K, V> produceMap(InjectionPoint ip) {
if (valueIsNumber(ip.getType())) {
return new TreeMap<K, V>();
}
return new HashMap<K, V>();
}
50. A NICE WAYTO ADD DECOUPLING
public class FirstBean {
@Inject Event<Post> postEvent;
public void saveNewPost(Post myPost) {
postEvent.fire(myPost);
}
}
public class SecondBean {
public void listenPost(@Observes Post post) {
System.out.println("Received : " + evt.message());
}
}
51. EVENTS CAN BE QUALIFIED
public class FirstBean {
@Inject Event<Post> postEvent;
public void saveNewPost(Post myPost) {
postEvent.select(
new AnnotationLiteral()<French> {}).fire(myPost);
}
}
public class SecondBean {
// these 3 observers will be called
public void listenFrPost(@Observes @French Post post) {}
public void listenPost(@Observes Post post) {}
public void listenObject(@Observes Object obj) {}
// This one won’t be called
public void listenEnPost(@Observes @English Post post) {}
}
52. AS ALWAYS “NOTYPE ERASURE”
public class SecondBean {
// these observers will be resolved depending
// on parameter in event payload type
public void listenStrPost(@Observes Post<String> post) {}
public void listenNumPost(@Observes Post<Number> post) {}
}
53. SOME BUILT-IN EVENTS
public class SecondBean {
public void beginRequest(@Observes @Initialized(RequestScoped.class)
ServletRequest req) {}
public void endRequest(@Observes @Destroyed(RequestScoped.class)
ServletRequest req) {}
public void beginSession(@Observes @Initialized(SessionScoped.class)
HttpSession session) {}
public void endSession(@Observes @Destroyed(SessionScoped.class)
HttpSession session) {}
}
55. INTERCEPTORVS DECORATOR
• They are two Aspect Oriented mechanism
• Interceptor is technical oriented : transaction, security, logging
• Interceptor can be bound to any bean or bean method
• Decorator is business oriented : change the behaviour of a bean
• Decorator is for a given bean class
56. DECORATOR
• To use a decorator, your bean should implement an interface
• The decorator will implement the same interface and will be annotated
with @Decorator annotation
• It can be an abstract class (to avoid choosing methods to decorate)
• A decorator injects the bean it decorates with @Delegate annotation
60. …IS USEDTO BIND AN INTERCEPTOR
@Interceptor @Loggable
@Priority(Interceptor.Priority.APPLICATION)
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());
}
}
}
61. IT CAN BE PUT ON CLASS OR METHOD
@Loggable
public class MyBean {
@Inject HelloService service;
public void displayHello() {
display( service.hello();
}
}
62. OTHER FEATURES
• Stereotypes: to create annotation gathering multiple annotations
• Alternatives: to provide alternative to a bean for tests or specific
environments
• Specialization : to completely override an existing bean
• Check the spec on http://cdi-spec.org
63. THAT’S ALL FOR BASIC CDI
• If you want to learn advanced stuff come to check my over talk : CDI
advanced.
• follow @cdispec and @antoine_sd on twitter
• Questions ?