La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Context and Dependency Injection Maxime Lefrançois M2 MIAGE Casablanca

Présentations similaires


Présentation au sujet: "Context and Dependency Injection Maxime Lefrançois M2 MIAGE Casablanca"— Transcription de la présentation:

1 Context and Dependency Injection Maxime Lefrançois M2 MIAGE Casablanca

2 Introduction 2

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 jai 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 lutilise pas ? Comment définir des implémentations alternatives, pour en changer au moment du déploiement ? Comment partager cet objet entre dautres objets ? 3

4 Context and Dependency Injection = CDI (JSR-299) CDI est un modèle riche de programmation couplage faible avec typage fort 4

5 CDI Gestion du cycle de vie des objets avec état, liés à des contextes injection de dépendance avec types intercepteurs dobjets et décorateurs notifications dévènements + SPI (pour extensions) 5

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) 6

7 Beans – couplage faible Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 1. 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 7

8 Beans – couplage faible Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 2. 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 8

9 Beans – couplage faible Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 3. Les notifications dévènement découplent complètement: les producteur dévènement les consommateurs dévènements 9

10 Beans – couplage faible Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 4. Les intercepteurs découplent: les considérations technique la logique métier (programmation par aspect) exemple: sécurité, transactions,... 10

11 Beans – couplage faible Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 5. Les décorateurs permettent de compartimenter les logiques métier 11

12 Beans – typage fort Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 6. le couplage ne se fait pas par des chaînes de caractères, on utilise des annotations: les qualifieurs 12

13 Beans – typage fort Un objet avec état lié à un contexte = un bean couplage faible avec typage fort 7. lutilisation du fichier descripteur est limitée pour les informations qui dépendent du déploiement META-INF/beans.xml 13

14 Notion de Bean Quels beans on connaît ? Cest quoi un bean ? 14

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 des intercepteurs (définis dans le bean = couplage fort !!!) cest quoi les propriétés dun Managed Bean ? 15

16 16 Pour commencer, une petite application pour vérifier quelques notions des Servlets et JSF2… Corrigez les erreurs ! Exercice 1

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... 17

