73
EJB 3 formation interne pour CLIO S.A. Cédric BOTTERO Michaël MATHIEU Genève, le 30 juin 2009

EJB-3

Embed Size (px)

Citation preview

Page 1: EJB-3

EJB 3formation interne pour CLIO S.A.

Cédric BOTTERO

Michaël MATHIEU

Genève, le 30 juin 2009

Page 2: EJB-3

Plan

• Introduction

• 3 types d’EJB (Session, Entity, Message-Driven)

• Injection et JNDI

• Intercepteurs et callbacks• Intercepteurs et callbacks

• Transactions (CMT, BMT)

• Sécurité

• Persistance avec JPA

Page 3: EJB-3

Introduction

• Permet d’éviter au développeur d’avoir à se préoccuper de tout ce qui a trait au système :

– Transactions

– Sécurité

– Evolutivité– Evolutivité

– Concurrence

– Communications

– Gestion des ressources

– Persistance

– Gestion des erreurs

– Etc.

Page 4: EJB-3

3 types d’EJB

• Session

– Stateless

– Stateful

• Entity• Entity

• Message-Driven

Page 5: EJB-3

Session

• Sont conçus pour encapsuler la logique métier

• Les plus utilisés

• 2 types d’EJB session :

– Stateless– Stateless

– Stateful

Page 6: EJB-3

Session -> Stateless

• Stateless (sans état) => les attributs de l’EJB sont réinitialisées entre chaque appel même s’il s’agit du même client

• Sont spécialement pensés pour être robustes et fiables lorsqu’il y a beaucoup d’appels en concurrence

• Lorsqu’un client appelle l’EJB, une instance de ce dernier sert le client, puis, retourne dans le pool d’EJB (cette dernière est donc prête a être réutilisée pour un autre client)

• A utiliser le plus souvent possible (par rapport aux Stateful) => cycle de vie

Page 7: EJB-3

EJB 2 vs. 3

• Pour les EJB session stateless, nous commencerons

par présenter leur utilisation avec les EJB 2, puis

avec les 3

• Le but est de montrer les améliorations et • Le but est de montrer les améliorations et

simplifications amenées avec la version 3

• Cela permettra également de mieux comprendre le

principe de fonctionnement des EJB (par exemple,

l’utilisation du

javax.rmi.PortableRemoteObject.nar

row(…))

Page 8: EJB-3

Structure d’un EJB

• Avec les EJB 2, la configuration des EJB se fait dans

le fichier META-INF/ejb-jar.xml

• Avec les EJB 3, le fichier de configuration n’est plus

nécessaire: la configuration se fait dans le code au nécessaire: la configuration se fait dans le code au

moyen des annotations

Page 9: EJB-3

Session -> Stateless

EJB 2

Page 10: EJB-3

Session -> Stateless

EJB 2

• Par convention, et ce afin d’éviter des

malentendus, les méthodes métier ne doivent pas

commencer par « ejb »

Page 11: EJB-3

Session -> Stateless

EJB 2META-INF/ejb-jar.xml

Page 12: EJB-3

Session -> Stateless

EJB 2

Page 13: EJB-3

Session -> Stateless

EJB 3

Page 14: EJB-3

Session -> Stateless

EJB 3

Page 15: EJB-3

Session -> Stateful

• Stateful (avec état) => les attributs de l’EJB sont sauvegardés durant toute la session

• Lorsqu’un client appelle l’EJB, une instance de ce dernier est créée, puis sert le client. Cette instance reste disponible pour les futurs appels de ceclient uniquement. Cette instance sera détruite à la fin de la session (timeout ou appel à une méthode portant l’annotation @Remove)

• S’il y a trop d’instances d’un EJB en mémoire, ces dernières peuvent être sorties de la mémoire de travail. Elles passent ainsi en mode passif (= sauvées sur disque => tous les attributs doivent être sérialisables = types implémentant l’interface Serializable)

Page 16: EJB-3

Sérialisation

• Le type des attributs et le type de retour de chaque méthode doivent être Serializable (sauf dans le cas d’une méthode d’un EJB stateless local)

