EJB3.
1/Java EE 6
S. Rosmorduc, Conservatoire National des Arts et Mtiers
(avec des vrais bouts de transparents de Marc Le Bihan dedans)
1
Bibliographie et sources
Oracle Java EE 6 tutorial
A. Goncalves, Beginning Java EE6
Cours GLG203 2012-2013 Marc Le Bihan
2
Plan
Rappels d'architecture
Dnition des EJB
Types dEJB
Interfaces dEJB
Cycle de vie
Utilisation des EJB
Dploiement
Concurrence
Transactions
Mcanismes sous-jacents
3
Rappels d'architecture
Couche Prsentation
(Web, Swing)
Couche Mtier
Couche Accs aux donnes
(DAO)
4
Rappels d'architecture
Couche Mtier
faade1 = service faade2 = service
classe mtier
classe mtier
classe mtier
5
Rappels d'architecture
Les #services# vont servir de faade pour laccs
au couche mtier
Ils sont organiss selon les use-case
Permettent disoler la couche mtier de son
interface : couplage plus faible, meilleure scurit
En JEE, ils sont implants sous forme dEJB
Ils peuvent tre rpartis (remote beans) : leur
interface permet de contrler les oprations
possibles.
6
Dnition des EJBs
Objets Grs par le serveur applicatif
crs et partags par le serveur applicatif
rcupration par appels JNDI ou Injection de
dpendance
le cycle de vie dpend du type de bean
Vous nappellerez jamais new pour crer un
EJB (sauf ventuellement pour les tests)!!!
Objets faade pour les couches mtier
7
Caractristiques des
EJBs
objet dcors fournissant des services
supplmentaires
accs distant
gestion de transaction
vnements lis au cycle de vie
injection de dpendances
8
Contraintes
ne crent pas de threads
pas de champ statique
mthodes exportes non nal
classe non nal
pas de mthode nalize() (anti-pattern, de
toutes faons)
9
Types d'EJB
Stateless
frquemment utilis comme faade
daccs aux donnes
Stateful
Singleton
Message-driven Bean (plus tard)
10
EJB Stateless
Pas dtat : on ne peut
pas garder dinformation
dans les variables
dinstance du bean
Annotation : @Stateless
Trs souvent utilis pour
laccs aux donnes
Injection
dEntityManager (JPA)
par
@PersistenceContext
11
@Stateless
public class ForumBean {
@PersistenceContext
EntityManager em;
public Message
addMessage(Message newMessage) {
[Link](newMessage);
return newMessage;
}
public Message getMessage(Long id) {
return [Link]([Link], id);
}
public List<MessageList> getAllMessages() {
return [Link](
"select m from Message m").getResultList();
}
}
LEJB sans tat
(Stateless bean)
Parce quil est sans tat, le stateless bean ne
devrait pas comporter de variables membres,
sinon en considrant ceci:
Elles ont des chances de ne plus avoir de
contenu lappel suivant.
et il y a un risque quelles aient encore le
contenu quelles avaient lappel
prcdent.
12
LEJB sans tat peut
tre initialis
Il reste possible de procder son
initialisation dans une mthode porteuse de
lannotation
@PostConstruct
Et un quivalent destructeur pourra
tre dni dans une mthode annote
@PreDestroy
13
Cycle de vie
et annotations
Le serveur maintient un pool de Stateless beans
Un nouveau bean est initialis par son constructeur,
puis par linjection de dpendances
puis par lappel de la mthode annote par @PostConstruct
(si elle existe)
quand le bean va tre libr par le serveur, il appelle la
mthode annote par @PreDestroy
important: si vous voulez initialiser votre bean en accdant
des valeurs de champs xes par injection, il faut le faire dans
la mthode @PostConstruct
14
nexiste
pas
prt
2. injection de dpendance
3. @PostConstruct
3. @PreDestroy
1. cration, constructeur
EJB Stateful
Bean tat, sera gnralement stock en
session une fois cr
Annotation @Stateful
Doit tre Serializable (sinon, pas de
passivation possible)
Exemple typique: panier provisions
15
Cycle de vie et
annotations
Lappel dune mthode annote par
@Remove demande la suppression du bean
16
nexiste
pas
2. injection de dpendance
3. @PostConstruct
1. @Remove
passif prt
1. cration, constructeur
2. @PreDestroy
@PrePassivate
@PostActivate
Exemple
17
@Stateful
public class BasketBean implements Serializable {
private HashSet<Product> products=
new HashSet<Product>();
public void addProduct(Product p) {
// .....
}
@Remove
public void doOrder() {
// Sauve la commande dans la base de donnes
}
}
lappel de cette mthode dclenche la destruction du
bean (@Remove)
Singleton
Bean qui nexiste quen un seul exemplaire
sur un serveur (application rpartie:
ventuellement un singleton par serveur)
Exemple: catalogue charg en mmoire,
conversation entre utilisateurs (non
permanente)
Attention: accs concurrents trs
probables.
18
Cycle de vie
et annotations
Le serveur propose toujours la mme
instance dun bean singleton.
Lannotation @Startup demande que le
bean soit cr ds le lancement de
lapplication
Des annotations permettent de grer les
accs concurrents
19
nexiste
pas
prt
2. injection de dpendance
3. @PostConstruct
3. @PreDestroy
1. cration, constructeur
Singleton et accs
concurrent
Les mthodes dun bean singleton seront
srement appeles simultanment par
plusieurs threads
Il importe donc de grer la concurrence
Cest possible simplement grce aux
annotations Lock
On distingue laccs en lecture
(paralllisable) et en criture (bloquant)
20
/**
* Catalogue stock en mmoire.
* pas follement pratique: l'accs en BD est plus
* simple.
*/
@Singleton
@ConcurrencyManagement([Link])
public class InMemoryCatalog {
@EJB
ProductService productService;
public Collection<Product> products;
@PostConstruct
@Lock([Link])
public void initCatalog() {
products = new HashSet<Product>([Link]());
}
@Lock([Link])
public void rafraichirCatalogue() {
initCatalog();
}
@Lock([Link])
public Collection<Product> getProducts() {
return products;
}
}
Singleton et
accs concurrent
21
optionnel
(CONTAINER par dfaut)
injection de laccs aux donnes
non parallle
parallle
Singleton et accs
concurrent
@ConcurrencyManagement([Link]
TAINER) : gestion automatique par le conteneur
@ConcurrencyManagement([Link]
) : gestion manuelle
@Lock([Link]) : mthode de lecture. Paralllisable.
@Lock([Link]): mthode dcriture, non paralllisable.
Valeur par dfaut.
Quand une mthode dcriture est en cours dexcution, elle
interdit lappel de toute autre mthode (lecture ou criture)
On peut appeler simultanment autant de mthode de lecture
quon veut.
22
Interfaces d'accs
Les beans ont t conus pour pouvoir construire des systmes
rpartis => accs distant
On peut avoir plusieurs types dinterface pour un bean
Aucune (quivaut #local# uniquement)
Local : interface utilisable au sein de la mme application que celle
qui hberge le bean
Remote : interface utilisable distance
diffrences avec RMI
paramtres des mthodes remote
LocalBean
23
Exemple: un bean
daccs aux produits
Dispose de trois mthodes
getProducts() : renvoie la liste des produits
addProduct(Product p) : ajoute un nouveau
produit
removeProduct(Product p) : supprime un
produit de la liste
On veut que le client distance puisse lister les
produits, mais pas les supprimer ou ajouter
24
Exemple (2)
25
@Local
public interface ProductLocal extends ProductRemote {
void addProduct(ProductDTO p);
void removeProduct(ProductDTO p);
}
@Remote
public interface ProductRemote {
public Collection <ProductDTO> getAllProducts();
}
@Stateless
public class ProductService implements ProductLocal, ProductRemote {
@Override
public void addProduct(ProductDTO p) {
//....
}
@Local
interface utilise pour laccs interne
lapplication
26
@Remote
Interface utilise pour les accs distants
Les arguments et les valeurs retournes
par les mthodes de linterface Remote
doivent tre Serializable.
27
Et si on ne dit rien ?
Un EJB sans annotation locale ou remote est
considr comme local.
Note importante: quand on a une interface locale
ou remote, seules les mthodes de cette interface
sont des mthodes EJB (transactionnelles, entre
autres). Les autres mthodes sont #normales#
Quand on na pas dinterface dclare, linterface
locale correspond lensemble des mthodes
publiques.
28
Utilisation des beans
Nombreuses manires de faire rfrence des beans
En JSF
injection de dpendance
Entre beans
rgles
Depuis une application cliente
JNDI
Depuis une Servlet
29
Accs depuis un
Managed Bean JSF
Dans larchitecture JSF, les clients des EJB
sont essentiellement les managed beans
Trs simple: on place lejb comme variable
dinstance et on utilise linjection de
dpendance.
Annotation : @EJB (ou @Inject)
30
Accs depuis un
Managed Bean JSF
31
@ManagedBean
@RequestScoped
public class CreatePersonBean {
@EJB
PersonService personService;
private String name;
private int age;
private Person person; // Or DTO : Data transfer Object
public void createPerson() {
person= [Link](name, age);
name= "";
age= 0;
}
public String getName() {
return name;
}
EJB
Accs depuis un Managed Bean JSF:
version #moderne#
32
@Named
@RequestScoped
public class CreatePersonBean {
@Inject
PersonService personService;
private String name;
private int age;
private Person person; // Or DTO : Data transfer Object
public void createPerson() {
person= [Link](name, age);
name= "";
age= 0;
}
public String getName() {
return name;
}
EJB
Injection et interfaces
Remote et Local
Pour linjection, le type utiliser est le nom
de linterface, pas celui de la classe:
@EJB
private ProductLocal productService;
33
Entre EJB
On peut utiliser linjection de dpendance
entre EJB
On utilise aussi @EJB ou @Inject
34
Accs par une
application
Une application texte ou graphique peut se connecter un bean
Le bean doit avoir une #interface distante# (similaire ce qui
se fait pour les RMI) : @Remote
Lapplication doit avoir un nombre assez consquent de
bibliothques du serveur applicatif dans son classPath.
Il existe une application #lanceur# nomme appclient.
On peut utiliser linjection, ou se connecter JNDI
ATTENTION : l'application distante doit avoir connatre
(avoir dans son classpath) l'interface Remote du bean (pas
le bean lui-mme)
35
JNDI
Java Naming and Directory Interface
Fournit un accs uni plusieurs services
dannuaires (DNS, LDAP...)
Annuaire: associe des donnes (objets) avec un
nom
[Link]
Laccs JNDI est fourni par le serveur applicatif
Derrire linjection de dpendance, on a quand
mme JNDI
36
Rcuprer un Bean avec JNDI
import [Link].*;
....
....
Context c= new InitialContext();
String beanName= "java:app/MyApp/BasketBean";
BasketBean b= (BasketBean) [Link](beanName);
Si le bean est Stateful, cre un nouveau bean
Si le bean est stateless, peut rutiliser un bean existant
Si le bean est un singleton, renvoie le singleton.
37
Coordonnes du
serveur JNDI
En local, donnes fournies par appclient
Sinon (pour GlassFish) :
38
Properties properties= new Properties();
[Link]("[Link]",
"[Link]");
[Link]("[Link]",
"[Link]");
[Link]("[Link]",
"[Link]");
[Link]("[Link]", "localhost");
[Link]("[Link]", "3700");
initialContext = new InitialContext(properties);
Noms JNDI des beans (1)
Rcemment standardis
Voir trace de glasssh pour les noms des beans
Pour un bean dans une autre application web, utiliser le nom #global#
java:global/APP/MODULE/BEAN
Pour une application construite partir de plusieurs war, jars: pour accder
des beans dans dautres modules dune mme application utiliser le #nom
dapplication# :
java:app/MODULE/BEAN
Pour des beans dans le mme module, utiliser le nom de module:
java:module/BEAN
APP= nom de lappli; MODULE = nom du module; Bean= nom du bean
(nom de la classe)
39
Noms JNDI des beans
(2)
Si on veut utiliser une interface particulire, on peut
ajouter !INTERFACE aprs le nom de la classe.
ex. :
java:app/MyApp/BasketBean![Link]
Utilise linterface remote
nom complet, y compris package.
Voir [Link]
EJB_FAQ.html#What_is_the_syntax_for_portable_glo
bal_ pour plus de dtails.
40
Accs aux EJB depuis
une Servlet
Stateless beans et singletons peuvent tre
injects dans la Servlet en utilisant
lannotation @EJB
Dans les servlets, il faut rcuprer les
Stateful beans #manuellement# en utilisant
JNDI, puis les stocker en session en
utilisant [Link]()
41
accs un bean session
depuis une servlet
Le bean:
@Stateful
public class Basket {
// Product is serializable !
private List<Product> content=
new ArrayList<Product> ();
public void add(Product p) {
[Link](p);
}
....
42
accs un bean session depuis une
servlet
@WebServlet(name = "AddToBasketServlet", urlPatterns = {"/addToBasket"})
public class AddToBasketServlet extends HttpServlet {
...
private Basket lookupBasketBean(HttpServletRequest request) {
HttpSession session = [Link]();
if ([Link]("basket") == null) {
try {
Context c = new InitialContext();
Basket b = (Basket) [Link]("java:global/SessionInViewTest/Basket");
[Link]("basket", b);
} catch (NamingException ne) {
[Link](getClass().getName()).log([Link], "exception", ne);
throw new RuntimeException(ne);
}
}
return (Basket) [Link]("basket");
}
}
Si le bean nest pas
en session, le crer avec
JNDI.
43
Dploiement
44
Concurrence
cration manuelle de Threads : INTERDITE
Timer
@Startup
@Schedule
@Timeout
Annotation @Asynchronous
45
L'EJB Timer (1)
Pour invoquer priodiquement un EJB, il n'existait avant la version
EJB 3.1 que des solutions fastidieuses, telles que :
Cration d'une servlet qui dmarre avec le serveur d'application,
puis cre des [Link],
et lorsque ces timers arrivent chance invoquent la mthode
d'EJB voulue
Le serveur d'application peut prsent prendre en charge seul
ces mthodes l'excution programme dans le temps.
Le timer est souvent attach un Singleton, charg ds le
dploiement (annot par @Startup)
46
EJB Timer (2)
Pour programmer une excution:
annotation @Schedule place sur une mthode
prend une expression #cron# en paramtre pour dnir son
dclenchement.
par dfaut, hour, minute, second sont 0.
dayOfMonth="4", hour="*" : Toutes les heures le 4me jour de chaque mois.
minute=*/5 : toutes les cinq minutes.
dayOfWeek="1, 3,5": lundi, mercredi et vendredi.
la mthode cible ne doit pas avoir d'arguments.
@Schedule(dayOfMonth="*")
public void sauvegarde() {}
47
EJB Timer
48
@Singleton
@Startup
public class MaDemoTimer implements Serializable{
private int compteur= 0;
private Logger logger = [Link]([Link]().toString());
@PostConstruct
public void myInit() {
[Link]("Init");
}
@Schedule(hour = "*", minute = "*", second = "*/5", persistent = true)
public void sauverDonnees() {
[Link]("On sauve les donnes "+
new Date()+ " compteur "+ (compteur++));
}
}
souvent singleton.
Startup=> cr ds le
dploiement du bean
EJB Timer (3)
@Schedule prend des paramtres
constants.
Lorsque la planication appliquer n'est
connue qu' l'excution, il faut utiliser un
TimerService.
C'est une ressource que l'on charge avec
des expressions temporelles : cron, ou bien
en dates classiques.
49
Timer programm
On cre un timer en utilisant la classe
TimerService (quon injecte)
Dans la classe o on cre le timer, on
cherche une mthode annote par
@Timeout
Cette mthode est lance selon la
frquence indique
50
Timer programm
51
@Singleton
public class ExempleTimerService {
@Resource
TimerService timerService;
private Logger logger= [Link]("TimerProgramme");
private Timer timer; // pour annuler le timer si besoin
// Installe le timer pour un certain intervalle de temps.
public void installerTimer(long intervalle) {
cancelTimer();
timer=
[Link](1000, intervalle,
new TimerConfig());
}
public void cancelTimer() {
if (timer != null) {[Link]();timer= null;}
}
@Timeout
public void sauvegardeProgrammee() {
[Link]("Sauvegarde bis "+ (compteur++) + " a "+ new Date());
}
}
Note propos de
Glasssh
Par dfaut, le timer est #persistante# : il se relancera, mme en
cas darrt du serveur. Il est capable de migrer sur un autre
serveur en cas de Load-balancing
En cas derreur de conguration, les timers persistants laissent des
chiers de sauvegarde incorrects dans Glasssh
Donc, en cas de problme :
soit dsactiver la persistance :
@Schedule(hour = "*", persistent = false)
soit effacer le chier incrimin :
glasssh/domains/domain1/generated/ejb/ejb-timer-service-app
52
Timer programm
Quand on cre l'objet timer en appelant
[Link](10, intervalle, new
TimerCong());
le timer dmarre, et la mthode annote @TimeOut est
lance (priodiquement ou une fois, selon le timer cr)
Il est possible de sauver lobjet timer dans un chier ou une
BD en le srialisant (on sauve la valeur renvoye par
[Link]()).
par dfaut, le timer est persistant quand il est lanc: si on
arrte le serveur JEE, le timer se relancera automatiquement.
53
54
@Named
@RequestScoped
public class StartTimerBean {
@Min(100)
private long intervalle=2000;
@EJB
private ExempleTimerService timerService;
public void demarrerTimer() {
[Link](intervalle);
}
public void arreterTimer() {
[Link]();
}
public long getIntervalle() {
return intervalle;
}
public void setIntervalle(long intervalle) {
[Link] = intervalle;
}
}
<h:form>
<p>Intervalle : <h:inputText value="#{[Link]}"/></p>
<h:commandButton value="Dmarrer" action="#{[Link]()}"/>
<h:commandButton value="Arrter" action="#{[Link]()}"/>
</h:form>
Exemple de Managed Bean
pour le timer prcdent
JSF
Gestion de transactions
rappels
TransactionManagement
Annotations disponibles pour
@TransactionAttribute
REQUIRED, REQUIRES_NEW,
MANDATORY, SUPPORT,
NOT_SUPPORTED, NEVER
55
Le problme des
transactions
transfert entre deux comptes en banque:
[Link](1000)
[Link](1000)
En BD:
update compte set solde= solde -1000 where id= 1
update compte set solde= solde + 1000 where id= 2
Que se passe-t-il si lopration est interrompue entre les deux
tapes ????
=> les deux oprations doivent, ou toutes les deux russir, ou
toutes les deux chouer
56
Transactions
Dnition
opration informatique cohrente compose de plusieurs tches
unitaires
implantent les proprits ACID:
atomique
cohrente
isole (plus ou moins)
durable
mcanisme
de base dans SQL : commit() rollback() start transaction()
57
Transaction : le
problme
opration technique au niveau SQL (accs
aux donnes)
au niveau logique, la dlimitation des
transaction correspond plutt la logique
applicative (suite dopration cohrente) !!
les EJB permettent de replacer les
transactions au #bon# niveau
58
Transactions et EJB
Java Transaction API
Par dfaut, toutes les mthodes qui font partie
de linterface dune EJB sont transactionnelles
Quand linterface utilisateur appelle une
mthode EJB, on dmarre une transaction; la
n de la mthode correspond au commit().
Sinterface naturellement avec JPA
Pas besoin douvrir ou fermer une transaction,
cest fait automatiquement par le conteneur
59
Annotation
@TransactionAttribute
@TransactionAttribute(.) devant une
mthode dun EJB: modie son
comportement transactionnel
gnralement, la question est la suivante:
une mthode f() transactionnelle
appelle une mthode g(), elle aussi
transactionnelle
que va-t-il se passer ? g() va-t-elle
sexcuter dans la transaction
dmarre par f() ?
quel suspense !
60
Valeurs possibles pour
@TransactionAttribute
[Link]: sil y a une transaction en cours,
excute la mthode dans cette transaction. Sinon, cre une nouvelle
transaction
TransactionAttributeType.REQUIRES_NEW: cre une nouvelle
transaction pour cet appel
[Link]: exception sil ny a pas dj
une transaction en cours
[Link]: ne cre pas de transaction, mais
sexcute dans le cadre de celle qui est en cours si elle existe.
[Link]: erreur si dans transaction
TransactionAttributeType.NOT_SUPPORTED: sexcute en dehors du
contexte transactionnel en cours.
61
Exemple
62
@Stateful
public class PanierService {
@PersistenceContext
EntityManager em;
private List<ProduitDTO> produits = new ArrayList<ProduitDTO>();
@TransactionAttribute([Link])
public void addProduit(ProduitDTO dto) {
[Link](dto);
}
// l'annotation ci-dessous est inutile (valeur par dfaut)
@TransactionAttribute([Link])
public void sauverCommande() {
// ... construit la commande partir des produit
// ... appelle [Link]()
Commande c = [Link](produits);
[Link](c);
}
}
Exemple (suite)
addProduit : [Link]
ne touche pas la base de donnes, et peut donc
ne pas tre transactionnel
si on lappelle dans le cadre dune transaction,
utilise celle-ci
sauverCommande:
[Link]
va forcment sexcuter dans le cadre dune
transaction.
63
Transactions
Concrtement, les transactions agissent sur des connections fournies
par les Datasources que le serveur dapplication a sous sa garde.
Agir sur les connections pour dbuter une transaction nest pas
ncessaire, le serveur dapplication sen charge.
Le commit advient de lui-mme lorsque le service qui a dbut une
transaction s est excut intgralement et a su composer avec
dautres services
Sans avoir reu de notication dabandon.
Sans stre retrouv dans une situation dannulation.
De sorte que dans un service, on ne soccupe que de notier les
situations de rollback.
64
Exceptions Systmes:
sur initiative du serveur dapplication et
dans des situations svres .
Les exceptions issues de RuntimeException,
RemoteException, et EJBException.
Ce sont des exceptions systme quil nest
pas attendu que nous levions nous-mmes
65
Exceptions applicatives
Les exceptions non systme
peuvent tre annotes par
@ApplicationException(rollback=true)
et alors elles provoqueront lannulation de la
transaction en cours si elles sont leves par le
service.
Attention: prendre cette dcision pour la classe
dexception elle-mme est brutal. Cest peut-tre
une dcision laisser au service ?
66
Notication dabandon
En ajoutant lEJB session la variable membre et la
mthode
@Stateless public class MonBean {
@Resource
private SessionContext sessionContext;
.
Une mthode de service de ce bean pourra annuler une
transaction en cours par un:
[Link](true);
67
Mcanismes sous-
jacents
Quand on appelle une mthode dEJB, comment le systme peut-il dcider de
commencer/terminer une transaction ?
On utilise le pattern Dcorateur avec un Proxy
On gnre une classe de mme interface que le Bean, qui appelle le bean,
mais #enrobe# les appels de mthodes dans le code ncessaire au
traitement de la transaction
Pour a
classe Proxy : permet dimplanter par programme java une interface
quelconque (cest du java standard). Fonctionne seulement sil y a une
interface Local ou Remote explicite.
Hritage et synthse de code : on cre le bytecode dune nouvelle classe
(bibliothque ASM), qui tend la classe dorigine (do linterdiction de
nal).
68
Pour rsumer... un exemple
de C(RUD) en JSF+EJB (+JPA)
Base de donnes de Dvd
Contrle : un managed bean
CreateDvdBean
Couche mtier : un Stateless Bean
DvdService
Accs aux donnes : JPA (et le bean
DvdService)
69
70
on ajoute JSF
Dvds la suite
Noter le dcoupage
en packages
71
On cre la base de donnes
Ajout dune Persistence
Unit (pour JPA)
72
Cration du modle
(rduit une classe ici)
73
LEJB daccs aux Dvd
(on pourrait faire deux EJB: un de bas
niveau (DAO), l'autre orient faade pour
l'interface graphique
74
Le managed bean pour
la cration et sa JSF
75
Note sur la valeur de
retour de l'action
return
"montrerDvd?faces-redirect=true&id=" +id;
faces-redirect => redirection (on charge
une nouvelle page)
id= : cette page va afcher le DVD cr
76
Managed Bean de
visualisation
77
Injection de paramtres
GET
@ManagedProperty(value="#{[Link]}")
Long id;
injecte la valeur de [Link] dans id
ne fonctionne que sur un @ManagedBean (pas @Named)
[Link]().getExternalContext()
permet davoir accs aux paramtres comme avec une servlet
Sinon, on peut injecter les valeurs partir de la JSF :
78
<f:metadata>
<f:viewParam name="id" value="#{[Link]}"/>
</f:metadata>