18 Notion de Bean Cest quoi un bean ? CDI donne une définition claire: Tout objet qui a un constructeur sans paramètre (ou un constructeur (ou un producteur de beans) 18

19 Un exemple dinjection public class SentenceParser { public List parse(String text) {... } public class SentenceTranslator implements Translator { public String translate(String sentence) {... } 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 19 est-ce que cest un bean ?

20 Un exemple dinjection On écrit donc une classe pour traduire un document en entier public class TextTranslator { private SentenceParser sentenceParser; private Translator 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 cest un bean ? 20

21 Un exemple dinjection On écrit donc une classe pour traduire un document en entier public class TextTranslator { private SentenceParser sentenceParser; private Translator 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 cest un bean ? OUI. Le conteneur va appeler le constructeur et injecter dautres beans dans les paramètres du constructeur. 21 Les paramètres du constructeur seront injectés

22 Un exemple dinjection On écrit donc une classe pour traduire un document en entier public class TextTranslator { private SentenceParser sentenceParser; private Translator 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 dun bean Ou dans un attribut ou une méthode dune servlet ou dun autre composant EJB 22

23 Un public class TranslateController 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 23

24 Utiliser CDI 24

25 Dans un projet JEE 6 25 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 davoir un fichier descripteur META-INF/beans.xml (même vide !) Weld, limplémentation de référencede CDI, est fournie Avec Tomcat, Jetty, … Suivre la procédure: US/html/environments.html#d0e5225http://docs.jboss.org/weld/reference/latest/en- US/html/environments.html#d0e5225

26 Projet Java SE avec CDI 26 On utilise limplémentation de référence: Weld Le jar: weld-se-core.jar Ou avec Maven: Est-ce quon doit écrire une classe principale avec un main ? org.jboss.weld.se weld-se CHOISIR LA DERNIERE FINALE

27 Projet Java SE avec CDI 27 Est-ce quon doit écrire une classe principale avec un main ? Réponse: NON !!! Où est linstance du conteneur de beans ??? Cest possible de linstantier nous-même, mais compliqué. Le plus simple: une méthode main est fournie avec weld-se, Le point dentré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 public class HelloWorld { public void ContainerInitialized List parameters) { System.out.println("Hello " + parameters.get(0)); } }

28 ² 28 Quelle différence entre les deux applications 2a, 2b ? La classe Init: La bonne façon davoir une méthode dun bean appelée dès que le lapplication 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

29 Introduction à CDI

30 Anatomie dun 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 30

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 31

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 {... } 32

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 lobjet à injecter, sans utiliser une chaîne @Target({TYPE, METHOD, PARAMETER, FIELD}) CreditCard {} 33

34 Type, qualifieur et injection de dépendance Pour ce 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 public class CreditCardPaymentProcessor implements PaymentProcessor {... } 34

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 qualifieurs Si aucun qualifieur nest spécifié, il y a le qualifieur par 35

36 36 1- Provoquez une erreur: point dinjection ambigüe, 2- Provoquez une erreur: point dinjection 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 nest instantié quune seule fois ? Exercice 3

37 Contexte (scope) Le contexte dun bean définit le cycle de vie de ses instances Un contexte est représenté par une … 37

38 Contexte (scope) Une instance dun bean session-scoped est liée à un session dun utilisateur et est partagé par toutes les requêtes executées dans cette session (on ne peut pas lenlever, ni le changer) Un bean a un contexte. Si aucun contexte nest défini, le contexte par défaut 38

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 class ShoppingCart implements Serializable {... public List getLineItems() {...}.... } On peut ensuite lutiliser dans une JSF ou une JSP:... 39

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 class ShoppingCart implements Serializable {... public List getLineItems() {...}.... } On peut ensuite lutiliser dans une JSF ou une JSP:... Propriété lineItems ! 40

41 Nom EL (EL= Expression Language) Valeur par class ShoppingCart implements Serializable {... public List getLineItems() {...}.... } Comme dans Exercice1

42 Alternatives Un bean peut être déclaré être une implémentation 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 42

43 Intercepteurs Existent dans Java EE 5 import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class TracingInterceptor 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()); public class HelloWorldBean implements HelloWorld { public void sayHello() { System.out.println("Hello!"); } } 43

44 Intercepteurs Existent dans Java EE 5, mais contre-intuitif ! On spécifiait directement la classe de lintercepteur dans lEJB ! On spécifiait directement lordre des intercepteurs dans lEJB ! 44

45 Intercepteurs Dans CDI: 1. annotation de lien à un @Target( { TYPE, METHOD Transactional {} 2. Lintercepteur déclare cette class TransactionInterceptor {... } 3. On applique cet aspect à un class ShoppingCart implements Serializable {... } 4. On active les intercepteurs et on définit leur ordre dans le fichier descripteur MEAT-INF/beans.xml 45

46 Quelles classes sont des beans ? Les Managed Beans Les EJB Session Beans Les Producer Methods Les Producer Fields (Injectables, décorables, interceptables,...) 46

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) 47

48 Les Managed Beans pas nécessaire avec CDI ! Le conteneur CDI considère chaque classe comme un managed beans si elle: nest pas une classe non-static interne est une classe concrètes, ou nest pas un composant EJB (un session bean...) nimplémente pas javax.enterprise.inject.spi.Extension a un constructeur approprié : soit un constructeur sans paramètres un constructeur 48

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 A UN ENTITY BEAN 49

50 Les Session Beans des services avancés proposés par le conteneur dEJB: sécurité et gestion des transactions au niveau des méthodes, gestion des accès concurrents, passivation des instances des stateful session beans et 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) 50

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 quun managed bean ? 51

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 quun managed bean ? Quand on a besoin des services offerts par le conteneur dEJB ! 52

53 Producer Methods Comment injecter un int au hasard entre 1 et 100 ? 53

54 Producer Methods Comment injecter un int au hasard entre 1 et 100 public class RandomNumberGenerator { private Random random = @Named int getRandomNumber() { return random.nextInt(100); } } 54

55 Producer Methods Comment injecter un int au hasard entre 1 et 100 public class RandomNumberGenerator { private Random random = @Named int getRandomNumber() { return random.nextInt(100); } } Cest cette méthode qui sera appelée pour injecter une instance dun bean avec le type int et public int rand,...) int rand; Un constructeur Un attribut... Des méthodes 55

56 Producer Methods Comment choisir au moment de lexecution quelle implémentation dun type de bean on veut instantier et injecter ? 56

57 Producer Methods Comment choisir au moment de lexecution quelle implémentation dun type de bean on veut instantier et injecter ? Une Producer Method 57

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 ? 58

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 59

60 Producer Fields Un raccourci pour les cas simples, plus simple que les Producer Methods: Les Producer Fields public class Shop PaymentProcessor List products =....; } 60

61 61 Ecrivez une producer method et/ou un producer field pour lentier aléatoire et lentier max Etudiez lenchaînement des appels de méthode Vérifiez que le bean Game est bien associé à une session Exercice4

62 Injection

63 Points dinjection dun bean Maintenant on a des beans, on peut les injecter. 63

64 Points dinjection dun bean Constructeur dun autre bean public class Checkout { private final ShoppingCart public Checkout(ShoppingCart cart) { this.cart = cart; } } Un bean ne peut avoir quun seul constructeur 64

65 Points dinjection dun bean Méthode dinitialisation public class Checkout { private ShoppingCart void setShoppingCart(ShoppingCart cart) { this.cart = cart; } } Un bean peut avoir plusieurs méthodes dinitialisation 65

66 Points dinjection dun bean Injection dattribut public class Checkout { ShoppingCart cart; } Un bean peut avoir plusieurs méthodes dinitialisation 66

67 Points dinjection dun bean 1. Le conteneur appelle le constructeur du bean (celui par défaut ou celui 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 dinitialisation du bean (sans ordre standard). 4. La méthode est appelée 67

68 Points dinjection dun bean Dautre injections de paramètres sont possibles dans CDI, par exemple dans les Producer Checkout createCheckout(ShoppingCart cart) { return new Checkout(cart); } 68

69 Quest-ce qui est injecté ? Algorithme typesafe resolution: vérifie quun et un seul bean peut être injecté à chaque fois Au moment de linitialisation ! Le plus simple: un seul bean dun certain type, et un point dinjection avec ce type... 69

70 Quest-ce qui est injecté ? Si plusieurs beans correspondent pour le point dinjection ? On peut utiliser un Qualifieur Les Qualifieurs peuvent avoir des membres On peut combiner plusieurs Qualifieurs Certains beans peuvent être des Alternatives 70

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 derreurs @Target({TYPE, METHOD, FIELD, PARAMETER}) Synchronous {} 71

72 Qualifieurs Qualifieur pour annoter: Un public class SynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) {... } } 72

73 Qualifieur pour annoter: Un point PaymentProcessor PaymentProcessor PaymentProcessor asyncPaymentProcessor) { return isSynchronous() ? syncPaymentProcessor : asyncPaymentProcessor; } PaymentProcessor public void PaymentProcessor syncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; public PaymentProcessor syncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; }

