Академический Документы
Профессиональный Документы
Культура Документы
La technologie des EJB (pour Enterprise Java Bean) ont t introduite en 1998 pour
offrir aux programmeurs un outil qui facilite la conception et le dploiement d'une
couche mtier. La version 1.0 trs simple est largement revue en 2002 avec la
version 2.0. Cette dernire introduit de nombreuses nouveauts avec la possibilit
de travailler directement (via des EJB particuliers) sur des donnes stockes dans
une base de donnes relationnelle.
Malheureusement, ces nouvelles fonctions s'accompagnent d'une lourdeur trs
importante de mise en oeuvre. Les composants EJB 2.0 doivent implmenter de
multiples interfaces et leur dploiement impose de fournir au serveur d'applications
des fichiers de description fastidieux rdigs en XML.
En 2006, la version EJB 3.0 a pour objectif de simplifier l'utilisation et le dploiement
de cette technologie en se basant sur quatre principes :
Les fichiers XML de dploiement sont remplacs par des annotations places
directement dans le code des EJB. Cette nouvelle possibilit est directement lie
aux apports de la version 1.5 de JavaSE (dfinition et exploitation des
annotations).
Pour assurer les interactions entre les EJB et le serveur d'application dans lequel
ils sont installs, le programmeur n'est plus oblig d'implmenter de nombreuses
interfaces (au sens java du terme). Ici encore, les annotations vont simplifier les
choses.
Tous les paramtres de dploiement sont dots de valeurs par dfaut qui
suffissent dans la plupart des cas.
Les EJB Session fournissent un service aux clients. Ils sont accessibles via le
rseau (en passant par le protocole RMI) ou localement dans la JVM du client.
Les EJB sessions sont les points d'entre de la couche mtier.
Les EJB Entity reprsentent les donnes qui proviennent ou qui alimentent la
base de donnes. Ils ne sont gnralement pas accessibles directement au
Les EJB MessageDriven reprsentent une file de messages posts par le client
et traits par le serveur (ou vice-versa). Nous ne les tudierons pas dans ce TP.
Mise en place
Pour travailler avec les EJB en version 3.0, nous avons besoin de mettre en place
des outils supplmentaires :
IDE Eclipse JEE
( sauter si dj fait)
Commencez par charger la version JEE de l'IDE Eclipse. Nous avons besoin de
cette version pour utiliser les nombreux plugins qu'elle intgre.
Serveur d'applications JBoss
Continuez en rcuprant le serveur d'applications JBoss 5.x.x qui est
indispensable pour dployer les EJB. N'oubliez pas de dcompresser l'archive
rcupre.
Modifiez
le
fichier eclipse.ini en
XX:MaxPermSize=512m .
lui
ajoutant
la
ligne
Nous allons commencer par construire un petit EJB Session Stateless dont le but est
de passer une chane de caractres en majuscule. Nous commencons par dfinir
l'interface :
packagemonpkg.services;
importjavax.ejb.Remote;
@Remote
publicinterfaceToUpper{
StringtoUpper(Stringdata);
Dans cette interface, l'annotation javax.ejb.Remote est utilise pour prciser que
l'EJB sera accessible via le protocole RMI. Si l'EJB est implant dans la mme JVM,
nous aurions du utiliser l'annotation javax.ejb.Local. Un EJB peut tre la fois
distant et local. Il faut dans ce cas deux interfaces.
puis nous ralisons une implantation :
packagemonpkg.impl;
importjavax.ejb.Stateless;
importmonpkg.services.ToUpper;
@Stateless(name="toUpper",description="Unpremieressai")
publicclassToUpperImplimplementsToUpper{
publicStringtoUpper(Stringqui){
returnqui.toUpperCase();
}
}
Nous allons maintenant crer le client sous la forme d'un nouveau projet. Mettez en
place une dpendance entre le projet client et le projet EJB et copiez dans votre
projet client la librairie client/jbossallclient.jar qui se trouve dans le
rpertoire de JBoss.
packagemonclient;
importjavax.naming.Context;
importjavax.naming.InitialContext;
importjavax.naming.NamingException;
importmonpkg.services.ToUpper;
importstaticorg.junit.Assert.*;
importorg.junit.Before;
importorg.junit.Test;
publicclassTestMonEJB{
finalContextinitial;
publicTestMonEJB()throwsNamingException{
initial=newInitialContext();
}
@Test
publicvoidtestToUpper()throwsNamingException{
Objecto=initial.lookup("toUpper/remote");
assertTrue(oinstanceofToUpper);
ToUpperp=(ToUpper)o;
assertEquals("PREMIER",p.toUpper("premier"));
}
}
Pour viter de prciser dans le code les paramtres de connexion JNDI, vous
pouvez crer un fichier de ressources jndi.properties accessible via le
CLASSPATH :
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost:1099
Le nom que nous utilisons pour reprer un EJB est de la forme nom/remote si l'EJB
est accessible via RMI ou nom/local si l'EJB est disponible dans la mme JVM. Si
vos EJB sont packags dans une application d'entreprise (une EAR : Enterprise
Application
aRchive),
alors
le
chemin
devient nomdeEAR/nomde
EJB/remote ou nomdeEAR/nomdeEJB/local. Une archive EAR regroupe des EJB
(packags dans un .jar) et une application WEB (packag dans un .war). Vous
pouvez, dans Eclipse, crer une application d'entreprise pour regrouper un
ensemble d'EJB et une application WEB.
Testez votre application.
Cycle de vie d'un EJB
publicvoidfin(){
System.out.println("Stopping"+this);
}
Ajoutez ces callbacks votre EJB et testez leur fonctionnement. Vous pouvez
remarquer que ces annotations ne sont pas directement lies la technologie des
EJB3.
Un EJB Session Stateful
Puis l'implantation :
packagemonpkg.impl;
importjavax.annotation.PostConstruct;
@Stateful(name="connectedUser")
publicclassConnectedUserBeanimplementsConnectedUser{
//implantationdesmthodes
...
}
Nous avons souvent besoin, dans une application, d'utiliser un premier EJB dans
l'implantation d'un second. Pour ce faire, nous devons faire un lien entre ces deux
EJB. Nous pouvons toujours le faire en considrant l'EJB utilisateur comme un client
et donc passer par un lookup JNDI. Pour simplifier ces problmes de liaison, la
norme
EJB3
introduit
la
notion
d'injection
de
dpendances
via
l'annotation javax.ejb.EJB :
@EJB
privateToUppertoUpper;
Ces mthodes sont places dans la classe surveiller ou dans une classe annexe
(ou les deux). Dans le cas d'une classe d'interception, vous devez donner son nom
avec l'annotation javax.interceptor.Interceptors (il peut y en avoir plusieurs) :
packagemonpkg.impl;
importjavax.interceptor.AroundInvoke;
importjavax.interceptor.InvocationContext;
publicclassInterceptor{
@AroundInvoke
publicObjectinterceptor(InvocationContextcontext)throwsException
{
...
}
}
Pour finir, une mthode pour dconnecter la surveillance effectue par une autre
classe en utilisant l'annotation @ExcludeClassInterceptors.
Mise en oeuvre : Crez un intercepteur qui va calculer la temps pris par les appels
aux mthodes mtiers (utilisez System.currentTimeMillis()).
JPA et EJB
Pour la mise en pratique de JPA, nous allons utiliser l'environnement EJB 3 bas sur
JBoss que nous avons mis en place lors du TP prcdent. Nous allons lui ajouter
quelques lments :
Paramtrage JPA
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistenceunitname="myPersistenceUnit"
transactiontype="JTA">
<jtadatasource>java:/DefaultDS</jtadatasource>
<properties>
<propertyname="hibernate.show_sql"value="true"/>
<propertyname="hibernate.format_sql"value="false"/>
<propertyname="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<propertyname="hibernate.hbm2ddl.auto"value="createdrop"/>
</properties>
</persistenceunit>
</persistence>
@Entity
publicclassPersonimplementsSerializable{
privatestaticfinallongserialVersionUID=1L;
@Id()
@GeneratedValue(strategy=GenerationType.AUTO)
privatelongid;
@Column(name="name",length=200,nullable=false)
privateStringname;
publicPerson(){
super();
}
publicPerson(Stringname){
super();
this.name=name;
}
@Override
publicStringtoString(){
return"Person(id="+id+","+name+")";
}
publiclonggetId(){
returnid;
}
publicvoidsetId(longid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
Un EJB DAO
importjavax.annotation.PostConstruct;
importjavax.ejb.Remote;
importjavax.ejb.Stateless;
importjavax.persistence.EntityManager;
importjavax.persistence.PersistenceContext;
importjavax.persistence.Query;
importmonpkg.entities.Person;
importmonpkg.services.Dao;
@Remote(value=Dao.class)
@Stateless(name="dao",description="MyDaoEJB")
publicclassDaoImplimplementsDao{
@PersistenceContext(unitName="myPersistenceUnit")
EntityManagerem;
@PostConstruct
publicvoidinit(){
System.err.println("Daoinit:"+this);
System.err.println("em="+em);
}
@Override
publicPersonaddPerson(Personp){
em.persist(p);
return(p);
}
@Override
publicPersonfindPerson(longid){
returnem.find(Person.class,id);
}
@SuppressWarnings("unchecked")
@Override
publicList<Person>findAllPersons(){
Queryq=em.createQuery("FROMPerson");
returnq.getResultList();
}
}
Explications :
via
le
mcanisme
d'injection
(annotation javax.persistence.PersistenceContext), l'EJB rcupre une instance
de l'interfacejavax.persistence.EntityManager. Celle-ci va permettre les
oprations CRUD de persistance sur les entits (Create, Read, Update et Delete).
Cette instance est prpare par le serveur d'application partir du
fichier persistence.xml.
Vrification : Aprs dploiement de cet EJB, vous devez trouver dans les traces de
JBOSS la configuration de la source de donnes.
Dans le projet client enrichissez la classe de test pour tester l'EJB Dao.
Vrification : La base de donnes embarque Hypersonic que nous utilisons dans
cet exemple maintient un fichier de trace qui est particulirement intressant. Il liste
notamment les ordres de cration des tables ainsi que les oprations sur les lignes.
Vous pouvez le trouver cet emplacement :
<JBOSS_DIR>/server/default/data/hypersonic/localDB.log