160
Context and Dependency Injection Maxime Lefrançois ([email protected] ), M2 MIAGE Casablanca 2012-2013

Context and Dependency Injection Maxime Lefrançois ([email protected]), M2 MIAGE Casablanca [email protected]

Embed Size (px)

Citation preview

Page 1: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

Context and Dependency Injection

Maxime Lefrançois ([email protected]), M2 MIAGE Casablanca 2012-2013

Page 2: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

2

Introduction

Page 3: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

3

Questions rébarbatives Pour un objet A ...

Combien de clients est-ce que A peut avoir ? est-ce que A est multi-threadé ? Comment j’ai accès à A dans un autre objet B ? Est-ce que je dois le détruire explicitement ? Où dois-je garder une référence à A si je ne

l’utilise pas ? Comment définir des implémentations

alternatives, pour en changer au moment du déploiement ?

Comment partager cet objet entre d’autres objets ?

Page 4: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

4

Context and Dependency Injection= CDI (JSR-299) CDI est un modèle riche de programmation

couplage faible avec typage fort

Page 5: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

5

CDI Gestion du cycle de vie des objets avec

état, liés à des contextes injection de dépendance avec types intercepteurs d’objets et décorateurs notifications d’évènements + SPI (pour extensions)

Page 6: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

6

CDI aboutissement des frameworks java:

Seam, Guice, Spring

Au coeur de la plateforme Java EE mais pas limité à Java EE

implémentation de référence de CDI : Weld(Seam Framework)

Page 7: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

7

Beans – couplage faible Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort1. un bean spécifie seulement le type et la

sémantique des beans dont il dépend, il ne connait pas: leur cycle de vie, leur implémentation concrete leur modèle de threading

Page 8: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

8

Beans – couplage faible Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort2. un bean spécifie seulement le type et la

sémantique des beans dont il dépend,leur implémentation, leur cycle de vie, ...peuvent varier en fonction du scénario de déploiement

Page 9: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

9

Beans – couplage faible Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort3. Les notifications d’évènement découplent

complètement:les producteur d’évènement

les consommateurs d’évènements

Page 10: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

10

Beans – couplage faible Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort4. Les intercepteurs découplent:

les considérations technique la logique métier

(programmation par aspect)

exemple: sécurité, transactions, ...

Page 11: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

11

Beans – couplage faible Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort5. Les décorateurs permettent de

compartimenter les logiques métier

Page 12: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

12

Beans – typage fort Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort6. le couplage ne se fait pas par des chaînes de

caractères, on utilise des annotations: les qualifieurs

Page 13: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

13

Beans – typage fort Un objet avec état lié à un contexte = un

bean couplage faible avec typage fort7. l’utilisation du fichier descripteur

est limitée pour les informations qui dépendent du déploiement

 META-INF/beans.xml

Page 14: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

14

Notion de Bean Quels beans on connaît ? C’est quoi un bean ?

Page 15: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

15

Notion de Bean Quels beans on connaît ?

les JSF Managed Bean: Un objet géré par un conteneur, avec des restrictions

minimes de programmation ~ un POJO (Plain Old Java Object)

Ont des propriétés

Supportent quelques services basiques: injection de ressources callbacks de cycle de vie (@PostConstruct, @PreDestroy, ...) des intercepteurs (définis dans le bean = couplage fort !!!)

c’est quoi les propriétés d’un Managed Bean ?

Page 16: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

16

Pour commencer, une petite application pour vérifier quelques notions des Servlets et JSF2…

Corrigez les erreurs !

Exercice 1

Page 17: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

17

Notion de Bean Quels beans on connaît ?

les javabeans les Managed Bean les EJB Session Beans / Message-driven Beans Les beans selon Spring Les beans selon Seam ...

Page 18: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

18

Notion de Bean

C’est quoi un bean ?CDI donne une définition claire:

Tout objet qui a un constructeur sans paramètre (ou un constructeur annoté @Inject) (ou un producteur de beans)

Page 19: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

19

Un exemple d’injection

public class SentenceParser {    public List<String> parse(String text) { ... } }

@Stateless public class SentenceTranslator implements Translator {    public String translate(String sentence) { ... } }

@Local public interface Translator {    public String translate(String sentence); }

Une classe avec une méthode qui découpe un texte en phrases

Un stateless session bean capable de traduire des phrases

Son interface locale Translator

est-ce que c’est un bean ?

est-ce que c’est un bean ?

est-ce que c’est un bean ?

Page 20: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

20

Un exemple d’injection

On écrit donc une classe pour traduire un document en entierpublic class TextTranslator {    private SentenceParser sentenceParser;    private Translator sentenceTranslator;         @Inject    TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {       this.sentenceParser = sentenceParser;       this.sentenceTranslator = sentenceTranslator;    }         public String translate(String text) {       StringBuilder sb = new StringBuilder();       for (String sentence: sentenceParser.parse(text)) {           sb.append(sentenceTranslator.translate(sentence));       }       return sb.toString();    } }

est-ce que c’est un bean ?

Page 21: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

21

Un exemple d’injection

On écrit donc une classe pour traduire un document en entierpublic class TextTranslator {    private SentenceParser sentenceParser;    private Translator sentenceTranslator;         @Inject    TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {       this.sentenceParser = sentenceParser;       this.sentenceTranslator = sentenceTranslator;    }         public String translate(String text) {       StringBuilder sb = new StringBuilder();       for (String sentence: sentenceParser.parse(text)) {           sb.append(sentenceTranslator.translate(sentence));       }       return sb.toString();    } }

est-ce que c’est un bean ? OUI. Le conteneur va appeler le constructeur annoté @Inject, et injecter d’autres beans dans les paramètres du constructeur.

Les paramètres du constructeur

annoté @Inject seront injectés

Page 22: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

22

Un exemple d’injection

On écrit donc une classe pour traduire un document en entierpublic class TextTranslator {    private SentenceParser sentenceParser;    private Translator sentenceTranslator;         @Inject    TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {       this.sentenceParser = sentenceParser;       this.sentenceTranslator = sentenceTranslator;    }         public String translate(String text) {       StringBuilder sb = new StringBuilder();       for (String sentence: sentenceParser.parse(text)) {           sb.append(sentenceTranslator.translate(sentence));       }       return sb.toString();    } }

On peut maintenant injecter une instance de TextTranslator :Dans un constructeur, une méthode, un attribut d’un beanOu dans un attribut ou une méthode d’une servlet ou d’un autre composant EJB

Page 23: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

