1/3 : introduction to CDI - Antoine Sabot-Durand

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

description

Allez plus Loin avec CDI En moins de 5 ans d’existence, Contexts and Dependency Injection (CDI) est devenue l’une des principale spécification de Java EE. Néanmoins, CDI est bien souvent perçu comme une simple solution d’injection de dépendance enrichie alors que cette spécification est bien plus riche que ça. Lors de cette présentation, après un rapide rappel des fonctionnalités de base de CDI, nous montrerons comment son utilisation avancée permet Java EE en intégrant des technologies legacy ou plus récent de manière naturelle. Nous finirons avec le travail en cours sur CDI 2.0 qui a commencé début septembre.

Transcript of 1/3 : introduction to CDI - Antoine Sabot-Durand

Page 1: 1/3 : introduction to CDI - Antoine Sabot-Durand

INTRODUCTION TO CONTEXTS AND DEPENDENCY INJECTION (CDI)

@antoine_sd

Page 2: 1/3 : introduction to CDI - Antoine Sabot-Durand

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: 1/3 : introduction to CDI - Antoine Sabot-Durand

WHAT IS CDI ?

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

Page 4: 1/3 : introduction to CDI - Antoine Sabot-Durand

Previously on CDI

Page 5: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 6: 1/3 : introduction to CDI - Antoine Sabot-Durand

IMPLEMENTATIONSJBoss Weld (Reference Implementation) Apache Open WebBeans

Page 7: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 8: 1/3 : introduction to CDI - Antoine Sabot-Durand

THE CDI BEAN• In Java EE 6 and 7 everything is a Managed Bean

• Managed 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 9: 1/3 : introduction to CDI - Antoine Sabot-Durand

BASIC DEPENDENCY INJECTION

@Inject

Page 10: 1/3 : introduction to CDI - Antoine Sabot-Durand

THIS IS A BEAN

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

Page 11: 1/3 : introduction to CDI - Antoine Sabot-Durand