74 Rappel: un bean a au moins un Qualifieur. Si aucun qualifieur nest écrit explicitement, cest comme si il y avait le 74

75 Quel est le qualifieur du bean qui sera injecté ? Comment dire: « nimporte quel bean » ? il y a de grandes chances pour que ce point dinjection soit ambiguë PaymentProcessor paymentProcessor; 75

76 Qualifieur avec membre Une annotation @Target({TYPE, METHOD, FIELD, PARAMETER}) Synchronous { PaymentMethod value(); } public enum PaymentMethod { CHEQUE, CB, CASH; } ici on utilise une énumeration pour aggréger plusieurs qualifieurs en un public class PayByCheckBean pbcb; ce bean correspond pour ce point dinjection 76

77 77 Vérifiez dans votre application, avec un qui a un membre qui est une énumeration: ALEATOIRE, MAX Exercice5

78 Qualifieur avec membre Un membre dune annotation qui ne doit pas servir à restreindre les @Target({TYPE, METHOD, FIELD, PARAMETER}) Synchronous { PaymentMethod String comment() default ""; } Sert: -soit à proposer un commentaire (comme ici) -soit à choisir le bean au moment de lexecution (en utilisant une Producer method et lintrospection java) 78

79 Plusieurs qualifieurs Seuls les beans qui ont TOUS les qualifieurs sont injectables Tous les beans qui ont AU MOINS ce qualifieur @Asynchronous PayByCheckBean PayByCheckBean pbcb;

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 @Asynchronous public class MockPaymentProcessor implements PaymentProcessor { public void process(Payment payment) {... } } org.mycompany.mock.MockPaymentProcessor 80 Injectable Injectable

