introduction to cdi given at java one 2014

Post on 27-Nov-2014

745 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

INTRODUCTION TO CONTEXTS AND DEPENDENCY INJECTION (CDI)

@antoine_sd

ANTOINE SABOT-DURAND

• Senior Software Engineer @Red Hat

• Java & OSS :

• CDI co-spec lead

• CDI community development

• Tech Lead on Agorava

• @antoine_sd

WHAT IS CDI ?

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

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

IMPLEMENTATIONSJBoss Weld (Reference Implementation) Apache Open WebBeans

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

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.

BASIC DEPENDENCY INJECTION

@Inject

THIS IS A BEAN

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

DI IN CONSTRUCTORpublic class MyBean {

    private HelloService service;

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

DI IN SETTERpublic class MyBean {

    private HelloService service;

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

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

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

NO TYPE ERASURE IN CDI

public class MyBean {

    @Inject Service<User> userService;

@Inject Service<Staff> staffService;    }

This w

orks

USING QUALIFIERS TO DISTINGUISH BEANS OF THE SAME TYPE

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

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

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

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

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

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

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

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

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

MULTIPLE QUALIFIERS

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

@French @Console @Securedpublic class FrenchHelloService implements HelloService {

}

MULTIPLE QUALIFIERS

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

@French @Securedpublic class FrenchHelloService implements HelloService {

}

RESERVED QUALIFIERS

@Default@Any@Named

PROGRAMMATIC LOOKUP

SOMETIMES CALLED “LAZY INJECTION”

public class MyBean {

    @Inject Instance<HelloService> service;

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

CHECK BEAN EXISTENCE AT RUNTIMEpublic class MyBean {

    @Inject Instance<HelloService> service;

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

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

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

SELECT A QUALIFIER AT RUNTIMEpublic class MyBean {

    @Inject @Any Instance<HelloService> services;

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

CONTEXTS

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

CHOOSING THE RIGHT CONTEXT

@SessionScopedpublic class CartBean {

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

CHOOSING THE RIGHT CONTEXT

@ApplicationScopedpublic class CartBean {

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

L !!!

CONVERSATION IS MANAGE BY DEV

@ConversationScopedpublic class CartBean {

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

NEW CONTEXTS CAN BE CREATED

@ThreadScopedpublic class CartBean {

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

PRODUCERS

CREATING BEAN FROM ANY CLASS

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

PRODUCERS MAY HAVE A SCOPE

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

GETTING INFO FROM INJECTION POINT

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

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

EVENTS

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

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

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

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

DECORATORS & INTERCEPTORS

A DECORATOR

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

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

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

INTERCEPTOR BINDING…

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

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

IT CAN BE PUT ON CLASS OR METHOD

@Loggablepublic class MyBean {

    @Inject HelloService service;

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

THAT’S ALL FOR BASIC CDI

• If you want to learn advanced stuff come to : Going Farther with CDI 1.2 [CON5585] Monday 5:30pm

• visit : http://cdi-spec.org

• follow @cdispec and @antoine_sd on twitter

• Questions ?

top related