63
INTRODUCTION TO CONTEXTS AND DEPENDENCY INJECTION (CDI) @antoine_sd

Introduction to CDI

Embed Size (px)

Citation preview

Page 1: Introduction to CDI

INTRODUCTION TO CONTEXTS AND DEPENDENCY INJECTION (CDI)

@antoine_sd

Page 2: Introduction to CDI

ANTOINE SABOT-DURAND

• Senior Software Engineer @Red Hat

• Java & OSS :

• CDI co-spec lead

• CDI community development

• Tech Lead on Agorava

• @antoine_sd

Page 3: Introduction to CDI

WHAT IS CDI ?

• Java EE dependency injection standard• Strong typed and type safe• Context management• Observer pattern included (Event bus)• Highly extensible

Page 4: Introduction to CDI

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 M

R)

CDI 2.0 Starts

Q1 2016

CDI 2.0 released

Page 5: Introduction to CDI

IMPLEMENTATIONSJBoss Weld (Reference Implementation) Apache Open WebBeans

Page 6: Introduction to CDI

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

Page 7: Introduction to CDI

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.

Page 8: Introduction to CDI

BASIC DEPENDENCY INJECTION

@Inject

Page 9: Introduction to CDI

THIS IS A BEAN

public class HelloService {    public String hello() {        return "Hello World!";    }}

Page 10: Introduction to CDI

DI IN CONSTRUCTORpublic class MyBean {

    private HelloService service;

    @Inject    public MyBean(HelloService service) {        this.service = service;    }}

Page 11: Introduction to CDI

DI IN INITIALISER METHODpublic class MyBean {

    private HelloService service;

    @Inject    public void initService(HelloService service) {        this.service = service;    }}

Page 12: Introduction to CDI

DI IN FIELDpublic class MyBean {     @Inject private HelloService service;

    public void displayHello() {        display(service.hello();    }}

Page 13: Introduction to CDI

NO TYPE ERASURE IN CDI

public class MyBean {

    @Inject Service<User> userService;

@Inject Service<Staff> staffService;    }

Page 14: Introduction to CDI

NO TYPE ERASURE IN CDI

public class MyBean {

    @Inject Service<User> userService;

@Inject Service<Staff> staffService;    }

This w

orks

Page 15: Introduction to CDI

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)

Page 16: Introduction to CDI

TYPES OF A BEANpublic 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 }

Page 17: Introduction to CDI

USING QUALIFIERS TO DISTINGUISH BEANS OF THE SAME TYPE

Page 18: Introduction to CDI

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!";    }}

Page 19: Introduction to CDI

…NEED QUALIFIERS…@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD, PARAMETER}) public @interface French {}

@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD, PARAMETER}) public @interface English {}

Page 20: Introduction to CDI

…TO BE DISTINGUISHED.

@Frenchpublic class FrenchHelloService implements HelloService {    public String hello() {        return "Bonjour tout le monde!";    }}

@Englishpublic class EnglishHelloService implements HelloService {    public String hello() {        return "Hello World!";    }}

Page 21: Introduction to CDI

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

Page 22: Introduction to CDI

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    }}

Page 23: Introduction to CDI

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!";    }}

Page 24: Introduction to CDI

QUALIFIERS WITH MEMBERS 2/2public 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();    }}

Page 25: Introduction to CDI

MULTIPLE QUALIFIERS

public class MyBean {    @Inject @French HelloService service;}

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 26: Introduction to CDI

MULTIPLE QUALIFIERS

public class MyBean {    @Inject @French @Console HelloService service;}

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 27: Introduction to CDI

MULTIPLE QUALIFIERS

public class MyBean {    @Inject @French @Console @Secured HelloService service;}

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 28: Introduction to CDI

MULTIPLE QUALIFIERS

public class MyBean {    @Inject @French @Console @Secured HelloService service;}

@French @Securedpublic class FrenchHelloService implements HelloService {

}

Page 29: Introduction to CDI

MULTIPLE QUALIFIERS

public class MyBean {    @Inject @French @Console @Secured HelloService service;}

@French @Securedpublic class FrenchHelloService implements HelloService {

}

Page 30: Introduction to CDI

RESERVED QUALIFIERS

@Default@Any@Named

Page 31: Introduction to CDI

PROGRAMMATIC LOOKUP

Page 32: Introduction to CDI

SOMETIMES CALLED “LAZY INJECTION”

public class MyBean {

    @Inject Instance<HelloService> service;

    public void displayHello() {        display( service.get().hello() );    }}

Page 33: Introduction to CDI