23

Un exemple d’injection

@Named @RequestScoped public class TranslateController {   @Inject TextTranslator textTranslator;

   private String inputText;    private String translation;

   // JSF action method, perhaps    public void translate() {       translation = textTranslator.translate(inputText);     }

   public String getInputText() {       return inputText;    }

   public void setInputText(String text) {       this.inputText = text;    }

   public String getTranslation() {       return translation;    } }

Exemple de Managed Bean qui utilise une instance injectée de TextTranslator

Page 24: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

24

Utiliser CDI

Page 25: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

25

Dans un projet JEE 6 Avec Netbeans Cocher la case « utiliser CDI » au

moment de la création du projet Java Web ou Java EE Ça crée simplement un fichier descripteur

META-INF/beans.xml

Avec Glassfish: il suffit d’avoir un fichier descripteur META-INF/beans.xml

(même vide !) Weld, l’implémentation de référencede CDI, est fournie

Avec Tomcat, Jetty, … Suivre la procédure:

http://docs.jboss.org/weld/reference/latest/en-US/html/environments.html#d0e5225

Page 26: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

26

Projet Java SE avec CDI On utilise l’implémentation de référence:

Weld http://www.seamframework.org/Weld/WeldDistributionDow

nloads

Le jar: weld-se-core.jar Ou avec Maven:

Est-ce qu’on doit écrire une classe principale avec un main ?

<dependency> <groupId>org.jboss.weld.se </groupId> <artifactId>weld-se </artifactId> <version>CHOISIR LA DERNIERE FINALE</version> </dependency>

Page 27: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

27

Projet Java SE avec CDI Est-ce qu’on doit écrire une classe principale

avec un main ? Réponse: NON !!! Où est l’instance du conteneur de beans ??? C’est possible de l’instantier nous-même, mais

compliqué. Le plus simple: une méthode main est fournie

avec weld-se, Le point d’entrée de notre application est un

écouteur Écouteur de l’évènement ContainerInitialized On récupère les paramètres de la ligne de

commande par injection

@Singleton public class HelloWorld {    public void printHello(@Observes ContainerInitialized event,  @Parameters List<String> parameters) {        System.out.println("Hello " + parameters.get(0));    } }

Page 28: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

28

²

Quelle différence entre les deux applications 2a, 2b ?

La classe Init: La bonne façon d’avoir une méthode d’un bean

appelée dès que le l’application est déployée (servlets ok, injection ok …)

Le singleton est un singleton EJB !

A votre avis, pourquoi est-ce que le bean Generator est instantié deux fois? (cf. la console)

Exercice 2

Page 29: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

Introduction à CDI

Page 30: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

30

Anatomie d’un Bean Un ensemble non vide de types Un ensemble non vide de qualifieurs Un contexte En option: Un nom EL Un ensemble de liens de type intercepteurs Une implémentation En option: être un bean alternatif

Page 31: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

31

Type, qualifieur et injection de dépendance On a une référence à un bean par injection de

dépendance, un attribut injecté spécifie un « contrat » que le bean injecté doit respecter: Un ensemble non vide de types Un ensemble non vide de qualifieurs

Page 32: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

32

Type, qualifieur et injection de dépendance Ensemble non vide de types:

ex1:public class Business  {    ... }

ex2 : public class BookShop        extends Business        implements Shop<Book> {    ... }

Page 33: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

33

Type, qualifieur et injection de dépendance Et si on souhaite injecter un objet de type

Business ? ambiguité ! Le client doit spécifier un/des qualifieurs

Un qualifieur est une annotation:ex:

Permet de désambiguiser l’objet à injecter, sans utiliser une chaîne de caractères

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

Page 34: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

34

Type, qualifieur et injection de dépendance Pour ce point d’injection:

@Inject @CreditCard PaymentProcessor paymentProcessor;

Le conteneur cherche un bean qui satisfait le contrat. Si il en trouve exactement un, il injecte une

instance de ce bean Sinon, il lance une erreur

exemple de bean qui satisfait le contrat:@CreditCard public class CreditCardPaymentProcessor      implements PaymentProcessor { ... }

Page 35: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

35

Type, qualifieur et injection de dépendance Un ensemble non vide de types

toujours au moins le type Object

Un ensemble non vide de qualifieursSi aucun qualifieur n’est spécifié, il y a le qualifieur par défaut: @Default

Page 36: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

36

1- Provoquez une erreur: point d’injection ambigüe,

2- Provoquez une erreur: point d’injection insatisfiable

3- Faites en sorte que le nombre affiché soit vraiment aléatoire

A votre avis, pourquoi le nombre ne change pas ? Et le bean generator n’est instantié qu’une seule fois ?

Exercice 3

Page 37: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

37

Contexte (scope) Le contexte d’un bean définit le cycle de vie

de ses instances

Un contexte est représenté par une annotation ex: @RequestScoped, @SessionScoped, …

Page 38: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

38

Contexte (scope) Une instance d’un bean session-scoped est

liée à un session d’un utilisateur et est partagé par toutes les requêtes executées dans cette session (on ne peut pas l’enlever, ni le changer)

Un bean a un contexte. Si aucun contexte n’est défini, le contexte par défaut est: @Dependent

Page 39: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

39

Nom EL (EL= Expression Language) Pour référencer un bean et ses propriétés dans une JSF ou une

JSP, on associe un nom EL

Annotation @Namedex:public @SessionScoped @Named("cart") class ShoppingCart implements Serializable { ...  public List<Item> getLineItems() {...} ....}

On peut ensuite l’utiliser dans une JSF ou une JSP:<h:dataTable value="#{cart.lineItems}" var="item">   ...</h:dataTable>

Page 40: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

40

Nom EL (EL= Expression Language) Pour référencer un bean et ses propriétés dans une JSF ou une

JSP, on associe un nom EL

Annotation @Namedex:public @SessionScoped @Named("cart") class ShoppingCart implements Serializable { ...  public List<Item> getLineItems() {...} ....}

On peut ensuite l’utiliser dans une JSF ou une JSP:<h:dataTable value="#{cart.lineItems}" var="item">   ...</h:dataTable>

Propriété lineItems !

Page 41: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

41

Nom EL (EL= Expression Language) Valeur par défaut:

public @SessionScoped @Namedclass ShoppingCart implements Serializable { ...  public List<Item> getLineItems() {...} ....}

<h:dataTable value="#{???.lineItems}" var="item">   ...</h:dataTable>

Comme dans Exercice1

Page 42: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

42