DI IN CONSTRUCTORpublic class MyBean {

    private HelloService service;

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

Page 12: 1/3 : introduction to CDI - Antoine Sabot-Durand

DI IN SETTERpublic class MyBean {

    private HelloService service;

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

Page 13: 1/3 : introduction to CDI - Antoine Sabot-Durand

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

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

Page 14: 1/3 : introduction to CDI - Antoine Sabot-Durand

NO TYPE ERASURE IN CDI

public class MyBean {

    @Inject Service<User> userService;

@Inject Service<Staff> staffService;    }

Page 15: 1/3 : introduction to CDI - Antoine Sabot-Durand

NO TYPE ERASURE IN CDI

public class MyBean {

    @Inject Service<User> userService;

@Inject Service<Staff> staffService;    }

This w

orks

Page 16: 1/3 : introduction to CDI - Antoine Sabot-Durand

USING QUALIFIERS TO DISTINGUISH BEANS OF THE SAME TYPE

Page 17: 1/3 : introduction to CDI - Antoine Sabot-Durand

2 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 18: 1/3 : introduction to CDI - Antoine Sabot-Durand

…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 19: 1/3 : introduction to CDI - Antoine Sabot-Durand

…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 20: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 21: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 22: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 23: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 24: 1/3 : introduction to CDI - Antoine Sabot-Durand

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 25: 1/3 : introduction to CDI - Antoine Sabot-Durand

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 26: 1/3 : introduction to CDI - Antoine Sabot-Durand

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

Page 27: 1/3 : introduction to CDI - Antoine Sabot-Durand

MULTIPLE QUALIFIERS

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

@French @Securedpublic class FrenchHelloService implements HelloService {

}

Page 28: 1/3 : introduction to CDI - Antoine Sabot-Durand

MULTIPLE QUALIFIERS

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

@French @Securedpublic class FrenchHelloService implements HelloService {

}

Page 29: 1/3 : introduction to CDI - Antoine Sabot-Durand

RESERVED QUALIFIERS

@Default@Any@Named

Page 30: 1/3 : introduction to CDI - Antoine Sabot-Durand

PROGRAMMATIC LOOKUP

Page 31: 1/3 : introduction to CDI - Antoine Sabot-Durand

SOMETIMES CALLED “LAZY INJECTION”

public class MyBean {

    @Inject Instance<HelloService> service;

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

Page 32: 1/3 : introduction to CDI - Antoine Sabot-Durand

CHECK BEAN EXISTENCE AT RUNTIMEpublic class MyBean {

    @Inject Instance<HelloService> service;

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

Page 33: 1/3 : introduction to CDI - Antoine Sabot-Durand

INSTANCE<T> IS ITERABLEpublic interface Instance<T> extends Iterable<T>, Provider<T> { public Instance<T> select(Annotation... qualifiers); public <U extends T> Instance<U> select(Class<U> subtype, Annotation... qualifiers); public <U extends T> Instance<U> select(TypeLiteral<U> subtype, Annotation... qualifiers); public boolean isUnsatisfied(); public boolean isAmbiguous(); public void destroy(T instance);}

Page 34: 1/3 : introduction to CDI - Antoine Sabot-Durand

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: 1/3 : introduction to CDI - Antoine Sabot-Durand

SELECT A QUALIFIER AT RUNTIMEpublic class MyBean {

    @Inject @Any Instance<HelloService> services;

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

Page 36: 1/3 : introduction to CDI - Antoine Sabot-Durand

CONTEXTS

Page 37: 1/3 : introduction to CDI - Antoine Sabot-Durand

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: 1/3 : introduction to CDI - Antoine Sabot-Durand

CHOOSING THE RIGHT CONTEXT

@SessionScopedpublic class CartBean {

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

Page 39: 1/3 : introduction to CDI - Antoine Sabot-Durand

CHOOSING THE RIGHT CONTEXT

@ApplicationScopedpublic class CartBean {

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

Page 40: 1/3 : introduction to CDI - Antoine Sabot-Durand

CHOOSING THE RIGHT CONTEXT

@ApplicationScopedpublic class CartBean {

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

L !!!

Page 41: 1/3 : introduction to CDI - Antoine Sabot-Durand

CONVERSATION IS MANAGE BY DEV

@ConversationScopedpublic class CartBean {

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

Page 42: 1/3 : introduction to CDI - Antoine Sabot-Durand

NEW CONTEXTS CAN BE CREATED

@ThreadScopedpublic class CartBean {

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

Page 43: 1/3 : introduction to CDI - Antoine Sabot-Durand

PRODUCERS

Page 44: 1/3 : introduction to CDI - Antoine Sabot-Durand

CREATING BEAN FROM ANY CLASS

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

Page 45: 1/3 : introduction to CDI - Antoine Sabot-Durand

PRODUCERS MAY HAVE A SCOPE

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

Page 46: 1/3 : introduction to CDI - Antoine Sabot-Durand

GETTING INFO FROM INJECTION POINT

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

Page 47: 1/3 : introduction to CDI - Antoine Sabot-Durand

EVENTS

Page 48: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 49: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 50: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 51: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 52: 1/3 : introduction to CDI - Antoine Sabot-Durand

STEREOTYPES TO AVOID ANNOTATIONS HELL

Page 53: 1/3 : introduction to CDI - Antoine Sabot-Durand

BUILT-IN STEREOTYPE

@Named@RequestScoped@Documented@Stereotype@Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface Model { }

Page 54: 1/3 : introduction to CDI - Antoine Sabot-Durand

MY STEREOTYPE@Named@SessionScoped @MyQualifier @MyOtherQualifier@Documented@Stereotype@Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface MyModel { }

Page 55: 1/3 : introduction to CDI - Antoine Sabot-Durand

USAGE

@MyModelpublic class CircularBean {

}

Page 56: 1/3 : introduction to CDI - Antoine Sabot-Durand

DECORATORS & INTERCEPTORS

Page 57: 1/3 : introduction to CDI - Antoine Sabot-Durand

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: 1/3 : introduction to CDI - Antoine Sabot-Durand

INTERCEPTOR BINDING…

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

Page 59: 1/3 : introduction to CDI - Antoine Sabot-Durand

…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 60: 1/3 : introduction to CDI - Antoine Sabot-Durand

IT CAN BE PUT ON CLASS OR METHOD

@Loggablepublic class MyBean {

    @Inject HelloService service;

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

Page 61: 1/3 : introduction to CDI - Antoine Sabot-Durand

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 ?