• Par précaution, nous tâcherons de veiller à ce que tous les types que nous utilisons soient Serializable

• Le serialVersionUID permet de faire la distinction entre des objets de même type, mais d’une version différente

• Lorsque qu’un objet est reçu, le destinataire vérifie que le serialVersionUID• Lorsque qu’un objet est reçu, le destinataire vérifie que le serialVersionUIDde l’objet reçu correspond à celui de la classe qu’il a chargé. S’il diffère, une InvalidClassException est lancée

• Ce mécanisme permet de s’assurer que l’émetteur et le destinataire travaillent avec la même version de l’objet

• Cette solution a une faiblesse: lors d’une modification, elle nécessite que toutes les applications qui utilisent cette classe doivent être mis à jour, alors que cela n’est pas forcément nécessaire. En effet, dans le cas où on ajoute un nouvel attribut à un objet, cela ne signifie pas forcément que toutes les applications ont l’utilité de ce nouvel attribut…=> on donne une valeur arbitraire par défaut au serialVersionUID et on ne la modifie pas

Page 17: EJB-3

Local vs. Remote

• Permet de spécifier la manière d’accéder à l’EJB =>

l’implémentation des services est identique

• Local

≠ appel à un EJB se trouvant sur la même machine≠ appel à un EJB se trouvant sur la même machine

= appel à un EJB se trouvant dans la même JVM

• Remote

– utilise RMI (Remote Method Invocation) (=> plus lent

qu’un appel local) et JNDI (Java Naming and Directory

Interface)

– utilisé dans la majorité des cas

Page 18: EJB-3

Local

EJB 2

Page 19: EJB-3

Local

EJB 2

Page 20: EJB-3

Local

EJB 2META-INF/jboss.xml

Page 21: EJB-3

Local

EJB 2

Page 22: EJB-3

Local

EJB 2META-INF/jboss.xml

Page 23: EJB-3

Local

EJB 2

Page 24: EJB-3

Local

EJB 3

Page 25: EJB-3

Entity

• Permet de gérer la persistance comme le ferait

Hibernate sur le concept de object-relational

mapping (ORM) => illusion de travailler avec une

base de données objetbase de données objet

• Le mapping ne se fait plus forcément dans un

fichier XML (comme hibernate.cfg.xml),

mais directement dans le code avec des

annotations (@Id, @Column, etc.)

• D’avantage de détails dans le dernier chapitre de

ce cours « Persistance avec JPA »

Page 26: EJB-3

• Permet à des applications de communiquer entre elles, en étant faiblement

couplées, et de manière asynchrones

• Ce concept est connu sous le nom de Message-oriented middleware (MOM)

• Les produits implémentant ce mécanisme sont nombreux comme IBM

WebSphere MQ (anciennement MQSeries), JBoss Messaging (qui remplacera

JBoss MQ), etc.

Message-Driven

JBoss MQ), etc.

PTP (point-to-point) pub-sub (publish-subscribe)javax.jms.Queue javax.jms.Topic

Page 27: EJB-3

Message-Driven

• Nous devons configurer le produit qui implémente le

mécanisme JMS. Ici, il s’agit de JBoss MQ qui est intégré à

notre version de JBoss (4.0.5-GA)

• Le fichier de configuration doit être déposé dans le répertoire

<jboss-install>/server/<configuration-<jboss-install>/server/<configuration-

name>/deploy/jms, et son nom doit se terminer par –

service.xml

Page 28: EJB-3

Message-Driven

EJB 3

Page 29: EJB-3

Message-Driven

EJB 3

Page 30: EJB-3

Message-Driven

EJB 3

Page 31: EJB-3

Message-Driven

• Il y a la possibilité de mettre un filtre sur les messages qui

peuvent être traités par un MDB. Cela permet de ne pas

recevoir certains messages. Cette propriété est surtout

intéressante dans le cas d’une Queue (PTP), car le message