CHECK BEAN EXISTENCE AT RUNTIMEpublic class MyBean {

    @Inject Instance<HelloService> service;

    public void displayHello() {        if (!service.isUnsatisfied()) {            display( service.get().hello() );        }    }}

Page 34: Introduction to CDI

LOOP ON ALL BEANS OF A GIVEN TYPEpublic class MyBean {

    @Inject @Any Instance<HelloService> services;

    public void displayHello() {        for (HelloService service : services) {            display( service.hello() );        }    }}

Page 35: Introduction to CDI

SELECT A QUALIFIER AT RUNTIMEpublic class MyBean {

    @Inject @Any Instance<HelloService> services;

    public void displayHello() {        display(             service.select( new AnnotationLiteral()<French> {})                .get() );    }}

Page 36: Introduction to CDI

CONTEXTS

Page 37: Introduction to CDI

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

Page 38: Introduction to CDI

CHOOSING THE RIGHT CONTEXT

@SessionScopedpublic class CartBean {

    public void addItem(Item item) { ...    } }

Page 39: Introduction to CDI

CHOOSING THE RIGHT CONTEXT

@ApplicationScopedpublic class CartBean {

    public void addItem(Item item) { ...    } }

Page 40: Introduction to CDI

CHOOSING THE RIGHT CONTEXT

@ApplicationScopedpublic class CartBean {

    public void addItem(Item item) { ...    } } FAI

L !!!

Page 41: Introduction to CDI

CONVERSATION IS MANAGE BY DEV

@ConversationScopedpublic class CartBean {

    public void addItem(Item item) { ...    } }

Page 42: Introduction to CDI

NEW CONTEXTS CAN BE CREATED

@ThreadScopedpublic class CartBean {

    public void addItem(Item item) { ...    } }

Page 43: Introduction to CDI

PRODUCERS

Page 44: Introduction to CDI

CREATING BEAN FROM ANY CLASS

@Producespublic MyNonCDIClass myProducer() {return new MyNonCdiClass();}...@InjectMyNonCDIClass bean;

Page 45: Introduction to CDI

DISPOSER ARE OPTIONAL

@Producespublic MyNonCDIClass myProducer() {return new MyNonCdiClass();}

// Will be call at the instance end of lifepublic void releaseMyInstance(@Disposes MyNonCdiClass inst) {inst.clean();}

Page 46: Introduction to CDI

PRODUCERS MAY HAVE A SCOPE

@Produces@RequestScopedpublic FacesContext produceFacesContext() { return FacesContext.getCurrentInstance();}

Page 47: Introduction to CDI

GETTING INFO FROM INJECTION POINT

@Producespublic Logger produceLog(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember() .getDeclaringClass().getName());}

Page 48: Introduction to CDI

REMEMBER : “NO TYPE ERASURE”

@Producespublic <K, V> Map<K, V> produceMap(InjectionPoint ip) { if (valueIsNumber(ip.getType())) { return new TreeMap<K, V>(); } return new HashMap<K, V>();}

Page 49: Introduction to CDI

EVENTS

Page 50: Introduction to CDI

A NICE WAY TO ADD DECOUPLINGpublic 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()); }}

Page 51: Introduction to CDI

EVENTS CAN BE QUALIFIEDpublic 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) {}}

Page 52: Introduction to CDI

AS ALWAYS “NO TYPE 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) {}}

Page 53: Introduction to CDI

SOME BUILT-IN EVENTSpublic 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) {}}

Page 54: Introduction to CDI

DECORATORS & INTERCEPTORS

Page 55: Introduction to CDI

INTERCEPTOR VS 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

Page 56: Introduction to CDI

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

Page 57: Introduction to CDI

A DECORATOR

@Decorator@Priority(Interceptor.Priority.APPLICATION)public abstract class HelloDecorator implements HelloService {

// The decorated service may be restricted with qualifiers    @Inject @Delegate HelloService service;

    public String hello() {        return service.hello() + "-decorated";    }}

Page 58: Introduction to CDI

INTERCEPTOR

Interceptor Binding Annotation

Interceptor Class

+

Page 59: Introduction to CDI

INTERCEPTOR BINDING…

@InterceptorBinding@Target({METHOD, TYPE}) @Retention(RUNTIME)public @interface Loggable {}

Page 60: Introduction to CDI

…IS USED TO 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());        }    } }

Page 61: Introduction to CDI

IT CAN BE PUT ON CLASS OR METHOD

@Loggablepublic class MyBean {

    @Inject HelloService service;

    public void displayHello() {        display( service.hello();    }}

Page 62: Introduction to CDI

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

Page 63: Introduction to CDI

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 ?