Alternatives Un bean peut être déclaré être une

implémentation alternative:

public @Alternative class MockPaymentProcessor extends PaymentProcessorImpl { ... }

Désactivées par défaut, on peut choisir une alternative à utiliser au moment du déploiement en le spécifiant dans le descripteur META-INF/beans.xml

Page 43: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

43

Intercepteurs Existent dans Java EE 5 import javax.interceptor.AroundInvoke;

import javax.interceptor.InvocationContext;public class TracingInterceptor {       @AroundInvoke    public Object logCall(InvocationContext context) throws Exception{        System.out.println("Invoking method: " + context.getMethod());        return context.proceed();        System.out.println(« Finished invoking method: " + context.getMethod());    }}

@Interceptors(TracingInterceptor.class, ...)@Statelesspublic class HelloWorldBean implements HelloWorld {         public void sayHello() {        System.out.println("Hello!");    }}

Page 44: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

44

Intercepteurs Existent dans Java EE 5, mais contre-intuitif !

On spécifiait directement la classe de l’intercepteur dans l’EJB !

On spécifiait directement l’ordre des intercepteurs dans l’EJB !

Page 45: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

45

Intercepteurs Dans CDI:

1. annotation de lien à un (groupe d’intercepteurs)@InterceptorBinding @Inherited @Target( { TYPE, METHOD }) @Retention(RUNTIME) public @interface Transactional {}

2. L’intercepteur déclare cette annotation:public @Transactional @Interceptor class TransactionInterceptor { ... }

3. On applique cet aspect à un bean:public @SessionScoped @Transactional class ShoppingCart implements Serializable { ... }

4. On active les intercepteurs et on définit leur ordre dans le fichier descripteur MEAT-INF/beans.xml

Page 46: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

46

Quelles classes sont des beans ? Les Managed Beans Les EJB Session Beans Les Producer Methods Les Producer Fields

(Injectables, décorables, interceptables, ...)

Page 47: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

47

Les Managed Beans Des POJOs gérés par le conteneur, un petit ensemble de services:

injection de ressource, callbacks du cycle de vie intercepteurs

JSR-316 Managed Beans (22 pages)

Page 48: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

48

Les Managed Beans Annotation @ManagedBean

pas nécessaire avec CDI ! Le conteneur CDI considère chaque classe

comme un managed beans si elle: n’est pas une classe non-static interne est une classe concrètes, ou annotées

@Decorator n’est pas un composant EJB (un session bean...) n’implémente pas

javax.enterprise.inject.spi.Extension a un constructeur approprié : soit

un constructeur sans paramètres un constructeur annoté @Inject

Page 49: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

49

Les Managed Beans Attention, les JPA Entity Beans sont

techniquement des Managed Beans, mais

IL NE FAUT PAS INJECTER UN ENTITY BEAN

IL NE FAUT PAS ASSIGNER UN CONTEXTE AUTRE QUE @Dependent A UN ENTITY BEAN

Page 50: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

50

Les Session Beans des services avancés proposés par le

conteneur d’EJB: sécurité et gestion des transactions au niveau

des méthodes, gestion des accès concurrents, passivation des instances des stateful session

beanset pooling des stateless session beans,

invocation de session beans distants ou de web services,

timers, méthodes asynchrones, ...

JSR-318 Enterprise JavaBeans Specification (626 pages)

Page 51: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

51

Session Bean ou Managed Bean ? Dans CDI, On peut injecter:

un session bean dans un autre session bean, Un managed dans un session bean, Un session bean dans un managed bean, ...

Dans CDI, Un managed bean peut observer un évènement

lancé par un session bean, etc.

QUESTION: Quand doit-on utiliser un session bean plutôt qu’un managed bean ?

Page 52: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

52

Session Bean ou Managed Bean ? Dans CDI, On peut injecter:

un session bean dans un autre session bean, Un managed dans un session bean, Un session bean dans un managed bean, ...

Dans CDI, Un managed bean peut observer un évènement

lancé par un session bean, etc.

QUESTION: Quand doit-on utiliser un session bean plutôt qu’un managed bean ?Quand on a besoin des services offerts

par le conteneur d’EJB !

Page 53: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

53

Producer Methods Comment injecter un int

au hasard entre 1 et 100 ?

Page 54: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

54

Producer Methods Comment injecter un int

au hasard entre 1 et 100 ?

@ApplicationScoped public class RandomNumberGenerator {        private Random random = new Random(System.currentTimeMillis());            @Produces @Random @Named int getRandomNumber() {       return random.nextInt(100);    }     }

Page 55: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

55

Producer Methods Comment injecter un int

au hasard entre 1 et 100 ?

@ApplicationScoped public class RandomNumberGenerator {        private Random random = new Random(System.currentTimeMillis());            @Produces @Random @Named int getRandomNumber() {       return random.nextInt(100);    }     }

C’est cette méthode qui sera appelée pour injecter une instance d’un bean avec le type int et le qualifieur @Random

@Injectpublic UnBean(@Random int rand, ...) { ... }

@Inject @Random int rand;

Un constructeur

Un attribut...

Des méthodes

Page 56: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

56

Producer Methods Comment choisir au moment de l’execution

quelle implémentation d’un type de bean on veut instantier et injecter ?

Page 57: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

57

Producer Methods Comment choisir au moment de l’execution

quelle implémentation d’un type de bean on veut instantier et injecter ?

Une Producer Method

Page 58: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

58

Producer Methods Comment injecter un objet qui est obtenu en

requêtant un service ou une ressource transactionnelle, par exemple un requête JPA ?

Page 59: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

59

Producer Methods Comment injecter un objet qui est obtenu en

requêtant un service ou une ressource transactionnelle, par exemple un requête JPA ?

Une Producer Method

Page 60: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

60

Producer Fields Un raccourci pour les cas simples,

plus simple que les Producer Methods:Les Producer Fields

public class Shop {    @Produces PaymentProcessor paymentProcessor = ....;    @Produces @Catalog List<Product> products = ....; }

Page 61: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

61

Ecrivez une producer method et/ou un producer field pour l’entier aléatoire (qualifieur @Rand) et l’entier max

Etudiez l’enchaînement des appels de méthode

Vérifiez que le bean Game est bien associé à une session

Exercice4

Page 62: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

Injection

Page 63: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

63

Points d’injection d’un bean Maintenant on a des beans,

on peut les injecter.

Annotation @javax.inject.Inject

Page 64: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

64

Points d’injection d’un bean Constructeur d’un autre bean

public class Checkout {             private final ShoppingCart cart;         @Inject    public Checkout(ShoppingCart cart) {       this.cart = cart;    } }

Un bean ne peut avoir qu’un seul constructeur annoté @Inject

Page 65: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

65

Points d’injection d’un bean Méthode d’initialisation

public class Checkout {             private ShoppingCart cart;    @Inject    void setShoppingCart(ShoppingCart cart) {       this.cart = cart;    }      }

Un bean peut avoir plusieurs méthodes d’initialisation

Page 66: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

66

Points d’injection d’un bean Injection d’attribut

public class Checkout {             private @Inject ShoppingCart cart;

}

Un bean peut avoir plusieurs méthodes d’initialisation

Page 67: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

67

Points d’injection d’un bean1. Le conteneur appelle le constructeur du

bean(celui par défaut ou celui annoté @Inject), pour obtenir une instance du bean.

2. Le conteneur initialise les valeurs des attributs injectés du bean.

3. Le conteneur appelle les méthodes d’initialisation du bean (sans ordre standard).

4. La méthode annotée @PostConstruct est appelée

Page 68: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

68

Points d’injection d’un bean D’autre injections de paramètres sont

possibles dans CDI, par exemple dans les Producer Methods

@Produces Checkout createCheckout(ShoppingCart cart) {     return new Checkout(cart); }

Page 69: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

69

Qu’est-ce qui est injecté ? Algorithme typesafe resolution:vérifie qu’un et un seul bean peut être injecté à

chaque foisAu moment de l’initialisation !

Le plus simple: un seul bean d’un certain type, et un point d’injection avec ce

type...

Page 70: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

70

Qu’est-ce qui est injecté ? Si plusieurs beans correspondent pour le point

d’injection ? On peut utiliser un Qualifieur Les Qualifieurs peuvent avoir des membres On peut combiner plusieurs Qualifieurs Certains beans peuvent être des Alternatives

Page 71: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

71

Qualifieurs Une annotation !

(et non pas une chaîne de caractères comme dans la spécification des managed beans) plus de sémantique moins d’erreurs de typographie

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

Page 72: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

Qualifieurs Qualifieur pour annoter:

Un bean

@Synchronous public class SynchronousPaymentProcessor implements PaymentProcessor {    public void process(Payment payment) { ... } }

72

Page 73: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

73

Qualifieur pour annoter: Un point d’injection

@Produces PaymentProcessor getPaymentProcessor(@Synchronous PaymentProcessor syncPaymentProcessor,                                      @Asynchronous PaymentProcessor asyncPaymentProcessor) {    return isSynchronous() ? syncPaymentProcessor : asyncPaymentProcessor; }

Qualifieurs

@Inject @Synchronous PaymentProcessor syncPaymentProcessor;

@Inject public void setPaymentProcessors(@Synchronous PaymentProcessor syncPaymentProcessor) {    this.syncPaymentProcessor = syncPaymentProcessor; }

@Inject public Checkout(@Synchronous PaymentProcessor syncPaymentProcessor) {    this.syncPaymentProcessor = syncPaymentProcessor; }

Page 74: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

74

Qualifieur @Default Rappel: un bean a au moins un Qualifieur.

Si aucun qualifieur n’est écrit explicitement, c’est comme si il y avait le qualifieur @Default

Page 75: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

75

Qualifieur @Any

Quel est le qualifieur du bean qui sera injecté ?

Comment dire: « n’importe quel bean » ?Qualifieur @Any

il y a de grandes chances pour que ce point d’injection soit ambiguë Exception

@Inject PaymentProcessor paymentProcessor;

@Inject @Any PaymentProcessor paymentProcessor;

Page 76: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

76

Qualifieur avec membre

Une annotation avec membre:

@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Synchronous { PaymentMethod value();}

public enum PaymentMethod { CHEQUE, CB, CASH; }

ici on utilise une énumeration pour aggréger plusieurs qualifieurs en un seul

@PayBy(CHEQUE)public class PayByCheckBean {...}

@Inject @PayBy(CHEQUE) PayByCheckBean pbcb;

ce bean correspond pour ce point d’injection

Page 77: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

77

Vérifiez dans votre application, avec un qualifieur @Number qui a un membre qui est une énumeration: ALEATOIRE, MAX

Exercice5

Page 78: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

78

Qualifieur avec membreannotation @Nonbinding

Un membre d’une annotation qui ne doit pas servir à restreindre les beans injectables

@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Synchronous { PaymentMethod value(); @Nonbinding String comment() default "";}

Sert:-soit à proposer un commentaire (comme ici)-soit à choisir le bean au moment de l’execution (en utilisant une Producer method et l’introspection java)

Page 79: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

79

Plusieurs qualifieurs

Seuls les beans qui ont TOUS les qualifieurs sont injectables

Tous les beans qui ont AU MOINS ce qualifieursont injectables

@Inject @PayBy(CHEQUE) @Asynchronous PayByCheckBean pbcb;

@Inject @PayBy(CHEQUE) PayByCheckBean pbcb;

Page 80: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

80

Alternatives

Un bean peut être déclaré être une implémentation alternative:

Désactivées par défaut, on peut choisir une alternative à utiliser au moment du déploiement en le spécifiant dans le descripteur META-INF/beans.xml

@Alternative @Synchronous @Asynchronous public class MockPaymentProcessor implements PaymentProcessor {    public void process(Payment payment) { ... } }

<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">   <alternatives>         <class>org.mycompany.mock.MockPaymentProcessor</class>   </alternatives></beans>

Injectable pour @Synchronous Injectable pour @Asynchronous

Page 81: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

81

²

Ecrivez un bean MockGame, alternatif qui étend Game et redéfinit les méthodes: getMaxNumber() : résultat toujours égal à 0 getRandomNumber() : résultat toujours égal à 0

Activez cette classe alternative dans beans.xml

Observez les deux résultats différents dans le navigateur

Exercice6

Page 82: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

82

²

Ça ne fonctionne pas, pourquoi ? Un bean alternatif remplace un bean

seulement pour les points d’injection, Pas dans les expressions EL Si ce bean contient des méthodes producers, ces

méthodes ne sont pas remplacées Pour remplacer complètement un bean:

@Alternative @Specialize Essayez avec MockGame

Exercice6

Page 83: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

83

Programmatic lookup Dans certaines situations, l’injection n’est pas le

meilleur moyen d’obteinur une référence contextuelle avec une combinaison spécifique d’un type et de qualifieurs Si le type du bean ou les qualifieurs varient

dynamiquement au moment de l’execution, ou Selon le déploiement, il peut ne pas y avoir de

combinaison type/qualifieurs acceptable si on veut itérer sur les beans d’un certain type...

Dans ces situations, on peut injecter une instance de l’objet paramétré Instance@Inject Instance<PaymentProcessor> paymentProcessorSource;

Page 84: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

84

Programmatic lookup

Si exactement un bean correspond : get()

Sinon : iterator()

@Inject @PayBy(CHEQUE) Instance<PaymentProcessor> paymentProcessorSource;

@Inject @Any Instance<PaymentProcessor> paymentProcessorSource;

PaymentProcessor paymentProcessor = paymentProcessorSource.get();

for(PaymentProcessor p : paymentProcessorSource) { ...}

Page 85: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

85

Programmatic lookup

On peut spécifier des qualifieurs au point d’injection

Ou spécialiser par la suite dynamiquement :

méthode select(Annotation ... qualifiers)

Attention, on doit obtenir une instance de notre qualifieur, une annotation est une interface, on peut donc pas juste écrire new Asynchronous() par exemple. On peut utiliser la classe utilitaire AnnotationLiteral<Asynchronous>...

Attention, ça ne n’est pas utilisable pour une qualifieur avec membre

@Inject @PayBy(CHEQUE) Instance<PaymentProcessor> paymentProcessorSource;

paymentProcessorSource.select(new AnnotationLiteral<Asynchronous>(){});

@Inject @Any Instance<PaymentProcessor> paymentProcessorSource;

Page 86: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

86

L’objet InjectionPoint Certains objets dépendent de l’endroit où ils

sont injectés pour faire ce qu’ils doivent faire.. le log doit connaître la classe de l’objet où il est l’injection d’un paramètre HTTP dépend du nom

du paramètre qui a été spécifié au point d’injection

l’injection du résultat d’une expression EL dépend de l’expression spécifiée au point d’injection

Page 87: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

87

L’objet InjectionPoint

Exemple du log: habituellement:

Avec CDI il suffit d’écrire une petite Producer method:

et on peut alors utiliser dans chaque classe:

Logger log = Logger.getLogger(MyClass.class.getName());

class LogFactory {    @Produces Logger createLogger(InjectionPoint injectionPoint) {        return Logger.getLogger(injectionPoint .getMember(). getDeclaringClass().getName());     } }

@inject Logger log;

Page 88: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

88

L’objet InjectionPoint

Exemple du paramètre HTTP: un type de qualifieur avec membre @Nonbinding

une petite Producer method

@BindingType @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface HttpParam {    @Nonbinding public String value(); }

class HttpParams    @Produces @HttpParam("")    String getParamValue(InjectionPoint ip) {       ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance()

.getExternalContext().getRequest(); String value = ip.getAnnotated().getAnnotation(HttpParam.class).value();      return request.getParameter(value);    } }

Page 89: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

89

L’objet InjectionPoint

Exemple du paramètre HTTP: et c’est parti !

@Inject @HttpParam("username") String uname; @Inject @HttpParam("password") String pwd;

Page 90: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

90

L’objet InjectionPoint

public interface InjectionPoint {    public Type getType();    public Set<Annotation> getQualifiers();    public Bean<?> getBean();    public Member getMember();    public Annotated getAnnotated();    public boolean isDelegate();    public boolean isTransient(); }

Page 91: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

91

Au moment où l’application est initialisée: Listez l’ensemble des beans qui ont le qualifieur

@Rand Pour chacun de ces beans, affichez le nom qualifié

de leur classe

Exercice7

Page 92: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

4- Portées et Contextes

Page 93: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

93

Portée Quatre portées définis par CDI:

@javax.enterprise.context.RequestScoped @javax.enterprise.context.SessionScoped @javax.enterprise.context.ApplicationScoped @javax.enterprise.context.ConversationScoped

Page 94: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

94

Portée Dans une application web

Chaque requête de servet a accès aux portées actives de type requête, session et application

Une requête JSF a accès à une portée active de type Conversation

Page 95: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

95

Portée Dans Java EE, les portées de type requête et

application sont actives Pendant l’invocation d’une méthode EJB remote Pendant l’invocation d’une méthode EJB

asynchrone Pendant un EJB timeout Pendant la réception d’un message par un

message-driven bean Pendant la réception d’un message par un

MessageListener Pendant l’invocation d’un service web

Page 96: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

96

Portée Les @SessionScoped et @ConversationScoped

doivent être sérialisable.

Page 97: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

97

Le contexte Conversation

Similaire au contexte Session, mais: c’est l’application qui définit le début et la fin Pour JSF: contient l’état d’un seul onglet d’un navigateur

La conversation représente donc une tâche, « ce sur quoi l’utilisateur travaille »

Le contexte Conversation est actif pendant une requête JSF, et par défaut est supprimée à la fin de la requête. Si on veut la garder, on doit signaler explicitement que la requête est de type « long-running conversation »

Page 98: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

98

Le contexte Conversation A chaque conversation.begin()

doit correspondre un conversation.end() !@ConversationScoped @Named("monBean")public class OrderBuilder implements Serializable {    private @Inject Conversation conversation;

public Conversation getConversation() {return conversation; }    

  @PostConstruct private void postConstruct() {       conversation.begin();    }

   public String destroy() {      conversation.end(); return "page2"; // navigation } }

Long-running conversation !

Arrête la conversation !

Page 99: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

99

Le contexte Conversation Propagation de la conversation

Automatique pour une requête JSF faces (une soumission de formulaire JSF), ou une redirection,

pas automatique pour un simple lien, on doit utiliser le paramètre réservé « cid »

<h:link outcome="/addProduct.xhtml" value="Add Product">   <f:param name="cid" value="#{monBean.conversation.id}"/></h:link>

Page 100: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

100

Le pseudo-contexte Singleton

Un bean qui sera instancié seulement une fois

Les clients ont une référence directe au bean Gros problème lors de la sérialisation d’une session ou d’une conversation !!! solutions:

le bean implémente writeResolve() et readReplace() le bean est déclaré transient (ne sera pas sérialisé) le client a une référence de type Instance<X> Ne pas utiliser Singleton et utiliser Application à

la place !

Page 101: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

101

Le pseudo-contexte Dependent contexte par défaut pour les beans qui n’en

déclarent pas Jamais partagé entre les clients C’est un objet Dépendant de son client

il sera instantié en même temps que son client il sera détruit en même temps que son client

Page 102: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

102

Le qualifieur @New

Pour obtenir un nouvel objet dépendant Fonctionne même si un autre contexte a été

déclaré pour Calculator exemple:

ici: deux instances différentes de Calculator

@Inject @New Calculator calculator;

public class PaymentCalc {    @Inject Calculator calculator;    @Inject @New Calculator newCalculator; }

@ConversationScoped public class Calculator { ... }

Page 103: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

103

Corrigez les erreurs Faites en sorte que la conversation soit long-

running Testez sur differents onglets et navigateurs Quel est le scope de Generator ? Quand un

bean de type Generator est-il créé ? Détruit ?

Exercice8

Page 104: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

5- Producer methods et attributes

Page 105: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

105

Objectif des Producer Methods Si l’objet à injecter n’est pas un bean Si le type concret de l’objet varie au moment

de l’execution Si l’objet doit être initialisé de manière

complexe

Page 106: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

106

Objectif des Producer Methods exemple: polymorphisme au moment de

l’execution@SessionScoped public class Preferences implements Serializable {    private PaymentStrategyType paymentStrategy;    ...    @Produces @Preferred     public PaymentStrategy getPaymentStrategy() {        switch (paymentStrategy) {            case CREDIT_CARD: return new CreditCardPaymentStrategy();            case CHEQUE: return new CheckPaymentStrategy();            case PAYPAL: return new PayPalPaymentStrategy();            default: return null;        }     } }

@Inject @Preferred PaymentStrategy paymentStrategy;

Page 107: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

107

Objectif des Producer Attributes Quand c’est très simple

@SessionScoped public class Preferences implements Serializable {       @Produces int randomInt= new Random().nextInt();}

@Inject int unNombre;

Page 108: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

108

Portée de l’objet produit Par défaut, l’objet produit par un Producer

Method a la portée @Dependent

On peut modifier ça simplement:

@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy() {    ... }

Page 109: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

109

Injection dans une Producer Methods

Attention ici on instancie un bean avec new ! Pas injection de dépendance dans

CreditCardPaymentStrategy, Pas d’intercepteur possible

Pour ça il faut laisser le conteneur instancier les beans Injection !

...           case CREDIT_CARD: return new CreditCardPaymentStrategy(); ...

@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,                                           CheckPaymentStrategy cps,                                           PayPalPaymentStrategy ppps) {    switch (paymentStrategy) {       case CREDIT_CARD: return ccps;       case CHEQUE: return cps;       case PAYPAL: return ppps;       default: return null;    }  }

Page 110: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

110

Utilisation de @New

Un nouvel objet dépendant sera créé et associé au contexte de la session !

Il ne sera détruit qu’à la fin de la session

@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(@New CreditCardPaymentStrategy ccps,                                           @New CheckPaymentStrategy cps,                                           @New PayPalPaymentStrategy ppps) {    switch (paymentStrategy) {       case CREDIT_CARD: return ccps;       case CHEQUE: return cps;       case PAYPAL: return ppps;       default: return null;    }  }

Page 111: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

111

Utilisation de @Disposes Certains objets renvoyés par un Producer

Method doivent être détruits proprement

méthode de destruction dans la même classe qu’où est définie la méthode de production !

@Produces @RequestScoped Connection connect(User user) {    return createConnection(user.getId(), user.getPassword()); }

void close(@Disposes Connection connection) {    connection.close(); }

Page 112: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

6- Intercepteurs

Page 113: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

113

Intercepteurs

Existent dans Java EE 5, définis dans la spécification JSR 318 - Java Interceptors 1.1

public class TracingInterceptor {   @AroundInvoke    public Object logCall(InvocationContext context) throws Exception{        System.out.println("Invoking method: " + context.getMethod());        return context.proceed();        System.out.println(« Finished invoking method: " + context.getMethod());    }}

@Interceptors(TracingInterceptor.class, ...)@Stateless public class HelloWorldBean implements HelloWorld {         public void sayHello() {        System.out.println("Hello!");    }}

Page 114: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

114

Intercepteurs Existent dans Java EE 5, définis dans la

spécification JSR 318 - Java Interceptors 1.1 mais contre-intuitif !

On spécifiait directement la classe de l’intercepteur dans l’EJB !

On spécifiait directement l’ordre des intercepteurs dans l’EJB !

CDI améliore cette spécification approche pour lier un intercepteur à un bean est

basée sur des annotations plutôt que explicitement.

Page 115: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

115

Intercepteurs Intercepter une méthode

Intercepter un callback du cycle de vie

Intercepter une méthode timeout

public class TransactionInterceptor {    @AroundInvoke     public Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

public class DependencyInjectionInterceptor {    @PostConstruct     public void injectDependencies(InvocationContext ctx) { ... } }

public class TransactionInterceptor {    @AroundInvoke     public Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

Page 116: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

116

API de InvocationContext

public interface InvocationContext {

// savoir des choses sur l’objet intercepté public Object getTarget();

// si c’est un composant EJB avec un timout public Object getTimer();

// savoir des choses sur la méthode interceptée public Method getMethod(); public Object[] getParameters(); public void setParameters(Object[] params);

// permet de passer des informations au prochain intercepteur public Map<String, Object> getContextData();

// passer la main au prochain intercepteur, // en bout de chaîne: exécuter la méthode interceptée public Object proceed() throws Exception;}

Page 117: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

117

Binding d’intercepteur Avec CDI, une annotation annotée

@InterceptorBinding

Ensuite on peut dire qu’un objet est transactionnel

Ou juste une méthode

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

@Transactional public class ShoppingCart { ... }

public class ShoppingCart {    @Transactional public void checkout() { ... } }

Page 118: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

118

Implémentation de l’intercepteur

Un intercepteur annoté avec @Intercepter et notre InterceptorBinding @Transactional

Peut utiliser l’injection de dépendance

Il peut y avoir plusieurs intercepteurs du même type de binding

@Transactional @Interceptor public class TransactionInterceptor {

   @Resource UserTransaction transaction;

   @AroundInvoke     public Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

Page 119: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

119

Activation des intercepteurs Par défaut les intercepteurs sont desactivés

on doit les activer dans META-INF/beans.xml spécifie l’ordre des intercepteurs permet de choisir lors du déploiement les

intercepteurs à utiliser

<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>org.mycompany.myapp.TransactionInterceptor</class>   </interceptors></beans>

Page 120: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

120

Bindings d’Intercepteurs avec membre Idem que pour les beans:

si le membre n’est pas annoté @Nonbinding, les membres doivent correspondre pour qu’il y ait interception

@InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Transactional {    boolean requiresNew() default false;}

@InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Secure {    @Nonbinding String[] rolesAllowed() default {}; }

Page 121: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

121

Plusieurs intercepteurs bindings Plusieurs intercepteurs pour un bean:

Un intercepteur avec plusieurs bindings

@Secure(rolesAllowed="admin") @Transactional public class ShoppingCart { ... }

@Transactional @Secure @Interceptor public class TransactionalSecureInterceptor { ... }

public class ShoppingCart {    @Transactional @Secure public void checkout() { ... } }

@Secure public class ShoppingCart {    @Transactional public void checkout() { ... } }

@Transactional public class ShoppingCart {    @Secure public void checkout() { ... } }

@Transactional @Secure public class ShoppingCart {    public void checkout() { ... } }

Page 122: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

122

Etudiez l’application numberguess9 Implementez un intercepteur

TricheurIntercepteur qui intercepte toutes les méthodes de Game et Generator et qui liste tout ce qui se passe dans la console Nom de la classe appelée, Nom de la méthode appelée Type et valeur des paramètres Valeur de retour

Exercice9

Page 123: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

7- Décorateurs

Page 124: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

124

Intercepteurs vs. Décorateurs Les intercepteurs offrent des services

orthogonaux à l’application transactions, sécurité, ... ils ne connaissent pas la sémantique de l’objet

intercepté ils sont utilisables par une grande variété d’objets

Page 125: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

125

Intercepteurs vs. Décorateurs Les décorateurs interceptent les invocations

pour une interface java seulement parfait pour ajouter de la logique métier connaissent la sémantique de cette interface moins de généralité qu’un intercepteur

Les intercepteurs et les décorateurs sont complémentaires

Page 126: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

126

Décorateurs

Exemple:

les grosses transactions doivent être écrites dans un log

Le boulot parfait pour un décorateur

public interface Account {    public BigDecimal getBalance();    public User getOwner();    public void withdraw(BigDecimal amount);    public void deposit(BigDecimal amount); }

@Decorator public abstract class LargeTransactionDecorator       implements Account {    ... }

Page 127: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

127

Décorateurs Un décorateur

annotée @Decorator implémente l’interface décorée définit les méthodes qu’qu’on doit intercepter peut utiliser l’injection de dépendance peut être une classe abstraite !

Les intercepteurs sont appelés AVANT les décorateurs

Page 128: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

128

Décorateurs

@Decorator public abstract class LargeTransactionDecorator       implements Account {    @Inject @Delegate @Any Account account;    @PersistenceContext EntityManager em;         public void withdraw(BigDecimal amount) {       ...    }         public void deposit(BigDecimal amount);       ...    } }

Page 129: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

129

Objet délégué @Delegate

@Decorator public abstract class LargeTransactionDecorator       implements Account {    @Inject @Delegate @Any Account account;    @PersistenceContext EntityManager em;         public void withdraw(BigDecimal amount) {       ...    }         public void deposit(BigDecimal amount);       ...    } }

Les décorateurs ont un point d’injection pour l’objet délégué du même type que l’objet décoré annoté @Delegate

Page 130: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

130

Objet délégué

Un décorateur peut appeler n’importe quelle méthode de l’objet décoré !

@Decorator public abstract class LargeTransactionDecorator       implements Account {    @Inject @Delegate @Any Account account;    @PersistenceContext EntityManager em;         public void withdraw(BigDecimal amount) {       account.withdraw(amount);       if ( amount.compareTo(LARGE_AMOUNT)>0 ) {          em.persist( new LoggedWithdrawl(amount) );       }    }         public void deposit(BigDecimal amount);       account.deposit(amount);       if ( amount.compareTo(LARGE_AMOUNT)>0 ) {          em.persist( new LoggedDeposit(amount) );       }    } }

Page 131: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

131

Binding Un decorateur est associé à tout bean tel que:

Le type du point d’injection est un des types du bean

Le bean a tous les qualifiers declarés au point d’injection

@Inject @Delegate @Any Account account;

décore tous les beans qui implément Account

@Inject @Delegate @Foreign @Saving Account account;

décore seulement les beans qui implément Account et qui ont les qualifieurs @Foreign et @Saving

Page 132: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

132

Activation des décorateurs Par défaut les décorateurs sont désactivés

on doit les activer dans META-INF/beans.xml spécifie l’ordre des décorateurs permet de choisir lors du déploiement les

décorateurs à utiliser

<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">   <decorators>         <class>org.mycompany.myapp.LargeTransactionDecorator</class>   </decorators></beans>

Page 133: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

133

Sur la base de l’application numberguess9 Implementez un décorateur TricheurDecorator

pour être sûr que le nombre à chercher est en réalité entre 1 et 5

Exercice10

Page 134: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

8- Evènements

Page 135: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

135

Rappel: le patron de conception classique observateur/observable

déjà dans le patron de conception classique, les producteurs d’évènements sont découplés des observateurs

Page 136: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

136

Evènements dans CDI Les producteurs d’évènements lèvent des

évènements qui sont passés aux observeurs par le conteneur

Page 137: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

137

CDI vs. observateur/observable Les atouts de CDI:

Dans CDI les observateurs sont découplés des producteurs

Les observateurs peuvent spécifier une collection de « sélecteurs » pour limiter l’ensemble de notifications d’évènements qu’ils reçoivent

Les observateurs peuvent être notifiés immédiatement, ou après la fin de la transaction.

Page 138: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

138

Objet évènement

Comme dans le patron de conception classiqueN’importe quel objet java

+ peut avoir des qualifieursPermet aux observateurs de spécifier un sous-ensemble des évènements qu’il observe

Page 139: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

139

Observateur Un observateur est une méthode de bean

avec un paramètre annoté @Observes

le paramètre d’évènement est document l’observateur peut spécifier des qualifieurs

pour restreindre les évènements qu’il observe (ci-dessus, par défaut, @Default)

L’observateur peut avoir d’autres paramètres (ce sont des points d’injection)

public void onAnyDocumentEvent(@Observes Document document) { ... }

public void onAnyDocumentEvent(@Observes @Updated Document document) { ... }

public void onAnyDocumentEvent(@Observes @Any Document document) { ... }

public void onAnyDocumentEvent(@Observes Document document, User user) { ... }

Page 140: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

140

Producteurs d’évènements Les producteurs d’évènement lèvent des

évènements en utilisant l’interface paramétrée Event, obtenue par injection

Pour lever un évènement:

@Inject @Any Event<Document> documentEvent;

documentEvent.fire(document);

Page 141: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

141

Producteurs d’évènements

@Inject @Updated Event<Document> documentEvent;documentEvent.fire(document);

@Inject @Any Event<Document> documentEvent;documentEvent.fire(document);

Produit un évènement sans qualifieur

Produit un évènement avec le qualifieur @Updated

@Inject @Any Event<Document> documentEvent;documentEvent.select(new AnnotationLiteral<Updated>(){}).fire(document);

Produit un évènement avec le qualifieur @Updated

Page 142: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

142

Méthode observateur conditionnelle

Par défaut, si aucune instance d’un observateur existe dans le contexte courant, le conteneur en crée une. Si on ne veut pas,

Un bean @Dependent ne peut pas être un observateur conditionnel (il ne serait jamais appelé) !

public void refreshOnDocumentUpdate( @Observes(notifyObserver = IF_EXISTS) @Updated Document d) { ... }

Page 143: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

143

Qualifieur d’évènement avec membre Un qualifieur d’évènements peut avoir un membre

La valeur du membre sert à limiter les évènements passés à l’observeur Si le membre n’est pas annoté @Nonbinding

@Qualifier @Target({PARAMETER, FIELD}) @Retention(RUNTIME) public @interface Role {    RoleType value(); }

public void adminLoggedIn(@Observes @Role(ADMIN) LoggedIn event) { ... }

Page 144: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

144

Qualifieur d’évènement avec membre La valeur du membre peut être définie

statiquement

Ou dynamiquement :1. On écrit une sous-classe abstraite de AnnotationLiteral

2. Le producteur d’évènements passe une instance de cette classe au select()

abstract class RoleBinding     extends AnnotationLiteral<Role>     implements Role {}

documentEvent.select(new RoleBinding() {    public void value() { return user.getRole(); } }).fire(document);

@Inject @Role(ADMIN) Event<LoggedIn> loggedInEvent;loggedInEvent.fire(document);

Page 145: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

145

Observateurs transactionnels

IN_PROGESS observers are called immediately (default) AFTER_SUCCESS observers are called during the after

completion phase of the transaction, but only if the transaction completes successfully

AFTER_FAILURE observers are called during the after completion phase of the transaction, but only if the transaction fails to complete successfully

AFTER_COMPLETION observers are called during the after completion phase of the transaction

BEFORE_COMPLETION observers are called during the before completion phase of the transaction

public void refreshCategoryTree(@Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event) { ... }

Page 146: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

146

Sur la base de l’application numberguess9 Faites en sorte que Game et Generator

lancent des évènements et implémentez un ou plusieurs écouteurs de ces évènements pour trace dans la console, et pouvoir avoir la réponse au jeu

Exercice11

Page 147: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

9- Stéréotypes

Page 148: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

148

Stéréotypes Un stéréotype est une annotation annotée

@Stereotype Regroupe un ensemble de comportements

génériques

@Stereotype @Retention(RUNTIME) @Target(TYPE) ... public @interface Action {}

Page 149: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

149

Portée par défaut Un stéréotype peut définir une portée par

défaut pour les beans qui le déclarent

@RequestScoped @Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface Action {}

@Action  public class LoginAction { ... }

@Dependent @Action  public class DependentScopedLoginAction { ... }

Portée Requête

Portée Dependent

Page 150: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

150

Intercepteurs Et si on a toute une catégorie de beans qui

ont les mêmes Intercepteurs ? utiliser un Stéréotype !

@RequestScoped @Transactional(requiresNew=true) @Secure @Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface Action {}

nos interceptor bindings

Page 151: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

151

Nom EL par défaut Et si on a toute une catégorie de beans qui

doivent avoir un nom EL ? utiliser un Stéréotype ! ce sera un nom EL par défaut

@RequestScoped @Transactional(requiresNew=true) @Secure@Named @Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface Action {}

Page 152: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

152

Alternatives Et si on a toute une catégorie de beans

alternatifs à activer ? Tous les activer un par un dans le fichier de

déploiement META-INF/beans.xml ? NON: utiliser un stéréotype !

@Alternative@Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface AlternativeAction {}

Page 153: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

153

Le stéréotype Model

CDI définit un stéréotype standard, @Model, à utiliser dans les applications Web...

... à la place d’un JSF managed bean

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

Page 154: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

10- Amélioration de Java EE avec CDI

Page 155: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

155

Injection de dépendance dans Java EE ça existe, mais très souvent utilise des

chaînes de caractères On peut utiliser CDI pour définir des

ressources proprement

Page 156: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

156

Définir une ressource Une ressource est un objet disponible dans

l’environnement Java EE JDBC Datasource, JMS Queues, Topics

and ConnectionFactorys, JavaMail Sessions et autres ressources transactionnelles,

JPA EntityManagers et EntityManagerFactorys, remote EJBs, et services web

Page 157: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

157

Un bean producteur de ressources Ressource= données JEE + données CDI

@Produces @WebServiceRef(lookup="java:app/service/Catalog") Catalog catalog;

@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatasource")  @CustomerDatabase Datasource customerDatabase;

@Produces @PersistenceContext(unitName="CustomerDatabase") @CustomerDatabase EntityManager customerDatabasePersistenceContext;

@Produces @PersistenceUnit(unitName="CustomerDatabase")  @CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;

@Produces @EJB(ejbLink="../their.jar#PaymentService")  PaymentService paymentService;

Page 158: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

158

Et ainsi... Un bean ResourcesProducer avec la liste des

ressources pour le deploiement normal Un bean ResourcesProducer annoté

@Alternative avec la liste des ressources pour le deploiement de test1

Un bean ResourcesProducer annoté @Alternative avec la liste des ressources pour le deploiement de test2

...

Page 159: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

159

Enfin On peut utiliser les ressources avec @Inject

plus propre, moins de code à changer si besoin

@Inject Catalog catalog;

@Inject @CustomerDatabase Datasource customerDatabase;

@Inject @CustomerDatabase EntityManager customerDatabasePersistenceContext;

@Inject @CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;

@Inject PaymentService paymentService;

Page 160: Context and Dependency Injection Maxime Lefrançois (maxime.lefrancois@inria.fr), M2 MIAGE Casablanca 2012-2013maxime.lefrancois@inria.fr

Context and Dependency Injection

Maxime Lefrançois ([email protected]), M2 MIAGE Casablanca 2012-2013