n’est envoyé qu’à un seul MDB. Dans le cas d’un Topic (pub-n’est envoyé qu’à un seul MDB. Dans le cas d’un Topic (pub-

sub), cela permet surtout de ne pas avoir à tester si le message

reçu peut être traité par le MDB

• Pour d’avantage de précisions sur la propriété

messageSelector, nous vous renvoyons à la page 131 du

livre « EJB 3 in Action », 2007, Manning

Page 32: EJB-3

Injection et JNDI

• L’annotation @Resource permet d’injecter un objet référencé (au sens large: DataSource, JMS, EJB, Context, etc.). Il est possible de spécifier le nom JNDI de l’objet pour lever une ambiguïté. Par exemple, dans le cas d’une DataSource, s’il y en a plusieurs définies sur le serveur, il faudra alors donner son nom JNDI (@Resource(name="jdbc/myDB")avec les EJB 2, dans le descripteur de déploiement, on utilisait la balise <res-ref-name>)

• Il est également possible d’injecter des variables d’environnement (de type String, Character, Byte, Short, Integer, Long, Boolean, Double

String, Character, Byte, Short, Integer, Long, Boolean, Doubleou Float) qui ont été préalablement déclarées dans le descripteur de déploiement :

• Lors du déploiement, le conteneur résout les références JNDI et relie les ressources en question. Si une ressource n’est pas trouvée lors du déploiement, le conteneur lance une RuntimeException; l’EJB est alors inutilisable

Page 33: EJB-3

Intercepteurs

• Lorsqu’une méthode métier est appelée, les intercepteurs

permettent d’exécuter des méthodes avant que la méthode métier

ne soit exécutée

• Les intercepteurs peuvent être utiles dans plusieurs situations: pour

mettre des logs sans avoir à surcharger le code, pour gérer la mettre des logs sans avoir à surcharger le code, pour gérer la

sécurité séparément du code métier, etc.

• Exemple pour vérifier le rôle de l’appelant :

Page 34: EJB-3

Intercepteurs

EJB 3

• Les intercepteurs peuvent être défini au niveau du descripteur de

déploiement, de la classe, de la méthode (ordre dans lequel ils sont

appelés)

Page 35: EJB-3

Callbacks

• Les callbacks permettent d’exécuter des méthodes lorsque

certains événements liés au cycle de vie de l’EJB interviennent

(création, suppression, hibernation, réveil)

• Après la création (@PostConstruct) (Stateless, Stateful,

Message-Driven)Message-Driven)

• Avant la suppression (@PreDestroy) (Stateless, Stateful,

Message-Driven)

• Avant l’hibernation (@PrePassivate) (Stateful)

• Après le réveil (@PostActivate) (Stateful)

Page 36: EJB-3

Intercepteurs et callbacks

• Session -> Stateless

Page 37: EJB-3

Intercepteurs et callbacks

• Session -> Stateful

Page 38: EJB-3

Intercepteurs et callbacks

• Entity

Page 39: EJB-3

Intercepteurs et callbacks

• Message-Driven

Page 40: EJB-3

Transactions

ACID

• AtomicitéPour atteindre un but donné, une transaction est composée de plusieurs opérations qui sont indispensables => soit toutes les opérations sont effectuées, soit aucune !

• CohérenceAprès qu’une transaction se soit réalisée, le base de données ou le système doit se trouver dans un état cohérentdans un état cohérent

• IsolationUne transaction doit se réaliser sans dépendre des autres transactions qui peuvent avoir lieu en même temps

• DurabilitéLorsqu’une transaction s’est terminée, le résultat de cette dernière est durable : que la transaction ait été annulée ou qu’elle se soit terminée correctement, les opérations qu’elle a effectué ne doivent pas disparaître

• Exemple : transfert bancaire

Page 41: EJB-3

Transactions

• JTA (Java Transaction API) fournit un API permettant de gérer

les transactions :

– BMT (Bean-Managed Transactions) =>

@TransactionManagement(TransactionManagementTyp

e.BEAN)e.BEAN)

– CMT (Container-Managed Transactions) =>

@TransactionManagement(TransactionManagementTyp

e.CONTAINER)

– Par défaut, le conteneur gère les transactions