81 ² 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

82 ² 82 Ça ne fonctionne pas, pourquoi ? Un bean alternatif remplace un bean seulement pour les points dinjection, 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 Essayez avec MockGame Exercice6

83 Programmatic lookup Dans certaines situations, linjection nest pas le meilleur moyen dobteinur une référence contextuelle avec une combinaison spécifique dun type et de qualifieurs Si le type du bean ou les qualifieurs varient dynamiquement au moment de lexecution, ou Selon le déploiement, il peut ne pas y avoir de combinaison type/qualifieurs acceptable si on veut itérer sur les beans dun certain type... Dans ces situations, on peut injecter une instance de lobjet paramétré Instance paymentProcessorSource; 83

84 Programmatic lookup Si exactement un bean correspond : get() Sinon Instance paymentProcessorSource; PaymentProcessor paymentProcessor = paymentProcessorSource.get(); for(PaymentProcessor p : paymentProcessorSource) {... } 84

85 Programmatic lookup On peut spécifier des qualifieurs au point dinjection 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... Attention, ça ne nest pas utilisable pour une qualifieur Instance paymentProcessorSource; paymentProcessorSource.select(new Instance paymentProcessorSource; 85

86 Lobjet InjectionPoint Certains objets dépendent de lendroit où ils sont injectés pour faire ce quils doivent faire.. le log doit connaître la classe de lobjet où il est linjection dun paramètre HTTP dépend du nom du paramètre qui a été spécifié au point dinjection linjection du résultat dune expression EL dépend de lexpression spécifiée au point dinjection 86

87 Lobjet 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 Logger createLogger(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember(). getDeclaringClass().getName()); } Logger log; 87

88 Lobjet InjectionPoint Exemple du paramètre HTTP: un type de qualifieur avec une petite @Target({TYPE, METHOD, FIELD, PARAMETER}) HttpParam public String value(); } 88 String getParamValue(InjectionPoint ip) { ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); String value = ip.getAnnotated().getAnnotation(HttpParam.class).value(); return request.getParameter(value); } }

89 Lobjet InjectionPoint Exemple du paramètre HTTP: et cest String pwd; 89

90 Lobjet InjectionPoint public interface InjectionPoint { public Type getType(); public Set getQualifiers(); public Bean getBean(); public Member getMember(); public Annotated getAnnotated(); public boolean isDelegate(); public boolean isTransient(); } 90

91 91 Au moment où lapplication est initialisée: Listez lensemble des beans qui ont le Pour chacun de ces beans, affichez le nom qualifié de leur classe Exercice7

92 4- Portées et Contextes

93 Portée Quatre portées définis 93

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 94