• JPA (Java Persistance API) ne dépend pas du mode de gestion

des transactions => n’influe que sur les EJB Session et les

Message-Driven, et non sur les Entity

Page 42: EJB-3

CMT

• Le conteneur démarre, valide ou annule la transaction. La

transaction commence au début de l’exécution de la méthode

métier appelée et se termine à la fin de cette dernière

@TransactionAttribute

Transaction

existante lors Résultat@TransactionAttribute existante lors

de l'appel ?

Résultat

REQUIRED Non Le conteneur crée une nouvelle transaction

(par défaut) Oui La méthode rejoint la transaction existante

REQUIRED_NEW Non Le conteneur crée une nouvelle transaction

Oui Le conteneur crée une nouvelle transaction et la transaction

existante est suspendue

SUPPORTS Non Aucune transaction n'est utilisée

Oui La méthode rejoint la transaction existante

MANDATORY Non Lève une javax.ejb.EJBTransactionRequiredException

Oui La méthode rejoint la transaction existante

NOT_SUPPORTED Non Aucune transaction n'est utilisée

Oui La transaction existante est suspendue et la méthode est

appelée sans transaction

NEVER Non Aucune transaction n'est utilisée

Oui Lève une javax.ejb.EJBException

Page 43: EJB-3

CMT

• On peut forcer le fait que la transaction soit annulée (context.setRollBackOnly())

• Les méthodes setRollbackOnly() et getRollbackOnly() ne peuvent être appelées que depuis un EJB dont les transactions sont gérées par le depuis un EJB dont les transactions sont gérées par le conteneur (CMT) et ayant comme attribut de transaction REQUIRED, REQUIRED_NEW ou MANDATORYSinon une IllegalStateException est levée !

• Si le conteneur détecte une exception système (principalement les RuntimeException) comme une ArrayIndexOutOfBoundsException ou une NullPointerException, la transaction sera automatiquement annulée

Page 44: EJB-3

CMT

• Avec CMT, nous n’avons pas le contrôle sur le moment où la

transaction est démarrée, validée ou annulée

• Il est possible d’être informé de ces évènements grâce à des

callbacks

• L’EJB doit implémenter l’interface • L’EJB doit implémenter l’interface

javax.ejb.SessionSynchronization

– void afterBegin() — Est appelé juste après que le conteneur ait créé

une nouvelle transaction et avant que la méthode métier soit appelée

– void beforeCompletion() — Est appelé lorsque la méthode métier

s’est terminée et juste avant que le conteneur termine la transaction

– void afterCompletion(boolean committed) — Est appelé après

que la transaction soit terminée. Le flag committed indique si la transaction

a été validée (true) ou si elle a été annulée (false)

Page 45: EJB-3

BMT

• On utilise la UserTransaction

– @Resource private UserTransaction userTransaction;

OU

– @Resource private SessionContext context;

...

UserTransaction userTransaction = UserTransaction userTransaction =

context.getUserTransaction();

• userTransaction.begin();

...userTransaction.commit();

OUuserTransaction.rollback();

• La UserTransaction ne peut être utilisée que dans le cas où les transactions sont gérées par l’EJB (BMT); dans le cas où c’est le conteneur (CMT) une IllegalStateException est levée

Page 46: EJB-3

Transactions distribuées

XA (eXtended Architecture)• Afin de garantir les propriétés ACID vues précédemment, dans

un contexte où les sources de données sont distribués, il faut

que les drivers des bases de données soient de type XA

• L’architecture XA définit un protocole de validation en 2 phases

et un API pour la communication entre un transaction et un API pour la communication entre un transaction

manager et un resource manager

• Dans le cas d’une transaction où l’on doit enregistrer des

données dans 2 bases de données, que faire si lors de la

validation une se déroule avec succès et l’autre non ?

L’application se trouvera alors dans un état inconsistant et les

propriétés ACID ne seront plus respectées !

=> utilisation du protocole de validation en 2 phases

Page 47: EJB-3

Sécurité

• JAAS (Java Authentication and Authorization Service) est une API standard