95 Portée Dans Java EE, les portées de type requête et application sont actives Pendant linvocation dune méthode EJB remote Pendant linvocation dune méthode EJB asynchrone Pendant un EJB timeout Pendant la réception dun message par un message-driven bean Pendant la réception dun message par un MessageListener Pendant linvocation dun service web 95

96 Portée doivent être sérialisable. 96

97 Le contexte Conversation Similaire au contexte Session, mais: cest lapplication qui définit le début et la fin Pour JSF: contient létat dun seul onglet dun navigateur La conversation représente donc une tâche, « ce sur quoi lutilisateur 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 » 97

98 Le contexte Conversation 98 A chaque conversation.begin() doit correspondre un public class OrderBuilder implements Serializable { Conversation conversation; public Conversation getConversation() {return conversation; private void postConstruct() { conversation.begin(); } public String destroy() { conversation.end(); return "page2"; // navigation } } Long-running conversation ! Arrête la conversation !

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 » 99

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 dune session ou dune 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 Ne pas utiliser Singleton et utiliser Application à la place ! 100

101 Le pseudo-contexte Dependent contexte par défaut pour les beans qui nen déclarent pas Jamais partagé entre les clients Cest 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 101

102 Le 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 Calculator calculator; public class PaymentCalc Calculator newCalculator; public class Calculator {... } 102

103 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

104 5- Producer methods et attributes

105 Objectif des Producer Methods Si lobjet à injecter nest pas un bean Si le type concret de lobjet varie au moment de lexecution Si lobjet doit être initialisé de manière complexe 105

106 Objectif des Producer Methods exemple: polymorphisme au moment de public class Preferences implements Serializable { private public PaymentStrategy getPaymentStrategy() { switch (paymentStrategy) { case CREDIT_CARD: return new CreditCardPaymentStrategy(); case CHEQUE: return new CheckPaymentStrategy(); case PAYPAL: return new PayPalPaymentStrategy(); default: return null; } PaymentStrategy paymentStrategy; 106

107 Objectif des Producer Attributes Quand cest très public class Preferences implements Serializable int randomInt= new Random().nextInt(); int unNombre; 107

108 Portée de lobjet produit Par défaut, lobjet produit par un Producer Method a la On peut modifier @SessionScoped public PaymentStrategy getPaymentStrategy() {... } 108

109 Injection dans une Producer Methods Attention ici on instancie un bean avec new ! Pas injection de dépendance dans CreditCardPaymentStrategy, Pas dintercepteur possible Pour ça il faut laisser le conteneur instancier les beans Injection !... case CREDIT_CARD: return @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; } } 109

110 Utilisation Un nouvel objet dépendant sera créé et associé au contexte de la session ! Il ne sera détruit quà la fin de @SessionScoped public PaymentStrategy CreditCardPaymentStrategy CheckPaymentStrategy PayPalPaymentStrategy ppps) { switch (paymentStrategy) { case CREDIT_CARD: return ccps; case CHEQUE: return cps; case PAYPAL: return ppps; default: return null; } } 110

111 Utilisation Certains objets renvoyés par un Producer Method doivent être détruits proprement méthode de destruction dans la même classe quoù est définie la méthode de Connection connect(User user) { return createConnection(user.getId(), user.getPassword()); } void Connection connection) { connection.close(); } 111

112 6- Intercepteurs

113 Intercepteurs Existent dans Java EE 5, définis dans la spécification JSR Java Interceptors 1.1 public class TracingInterceptor 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()); public class HelloWorldBean implements HelloWorld { public void sayHello() { System.out.println("Hello!"); } } 113

114 Intercepteurs Existent dans Java EE 5, définis dans la spécification JSR Java Interceptors 1.1 mais contre-intuitif ! On spécifiait directement la classe de lintercepteur dans lEJB ! On spécifiait directement lordre des intercepteurs dans lEJB ! CDI améliore cette spécification approche pour lier un intercepteur à un bean est basée sur des annotations plutôt que explicitement. 114