de Java permettant de gérer les identifications et les droits associés (par

rôles) au niveau du client et du serveur d'application

• Principe de fonctionnement :

– Dans un premier temps, JAAS authentifie (valide l'identité du client)

– Puis gère les autorisations (valide les droits d'accès pour un client authentifié)

– Les identités sont regroupées en rôles et les autorisations accordées par rôle

• Côté client, la technique la plus simple, mais aussi la plus ancienne et la

plus limitée : le username (Context.SECURITY_PRINCIPAL) et le

password (Context.SECURITY_CREDENTIAL) sont transmis avant le

lookup au contexte JNDI

Page 48: EJB-3

Sécurité

• L’authentification est réalisée par une application web qui ensuite appelle l’EJB en lui passant le Principal

• Pour sécuriser une méthode, il existe 2 possibilités :

– Avec les annotations (@RolesAllowed(...), @PermitAll, @DenyAll)

– Avec la méthode isCallerInRole(...)

Page 49: EJB-3

Sécurité

• Dans un premier temps, il faut configurer la sécurité JAAS sur le serveur

• Pour nous simplifier la tâche, nous utiliserons la méthode d’authentification

SimpleServerLoginModule :

– Si le mot de passe est null, alors l’utilisateur est authentifié avec le rôle guest

– Si le nom d’utilisateur est égal au mot de passe, alors l’utilisateur est authentifié avec les

rôles guest et userrôles guest et user

– Sinon l’authentification échoue

• Pour cela, nous devons définir une politique de sécurité dans le fichier <jboss-

install>/server/<configuration-name>/conf/login-

config.xml

Page 50: EJB-3

Sécurité

• Remarque : dans le cadre d’une vraie application, nous aurions

plutôt utilisé la méthode d’authentification

DatabaseServerLoginModule qui effectue une requête

dans une base de données qui contiendrait les noms

d’utilisateurs, les mots de passe, ainsi que les rôles associés d’utilisateurs, les mots de passe, ainsi que les rôles associés

aux utilisateurs

• Dans les 2 exemples qui suivent, on déclare le domaine de

sécurité par l’annotation @SecurityDomain(...)

ATTENTION utiliser l’interface

org.jboss.annotation.security.SecurityDoma

in et non

org.jboss.aspects.security.SecurityDomain

Page 51: EJB-3

Sécurité

• Avec les annotations

Page 52: EJB-3

Sécurité

• Avec la méthode isCallerInRole(...)

Page 53: EJB-3

Sécurité

• Pour pouvoir accéder aux méthodes précédemment

sécurisées, il faut que l’appelant soit correctement identifié

avec JAAS

• Prenons le cas d’une application web

Page 54: EJB-3

Sécurité

• Définir le domaine de sécurité : fichier <your-web-

app>/WEB-INF/jboss-web.xml

• Définir ce qui sera sécurisé, comment, et quelle sera la page

d’authentification et la forme de celle-ci : fichier <your-

web-app>/WEF-INF/web.xml (contenu sur le slide

suivant)

Page 55: EJB-3
Page 56: EJB-3

Sécurité

• Page JSP qui permet d’appeler l’authentification JAAS : fichier

<your-web-app>/WEB-INF/jsp/login.jsp

Page 57: EJB-3

Sécurité

• Appel de l’EJB depuis la Servlet :

Page 58: EJB-3

Persistance avec JPA

• Intérêt de JPA: permet d’être indépendant du framework

gérant la persistance => si Hibernate venait à disparaître,

l’utilisation de son successeur ne demanderait que peu

d’adaptation

• Pour cette partie, nous partons du principe que vous êtes déjà • Pour cette partie, nous partons du principe que vous êtes déjà

familiarisé avec Hibernate et avec le concept d’ORM (Object-

Relational Mapping)

• Au passage, nous profitons pour vous indiquer une excellente

référence : Hibernate 3.0, 2005, Eyrolles

Page 59: EJB-3

Persistance avec Hibernate

• Un petit rappel sera tout de même le bienvenu !

• Les différents types de relations :– one-to-one => <one-to-one name="user" class="User" constrained="true" />

(Email.hbm.xml)

– many-to-one => <many-to-one column="NATIONALITY" name="nationality“ class="Country" /> (User.hbm.xml)

– one-to-many => <set name="users" inverse="true">

<key column="NATIONALITY" />

<one-to-many class="User" />

</set> (Country.hbm.xml)

– many-to-many => <set name="bookmarks" table="WEBSITE_USER">

<key column="ID_USER" />

<many-to-many class="WebSite" column="ID_WEBSITE" />

</set> (User.hbm.xml)

Page 60: EJB-3

Persistance avec JPA

• Activer la persistance JPA (META-INF\persistence.xml)

• Au préalable une DataSource

a été déclarée sur le serveur

(<jboss-install>/

server/

<configuration-name>

/deploy)

Page 61: EJB-3

Persistance avec JPA

@Entity

• Cette annotation permet de spécifier qu’une classe doit être

persistée par JPA

• Cette classe doit posséder un constructeur public ou

protected sans argument protected sans argument

@Transient

• Permet de spécifier qu’il ne faut pas persister un attribut

donné

Page 62: EJB-3

Persistance avec JPA

@Id

• Permet de définir quel champ sera utilisé comme clé primaire

@IdClass, @Embeddable + @EmbeddedId@IdClass, @Embeddable + @EmbeddedId

• Permettent de définir des clés composées

• Nous n’allons pas les aborder dans le cadre de ce cours

• Nous vous renvoyons à la page 235 du livre « EJB 3 in action »,

Manning, 2007

Page 63: EJB-3

ORM

• @OneToOne

Remarque: fonctionne très bien dans une utilisation « naïve », mais cela devient problématique lorsque l’on veut utiliser des fonctionnalités plus intéressantes, comme

@PrimaryKeyJoinColumn

[http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_S[http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_Relationships]

• @OneToMany

• @ManyToOne

• @ManyToMany

Page 64: EJB-3

ORM

Page 65: EJB-3

ORM

Page 66: EJB-3

ORM

Page 67: EJB-3
Page 68: EJB-3

ORM

• Inconvénients des annotations, surtout dans le cas de la

persistance JPA :

– Dégrade la lisibilité du code

– Perte de la séparation entre Entité et Mapping

– En cas de modification, nécessite de recompiler les classes modifiées, – En cas de modification, nécessite de recompiler les classes modifiées,

au lieu de juste modifier les fichiers de mapping concernés

=> à utiliser plutôt dans le cas d’un prototype

• Solution plus élégante : utilisation d’un fichier de mapping XML

(META-INF\orm.xml) (contenu sur les slides suivant)

Page 69: EJB-3

orm.xml (1/2)

Page 70: EJB-3

orm.xml (2/2)

Page 71: EJB-3

Callbacks

• Comme pour les EJB session et les Message-Driven, il existe

des callbacks pour le Entity

• Avant / après la persistance d’une Entity (@PrePersist /

@PostPersist)

Après avoir chargé une Entity lors d’une requête ou d’un • Après avoir chargé une Entity lors d’une requête ou d’un

refresh (@PostLoad)

• Avant / après la mise à jour d’une Entity (@PreUpdate /

@PostUpdate)

• Avant / après la suppression d’une Entity (@PreRemove /

@PostRemove)

Page 72: EJB-3

Références

• EJB 3 in action, 2007, Manning

• JBoss in action, 2009, Manning

• The J2EE 1.4 Tutorial, 2005, SUN [http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html]

• EJB 2, 2005, SUPINFO [http://www.labo-sun.com/resource-fr-essentiels-835-0-java-j2ee-ejb-2-les-entreprise-java-bean-javabeans-.htm]

• EJB 3, 2006, SUPINFO [http://www.labo-sun.com/resource-fr-essentiels-836-0-java-j2ee-ejb-3-les-entreprise-java-bean-version-3-javabeans-.htm]

• Java Persistence, WIKIBOOKS [http://en.wikibooks.org/wiki/Java_Persistence]

Page 73: EJB-3

FIN

Merci pour votre attention !