115 Intercepteurs Intercepter une méthode Intercepter un callback du cycle de vie Intercepter une méthode timeout public class TransactionInterceptor public Object manageTransaction(InvocationContext ctx) throws Exception {... } } public class DependencyInjectionInterceptor public void injectDependencies(InvocationContext ctx) {... } } public class TransactionInterceptor public Object manageTransaction(InvocationContext ctx) throws Exception {... } } 115

116 API de InvocationContext public interface InvocationContext { // savoir des choses sur lobjet intercepté public Object getTarget(); // si cest 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 getContextData(); // passer la main au prochain intercepteur, // en bout de chaîne: exécuter la méthode interceptée public Object proceed() throws Exception; } 116

117 Binding dintercepteur Avec CDI, une annotation Ensuite on peut dire quun objet est transactionnel Ou juste Transactional public class ShoppingCart {... } public class ShoppingCart public void checkout() {... } } 117

118 Implémentation de lintercepteur Un intercepteur annoté et notre Peut utiliser linjection de dépendance Il peut y avoir plusieurs intercepteurs du même type public class TransactionInterceptor UserTransaction public Object manageTransaction(InvocationContext ctx) throws Exception {... } } 118

119 Activation des intercepteurs Par défaut les intercepteurs sont desactivés on doit les activer dans META-INF/beans.xml spécifie lordre des intercepteurs permet de choisir lors du déploiement les intercepteurs à utiliser org.mycompany.myapp.TransactionInterceptor 119

120 Bindings dIntercepteurs avec membre Idem que pour les beans: si le membre nest pas les membres doivent correspondre pour quil y Transactional { boolean requiresNew() default Secure String[] rolesAllowed() default {}; } 120

121 Plusieurs intercepteurs bindings Plusieurs intercepteurs pour un bean: Un intercepteur avec public class ShoppingCart @Interceptor public class TransactionalSecureInterceptor {... } public class public void checkout() {... } public class ShoppingCart public void checkout() {... } public class ShoppingCart public void checkout() {... public class ShoppingCart { public void checkout() {... } } 121

122 122 Etudiez lapplication 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

123 7- Décorateurs

124 Intercepteurs vs. Décorateurs Les intercepteurs offrent des services orthogonaux à lapplication transactions, sécurité,... ils ne connaissent pas la sémantique de lobjet intercepté ils sont utilisables par une grande variété dobjets 124

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é quun intercepteur Les intercepteurs et les décorateurs sont complémentaires 125

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); public abstract class LargeTransactionDecorator implements Account {... } 126

127 Décorateurs Un décorateur implémente linterface décorée définit les méthodes ququon doit intercepter peut utiliser linjection de dépendance peut être une classe abstraite ! Les intercepteurs sont appelés AVANT les décorateurs 127

128 public abstract class LargeTransactionDecorator implements @Any Account EntityManager em; public void withdraw(BigDecimal amount) {... } public void deposit(BigDecimal amount);... } } 128

129 public abstract class LargeTransactionDecorator implements @Any Account EntityManager em; public void withdraw(BigDecimal amount) {... } public void deposit(BigDecimal amount);... } } 129 Les décorateurs ont un point dinjection pour lobjet délégué du même type que lobjet décoré

130 Objet délégué Un décorateur peut appeler nimporte quelle méthode de lobjet décoré ! public abstract class LargeTransactionDecorator implements @Any Account 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) ); } } }

131 Binding Un decorateur est associé à tout bean tel que: Le type du point dinjection est un des types du bean Le bean a tous les qualifiers declarés au @Any Account account; décore tous les beans qui Account account; décore seulement les beans qui implément Account et qui ont les 131

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 lordre des décorateurs permet de choisir lors du déploiement les décorateurs à utiliser org.mycompany.myapp.LargeTransactionDecorator 132

133 133 Sur la base de lapplication numberguess9 Implementez un décorateur TricheurDecorator pour être sûr que le nombre à chercher est en réalité entre 1 et 5 Exercice10

134 8- Evènements

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 135

136 Evènements dans CDI Les producteurs dévènements lèvent des évènements qui sont passés aux observeurs par le conteneur 136

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 lensemble de notifications dévènements quils reçoivent Les observateurs peuvent être notifiés immédiatement, ou après la fin de la transaction. 137

138 Objet évènement Comme dans le patron de conception classique Nimporte quel objet java + peut avoir des qualifieurs Permet aux observateurs de spécifier un sous-ensemble des évènements quil observe 138

139 Observateur Un observateur est une méthode de bean avec un paramètre le paramètre dévènement est document lobservateur peut spécifier des qualifieurs pour restreindre les évènements quil observe (ci-dessus, par Lobservateur peut avoir dautres paramètres (ce sont des points dinjection) public void Document document) {... } public Document document) {... } public Document document) {... } public void Document document, User user) {... } 139

140 Producteurs dévènements Les producteurs dévènement lèvent des évènements en utilisant linterface paramétrée Event, obtenue par injection Pour lever Event documentEvent; documentEvent.fire(document); 140

141 Event Event documentEvent; documentEvent.fire(document); Produit un évènement sans qualifieur Produit un évènement avec @Any Event documentEvent; documentEvent.select(new AnnotationLiteral (){}).fire(document); Produit un évènement avec le 141

142 Méthode observateur conditionnelle Par défaut, si aucune instance dun observateur existe dans le contexte courant, le conteneur en crée une. Si on ne veut pas, Un ne peut pas être un observateur conditionnel (il ne serait jamais appelé) ! public void = Document d) {... } 142

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 à lobserveur Si le membre nest @Target({PARAMETER, Role { RoleType value(); } public LoggedIn event) {... } 143

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 implements Role {} documentEvent.select(new RoleBinding() { public void value() { return user.getRole(); Event loggedInEvent; loggedInEvent.fire(document); 144

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 = AFTER_SUCCESS) CategoryUpdateEvent event) {... } 145

146 146 Sur la base de lapplication 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

147 9- Stéréotypes

148 Stéréotypes Un stéréotype est une annotation Regroupe un ensemble de @Target(TYPE)... Action {} 148

149 Portée par défaut Un stéréotype peut définir une portée par défaut pour les beans qui Action public class LoginAction public class DependentScopedLoginAction {... } Portée Requête Portée Dependent 149

150 Intercepteurs Et si on a toute une catégorie de beans qui ont les mêmes Intercepteurs ? utiliser un Action {} nos interceptor bindings 150

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 @Stereotype Action {} 151

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 AlternativeAction {} 152

153 Le stéréotype Model CDI définit un stéréotype à utiliser dans les applications Web à la place dun JSF Model {} 153

154 10- Amélioration de Java EE avec CDI

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 155

156 Définir une ressource Une ressource est un objet disponible dans lenvironnement Java EE JDBC Datasource, JMS Queues, Topics and ConnectionFactorys, JavaMail Sessions et autres ressources transactionnelles, JPA EntityManagers et EntityManagerFactorys, remote EJBs, et services web 156

157 Un bean producteur de ressources Ressource= données JEE + @CustomerDatabase @CustomerDatabase @CustomerDatabase PaymentService paymentService; 157

158 Et ainsi... Un bean ResourcesProducer avec la liste des ressources pour le deploiement normal Un bean ResourcesProducer avec la liste des ressources pour le deploiement de test1 Un bean ResourcesProducer avec la liste des ressources pour le deploiement de test

159 Enfin On peut utiliser les ressources plus propre, moins de code à changer si EntityManagerFactory PaymentService paymentService; 159

160 Context and Dependency Injection Maxime Lefrançois M2 MIAGE Casablanca


Télécharger ppt "Context and Dependency Injection Maxime Lefrançois M2 MIAGE Casablanca"

Présentations similaires


Annonces Google