Intergiciel et Construction d’Applications Repartiesc©2007, Cedric JOFFROY, Sebastien MOSSER, Michel RIVEILL
(version du 14 novembre 2008 - 11:13)
Chapitre9
Premiers pas J2EE
L’objectif de cette annexe est de permettre a chacun de se familiariser un peu avec uneplate-forme respectant les specifications J2EE (Java 2 Enterprise Edition). Pour cela nousallons developper une petite application permettant a chacun de gere ses cartes de visite(ajout, suppression et consultation) et de les rendre accessibles aux autres utilisateurs (uni-quement consultation). Pour atteindre ce but, l’application se compose de deux parties :le service d’annuaire qui doit pouvoir etre utilisee a distance et differentes applicationsclientes de type client leger ou client lourd graphique ou en ligne de commande. Pour desraisons de simplicite nous ne nous interesserons pas aux problemes lies a l’authentificationdes differentes classes d’utilisateurs.
Pour mettre en œuvrecette application nous allons utiliser :– un container managed entity bean pour gerer la persistance des cartes de visites,– un statefull session bean pour l’ajout et la suppression des cartes de visites,– un stateless session bean pour la consultation des cartes stockees,– un client lourd pour administrer l’application et permettre l’ajout et la suppression
de cartes de visites– un client leger de consultation en utilisant une (servlet).Une version html de ce texte est disponible a l’adresse http://rangiroa.polytech.
unice.fr/riveill/enseignement/tp/j2ee.html. Elle contiendra les evolutions futuresdu sujet.
9.1 Les outils a utiliser
Parmis toutes les plates-formes J2EE disponible, nous avons fait le choix d’utiliserJ2EE Jonas developpe par des equipes francaises dans le cadre du consortium Object-Web qui peut etre recupere sur le site web du consortium1.
1www.objectweb.com
2 CHAPITRE 9. PREMIERS PAS J2EE
9.1.1 Installation de Jonas
L’installation proposee ici concerne la version 4.7.7 et s’adresse aux utilisation d’unemachine de type Linux ou Mac Os X. On laisse au lecteur attentif la modification decette procedure pour installer Jonas sur une plateforme Windows ou pour installer uneautre version de Jonas.
Nous allons installer Jonas dans le repertoire /opt/.
LINUX:~> tar xvfz jonas4 .7.7- tomcat5 .5.15. tgz
LINUX:~> sudo mv JONAS_4_7_7 /opt/.
Pour fonctionner correctement, Jonas utiliser trois variables d’environnement quidoivent etre correctement positionnee :
– JONAS ROOT : chemin d’acces au repertoire de Jonas,– PATH : chemin d’acces aux binaires de Jonas,– CLASSPATH : doit contenir les deux archives necessaire au bon deroulement de ces
ateliers : ejb-2 1-api.jar et servlet-2 4.jar.– selon les versions Jonas, il peut y avoir d’autres variables d’environneent : SPS=’ :’
et JONAS BASE=JONAS ROOT
9.1.2 Installation d’ANT
L’installation Ant est recommandee si l’on veut tester les exemples fournis avec Jonaset qui se trouve dans le repertoire /opt/JONAS 4 7 7/examples/src/. Ant est par exempledisponible a l’url http://ant.apache.org/bindownload.cgi et s’installe tres aisement.
LINUX:~> unzip apache -ant -1.6.5 - bin.zip
LINUX:~> sudo mv apache -ant -1.6.5 /opt/.
Comme pour Jonas, il est necessaire que la variable d’environnement ANT HOME
contienne le repertoire d’installation de Ant.
9.1.3 Mise a jour des variables d’environnement
Pour etre certain de ne pas oublier une mise a jour lors d’une utilisation ulterieure,nous vous invitons a regrouper celles-ci dans le fichier environnement.sh.
#!/bin/sh
# Mise a jour des variables d’environnemnts pour Jonas
JONAS_ROOT =/opt/JONAS_4_7_7
echo "JONAS_ROOT set to $JONAS_ROOT"
PATH=$JONAS_ROOT/bin/unix:$PATH
echo "PATH set to $PATH"
CLASSPATH=$CLASSPATH:$JONAS_ROOT/lib/commons/j2ee/ejb -2_1 -api.jar
CLASSPATH=$CLASSPATH:$JONAS_ROOT/lib/commons/j2ee/servlet -2_4.jar
echo "CLASSPATH set to $CLASSPATH"
# Mise a jour des variables d’environnement pour Ant
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 3
ANT_HOME =/opt/apache -ant -1.6.5
echo "ANT_HOME set to $ANT_HOME"
export JONAS_ROOT ANT_HOME PATH CLASSPATH
Listing 9.1 – Fichier environment.sh
Il ne reste plus qu’a executer ce shell a l’aide de la commande source pour s’affranchirdu dialecte utilise (zsh, tcsh ou bash) :
LINUX:~> source environnement.sh
9.1.4 Pour tester l’installation
Avant toutes autres manipulation, un test de l’installation s’impose. Suivez attentive-ment les differents messages d’erreurs.
LINUX:~> jonas check
LINUX:~> jonas start
1. Le check verifie l’etat de l’installation, et peut renvoyer des warnings, rien de biengrave.
2. Le start lance le serveur Jonas. Lorsque le lancement est termine, il rend la mainen indiquant qu’il a demarre.
9.2 Gestion de la persistance - entity bean
Les objets persistants sont les cartes de visites. Nous allons donc les implementer sousla forme d’entity bean dont la persistance est directement geree par le container. Avantd’ecrire l’entity bean, construisons la base de donnees.
9.2.1 La base de donnees
Pour conserver les cartes de visite nous allons utiliser une base de donnee qui contiendraune seule table CARTEDEVISITE structuree de la maniere suivante :
– un id permettant d’identifier de maniere unique chacune des cartes de visite,– un nom,– un prenom,– une adresse mail,– un numero de telephone.Tous ces champs sont de type varchar et sont non nuls, a l’exception du champ id qui
est de type identity (shortcut pour un integer primary key dans le SGBD utilise).Nous utiliserons le micro–moteur de base de donnees HSQLDB, livre avec Jonas. Les
informations de connexion sont les suivantes
urlid localhost -dbjonas
url jdbc:hsqldb:hsql :// localhost :9001/ db_jonas
username jonas
4 CHAPITRE 9. PREMIERS PAS J2EE
password jonas
Listing 9.2 – Fichier sql-rc.conf
Description du schema relationnel
1 drop table if exists CARTEDEVISITE;
create table CARTEDEVISITE (
ID IDENTITY ,
NOM varchar (255) not null ,
PRENOM varchar (255) not null ,
6 EMAIL varchar (255) not null ,
PHONE varchar (255) not null
);
Listing 9.3 – Fichier database.sql
Chargement de la relation dans le moteur
LINUX:~> java -jar $JONAS_ROOT/lib/commons/jonas/hsqldb.jar \
2 --autoCommit --continueOnErr \
--rcfile ./sql -rc.conf localhost -dbjonas database.sql
Script de chargement automatique
Pour simplifier l’initialisation de la base de donnees, on met en place un script quipermet d’executer cette ligne de commande :
#!/bin/sh
2 echo "Database initialization"
java -jar $JONAS_ROOT/lib/commons/jonas/hsqldb.jar \
--autoCommit --continueOnErr \
--rcfile ./sql -rc.conf localhost -dbjonas database.sql
Listing 9.4 – Fichier initDatabase.sh
Pour executer ce script (apres l’avoir rendu executable . . .) :
LINUX:~> ./ initDatabase.sh
On dispose maintenant d’une relation vide dans le moteur de base de donnees HSQL.Si vous n’etes pas convaincu, lancez le client graphique Hsql Manager sans toucher aumot de passe :
LINUX:~> java -cp $JONAS_ROOT/lib/commons/jonas/hsqldb.jar org.hsqldb.util.DatabaseManager
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 5
9.2.2 Ecriture du container managed entity bean
Le code d’un entity bean est reparti dans plusieurs classes Java et descripteurs :– Remote Interface : l’interface qui definit les differentes methodes du Bean qui seront
accessibles pour les clients,– Home Interface : l’interface qui est visible par le client pour creer, retrouver puis
manipuler des instances du Bean,– la classe d’implementation du Bean,– deux descripteurs de deploiement indiquant entre autre le mapping objet ⇔
relationnel a utiliser pour garantir la persistance des objets, et les requetes per-mettant de les retrouver.
Interface remote : on decrit dans cette interface les fonctions permettant de manipulerles cartes de visite.
package carte_cmp;
import javax.ejb.EJBObject;
4 import java.rmi.RemoteException;
public interface CarteDeVisiteCMP extends EJBObject {
public Integer getId () throws RemoteException;
9 public String getNom () throws RemoteException;
public String getPrenom () throws RemoteException;
public String getEmail () throws RemoteException;
public String getPhone () throws RemoteException;
14 // Pas de setId , le SGBD la genere.
public void setPrenom(String prenom) throws RemoteException;
public void setNom(String nom) throws RemoteException;
public void setEmail(String email) throws RemoteException;
public void setPhone(String phone) throws RemoteException;
19 }
Listing 9.5 – Fichier CarteDeVisiteCMP.java
Interface Home : cette interface, accessible par les clients de l’application, permetde retouver les instances de cartes de visites, d’en creer, . . .. Les instances qu’elle renvoiesont du type de l’interface precedente, ce qui masque aux clients l’implementation reelledu Bean.
1 package carte_cmp;
import java.rmi.RemoteException;
import javax.ejb .*;
import java.util .*;
6
public interface CarteDeVisiteCMPHome extends EJBHome {
public CarteDeVisiteCMP
create(String nom , String prenom , String email , String phone)
6 CHAPITRE 9. PREMIERS PAS J2EE
11 throws RemoteException , CreateException;
public CarteDeVisiteCMP findByPrimaryKey(Integer id)
throws RemoteException , FinderException;
16 public Collection findByNom(String nom)
throws RemoteException , FinderException;
public Collection findByPrefix(String prefix)
throws RemoteException , FinderException;
21 }
Listing 9.6 – Fichier CarteDeVisiteCMPHome.java
Implementation du bean Le choix d’utiliser un CMP entity bean simplifie grandementla mise en oeuvre puis que la plupart des methodes n’ont pas besoin d’etre implementeeset seront generees a partir des fichiers de deploiement.
package carte_cmp;
import java.sql .*;
4 import javax.sql .*;
import java.util .*;
import javax.ejb .*;
import javax.naming .*;
9 public abstract class CarteDeVisiteCMPBean implements EntityBean {
/** Abstract ==> gere par le conteneur **/
public abstract Integer getId ();
public abstract void setId(Integer id);
14 public abstract String getNom ();
public abstract void setNom(String nom);
public abstract String getPrenom ();
public abstract void setPrenom(String prenom );
public abstract String getEmail ();
19 public abstract void setEmail(String email );
public abstract String getPhone ();
public abstract void setPhone(String phone );
// Cree le composant et le sauvegarde dans la base de donnees avec
24 // un insert
public Integer
ejbCreate(String nom , String prenom , String email , String phone)
throws CreateException {
// renseigne les propriete du composant
29 setNom(nom);
setPrenom(prenom );
setEmail(email );
setPhone(phone );
return null;
34 }
public void
ejbPostCreate(String nom , String prenom ,
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 7
String email , String phone) {
39 // Dans le cas de tables de liaisons , on instancierait les
// liaisons ici.
}
// les methodes suivantes n’ont pas besoin d etre implemante dans
44 // le cadre d un CMP entity bean
public void ejbRemove () throws RemoveException { }
public void setEntityContext(EntityContext context) {
this.context = context;
}
49 public void unsetEntityContext () { this.context = null; }
public void ejbActivate () { }
public void ejbPassivate () { }
public void ejbLoad () { }
54 public void ejbStore () { }
}
Listing 9.7 – Fichier CarteDeVisiteCMPBean.java
La cle primaire utilisee sera de type auto incrementee (par la base de donnee). Nousn’utiliserons donc jamais la methode setId().
TODO pourquoi alors mettre cette methode ? on a besoin de l’operation ’setId’ car legenerateur de code rale si elle n’y est pas. Reste a le reverifier.
Descripteur de deploiement J2EE : ce fichier est commun a tous les serveur d’ap-plications J2ee et permet de preciser le mapping a utiliser entre l’entity bean et la basede donnee.
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<ejb -jar >
<description >Descripteur de deploiement pour l EJB carte de visite
</description >
5 <display -name >EJB CarteDeVisite </display -name >
<enterprise -beans >
<entity >
<description >EJB CarteDeVisite ( CMP )</description >
<ejb -name >CarteDeVisiteCMP </ejb -name >
10 <home >carte_cmp.CarteDeVisiteCMPHome </home >
<remote >carte_cmp.CarteDeVisiteCMP </remote >
<ejb -class >carte_cmp.CarteDeVisiteCMPBean </ejb -class >
<persistence -type >Container </ persistence -type >
<prim -key -class >java.lang.Integer </prim -key -class >
15 <reentrant >False </reentrant >
<abstract -schema -name >cartedevisite </abstract -schema -name >
<cmp -field >
<field -name >id </field -name >
</cmp -field >
20 <cmp -field >
<field -name >nom </field -name >
</cmp -field >
<cmp -field >
<field -name >prenom </field -name >
25 </cmp -field >
8 CHAPITRE 9. PREMIERS PAS J2EE
<cmp -field >
<field -name >email </field -name >
</cmp -field >
<cmp -field >
30 <field -name >phone </field -name >
</cmp -field >
<primkey -field >id </primkey -field >
<query >
<query -method >
35 <method -name >findByNom </method -name >
<method -params >
<method -param >java.lang.String </method -param >
</method -params >
</query -method >
40 <ejb -ql >SELECT OBJECT(o) FROM cartedevisite o
WHERE o.nom = ?1
</ejb -ql >
</query >
<query >
45 <query -method >
<method -name >findByPrefix </method -name >
<method -params >
<method -param >java.lang.String </method -param >
</method -params >
50 </query -method >
<ejb -ql >SELECT OBJECT(o) FROM cartedevisite o
WHERE LOCATE (?1,o.nom) > 0
</ejb -ql >
</query >
55 <query >
<query -method >
<method -name >findByPrimaryKey </method -name >
<method -params >
<method -param >java.lang.Integer </method -param >
60 </method -params >
</query -method >
<ejb -ql >SELECT OBJECT(o) FROM cartedevisite o
WHERE o.id = ?1
</ejb -ql >
65 </query >
</entity >
</enterprise -beans >
<assembly -descriptor >
70 <container -transaction >
<method >
<ejb -name >CarteDeVisiteCMP </ejb -name >
<method -name >*</method -name >
</method >
75 <trans -attribute >Required </trans -attribute >
</container -transaction >
</assembly -descriptor >
</ejb -jar >
Listing 9.8 – Fichier ejb-jar.xml
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 9
Descripteur Jonas : En complement du descripteur J2EE, chaque fournisseur de plate-forme propose son propre descripteur afin de completer la description initiale. Dans Jonas,il permet de decrire l’utilisation des ressources tierces comme par exemple l’acces a la basede donnees.
1 <?xml version ="1.0" encoding ="ISO -8859 -1"? >
<jonas -ejb -jar >
<jonas -entity >
<ejb -name >CarteDeVisiteCMP </ejb -name >
<jndi -name >MyCarteDeVisiteCMP </jndi -name >
6 <jdbc -mapping >
<jndi -name >jdbc_1 </jndi -name >
<jdbc -table -name >CARTEDEVISITE </jdbc -table -name >
<automatic -pk>true </automatic -pk>
<cmp -field -jdbc -mapping >
11 <field -name >id </field -name >
<jdbc -field -name >ID </jdbc -field -name >
</cmp -field -jdbc -mapping >
<cmp -field -jdbc -mapping >
<field -name >nom </field -name >
16 <jdbc -field -name >NOM </jdbc -field -name >
</cmp -field -jdbc -mapping >
<cmp -field -jdbc -mapping >
<field -name >prenom </field -name >
<jdbc -field -name >PRENOM </jdbc -field -name >
21 </cmp -field -jdbc -mapping >
<cmp -field -jdbc -mapping >
<field -name >phone </field -name >
<jdbc -field -name >PHONE </jdbc -field -name >
</cmp -field -jdbc -mapping >
26 <cmp -field -jdbc -mapping >
<field -name >email </field -name >
<jdbc -field -name >EMAIL </jdbc -field -name >
</cmp -field -jdbc -mapping >
</jdbc -mapping >
31 </jonas -entity >
</jonas -ejb -jar >
Listing 9.9 – Fichier jonas-ejb-jar.xml
9.2.3 Compilation et deploiement de l’entity bean
Nous avons maintenant tout ce qui est necessaire pour compiler et deployer l’entitybean. A l’issue de cette premiere etape nous avons l’arborescence suivante :
+--> bin/
+--> META -INF/
3 +--> ejb -jar.xml
+--> jonas -ejb -jar.xml
+--> src/
+--> CarteDeVisiteCMPBean.java
+--> CarteDeVisiteCMPHome.java
8 +--> CarteDeVisiteCMP.java
+--> Test.java
10 CHAPITRE 9. PREMIERS PAS J2EE
Nous conserverons cette arborescence pour les autres beans que nous creerons. Lerepertoire bean contiendra toujours le code compile des fichiers java et le repertoirebin/META-INF, les descripteurs.
Pour pouvoir etre execute par Jonas, un bean a besoin d’etre contenu dans une archivequi facilite son deploiement. Pour cela, on genere le bytecode, puis on ecrit les descripteurde deploiement et on archive l’ensemble dans un fichier jar.
1 LINUX :~/ CarteDeVisite > javac -d bin src/*. java
LINUX :~/ CarteDeVisite > cp *.xml bin/META -INF/.
LINUX :~/ CarteDeVisite > cd bin
LINUX :~/ CarteDeVisite/bin > jar cf ../ CarteDeVisiteCMP.jar
LINUX :~/ CarteDeVisite/bin > cd ..
6 LINUX :~/ CarteDeVisite >
Deployer un bean dans Jonas se fait en deux etapes :– deposer l’archive dans le repertoire ejbjars de Jonas,– utiliser l’outils d’administration de Jonas pour publier le bean.
LINUX :~/ CarteDeVisite > cp CarteDeVisiteCMP.jar $JONAS_ROOT/ejbjars /.
LINUX :~/ CarteDeVisite > cd $JONAS_ROOT/ejbjars
LINUX:/opt/JONAS_4_7_7/ejbjars > jonas admin -a CarteDeVisiteCMP.jar
4 LINUX:/opt/JONAS_4_7_7/ejbjars > cd -
LINUX :~/ CarteDeVisite >
9.2.4 Client d’un entity bean
Ce client, non essentiel a l’application, permet de valider le code de l’entity bean. Nousfaisons le choix d’implementer un client simple qui cree deux entity bean, effectue unerecherche par nom et une recherche a l’aide d’un prefixe.
package carte_cmp;
import java.util.Properties;
import javax.naming.InitialContext;
5 import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
import java.util.Collection;
import java.util.Iterator;
10
public class Test {
public static void main(String args []) {
15 try {
// Recherche de l’interface home de l’EJB
Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyCarteDeVisiteCMP");
20
// Reference a l’interface locale de l’EJB
CarteDeVisiteCMPHome home = (CarteDeVisiteCMPHome)
PortableRemoteObject.narrow(objref , CarteDeVisiteCMPHome.class );
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 11
25 // Creation deux carte de visite dans la base de donnees
CarteDeVisiteCMP toto =
home.create("TOTO", "toto", "toto@toto", "0123456");
CarteDeVisiteCMP titi =
home.create("TITI", "titi", "titi@titi", "9876443");
30
// Objet de type client pour faire nos tests
CarteDeVisiteCMP test;
35 // Recherche par le nom de la personne
System.out.println("Liste des clients qui ont pour nom TOTO :");
Collection cl = home.findByNom("TOTO");
Iterator iLast = cl.iterator ();
while (iLast.hasNext ()) {
40 test = iLast.next ();
System.out.println("->" + test.getPrenom ());
}
// Recherche par le prefixe de la personne
45 System.out.println("Liste des clients qui ont pour prefixe T :");
Collection c2 = home.findByPrefix("T");
Iterator iLast1 = c2.iterator ();
while (iLast1.hasNext ()) {
test = iLast1.next ();
50 System.out.println("->" + test.getPrenom ());
}
} catch (Exception e) {
System.err.println("Erreur : " + e);
55 System.exit (2);
}
}
}
Listing 9.10 – Fichier Test.java
9.2.5 Compilation et execution du client
Apres avoir compile le client, nous utilisons pour l’executer, l’utilitaire jclient quipermet l’execution du client dans le contexte de Jonas et d’avoir ainsi l’acces a l’annuairede referencement JNDI dans lequel sont enregistres tous les beans publies dans Jonas.
Nous considererons que le client possede dans son CLASSPATH le jar du bean, pour pou-voir utiliser le proxy (classe RemoteStub generee par genic) permettant d’acceder au beancomme un objet distant. Pour ’travailler proprement’, il serait beaucoup plus judicieux dedonner au client soit le proxy, soit une maniere de le generer.
1 LINUX :~/ CarteDeVisite > jclient \
-cp $JONAS_ROOT/ejbjars/CarteDeVisiteCMP.jar \
-argclient carte_cmp.Test
ClientContainer.info : Starting client ...
Liste des clients qui ont pour nom TOTO :
6 -> toto
12 CHAPITRE 9. PREMIERS PAS J2EE
Liste des clients qui ont pour prefixe T :
-> toto
-> titi
9.2.6 Automatisation des taches repetitives
La compilation, le deployement et la publication d’un bean, ainsi que la compilationet l’execution d’un client sont des taches repetitives qu’il est aise d’automatiser. Voici unexemple de script bash qui rendra la suite de l’ennonce beaucoup plus lisible. Ce scriptpermet :
– de compiler et generer l’archive d’un bean (compile),– de le deployer et de le publier (load),– de compiler et d’executer un client (run),– de retirer le bean publie (unload),– et de nettoyer les sources (clean).TODO valider le script pour tcsh
1 #!/bin/sh
# ATTENTION : fonctionne en bash , zsh
JAR_NAME=CarteDeVisiteCMP.jar
6 CLIENT_CLASS_NAME=carte_cmp.Test
### DO NOT EDIT AFTER THIS LINE !! ###
export JAR_NAME CLIENT_CLASS_NAME
11 function compile () {
echo "## src --> bin compilation "
javac -d bin src/*. java
echo "## Deploying xml descriptors"
cp *.xml bin/META -INF/.
16 echo "## Building $JAR_NAME"
cd bin
jar cf ../ $JAR_NAME *
cd ..
}
21
function load() {
echo "## Moving $JAR_NAME --> $JONAS_ROOT/ejbjars"
mv $JAR_NAME $JONAS_ROOT/ejbjars /.
echo "## Loading $JAR_NAME in JONAS"
26 cd $JONAS_ROOT/ejbjars
jonas admin -a $JAR_NAME
cd -
}
31 function unload () {
echo "## Unloading $JAR_NAME from JONAS"
cd $JONAS_ROOT/ejbjars
jonas admin -r $JAR_NAME
cd -
36 }
9.2. GESTION DE LA PERSISTANCE - ENTITY BEAN 13
function run() {
echo "## Runnning client ... "
jclient -cp $JONAS_ROOT/ejbjars/$JAR_NAME -argclient $CLIENT_CLASS_NAME
41 }
function clean () {
echo "## Cleaning directories"
rm -rf *~ *.jar src /*~ bin/*
46 mkdir bin/META -INF
}
function main() {
case $1 in
51 "compile") compile ;;
"load") load;;
"unload") unload ;;
"run") run;;
"clean") clean;;
56 "all") unloand; clean; compile; load; run;;
*) "Unknown Command : [$1]";;
esac
}
61 main $@
Listing 9.11 – Fichier manage.sh
La gestion d’un bean devient simple. Il suffit de modifier l’entete pour indique le nomdu bean et le nom du client et d’executer ce script en precisant l’action a effectuer.
LINUX :~/ CarteDeVisite > ./ manage.sh clean
## Cleaning directories
LINUX :~/ CarteDeVisite > ./ manage.sh compile
4 ## src --> bin compilation
## Deploying xml descriptors
## Building CarteDeVisiteCMP.jar
LINUX :~/ CarteDeVisite > ./ manage.sh load
## Moving CarteDeVisiteCMP.jar --> /opt/JONAS_4_7_7/ejbjars
9 ## Loading CarteDeVisiteCMP.jar in JONAS
LINUX :~/ CarteDeVisite > ./ manage.sh run
## Runnning client ...
ClientContainer.info : Starting client ...
Liste des clients qui ont pour nom TOTO :
14 ->toto
->toto
Liste des clients qui ont pour prefixe T :
->toto
->titi
19 ->toto
->titi
LINUX :~/ CarteDeVisite > ./ manage.sh unload
## Unloading CarteDeVisiteCMP.jar from JONAS
Note : Nous utiliserons systematiquement ce script par la suite.
14 CHAPITRE 9. PREMIERS PAS J2EE
9.3 La partie metier - statefull session bean
9.3.1 Principe
Dans le cadre d’une architecture n− tiers, il n’est pas pensable d’offrir aux differentsclients la possibilite de manipuler directement les entity beans qui representent des donneesdans la base de donnees. En effet, les acces sont trop elementaires. Nous allons encapsulerla logique metier de l’application dans un session bean.
Les operations d’ajout et de supression de cartes etant critiques nous allons unique-ment les autoriser pour l’administrateur de l’application a l’aide d’un bean de session aetat (statefull session bean), dans lequel on positionnera un etat estIdentifie. L’executiondes actions d’ajout et de suppression sera autorisee uniquement pour les utilisateurs au-thentifies.
9.3.2 Ecriture du statefull session bean
Comme pour un entity bean, l’ecriture d’un session bean demande l’ecriture de deuxinterfaces (l’interface remote et l’interface home), d’une classe java implementant le beanet de deux descripteurs de configuration (celui present dans toutes plates-formes J2EE etcelui de Jonas).
Interface remote
package administrators;
3 import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Administrator extends EJBObject {
// Log into the bean
8 public boolean login(String username , String password)
throws RemoteException;
// Log out from the bean
public boolean logout () throws RemoteException;
13
// Add a ’CarteDeVisite ’ inside the system
public boolean add (String nom , String prenom ,
String mail , String phone)
throws RemoteException;
18
// Delete a card , using the id to retrieve the good one
public boolean delete (int id) throws RemoteException;
}
Listing 9.12 – Fichier Administrator.java
Interface home
9.3. LA PARTIE METIER - STATEFULL SESSION BEAN 15
package administrators;
3 import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface AdministratorHome extends EJBHome {
8 // Constructeur par defaut
Administrator create () throws RemoteException , CreateException;
// Permet de se logger directement a la creation
Administrator create(String username , String password)
13 throws RemoteException , CreateException;
}
Listing 9.13 – Fichier AdministratorHome.java
Implementation du session bean
package administrators;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
5 import javax.ejb.SessionContext;
import javax.rmi .*;
import javax.naming.InitialContext;
import javax.naming.Context;
10
import java.util .*;
import carte_cmp .*;
15 public class AdministratorBean implements SessionBean {
private boolean isLogged;
public boolean login(String username , String password) {
20 if (username.equals("admin") && password.equals("admin")) {
this.isLogged = true;
return true;
}
return false;
25 }
public boolean logout () {
this.isLogged = false;
return true;
30 }
public boolean add (String nom , String prenom , String mail , String phone) {
try {
if (isLogged) {
16 CHAPITRE 9. PREMIERS PAS J2EE
35 Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyCarteDeVisiteCMP");
// Reference a l’interface locale de l’EJB
CarteDeVisiteCMPHome home = (CarteDeVisiteCMPHome)
40 PortableRemoteObject.narrow(objref ,
CarteDeVisiteCMPHome.class );
// Objet de type CarteDeVisite , avec creation de cet objet
CarteDeVisiteCMP test = home.create (nom , prenom , mail , phone );
45
return true;
} else return false;
}
catch (Exception e) {
50 System.err.println("Erreur : " + e);
}
return false;
}
55 public boolean delete (int id) {
try {
if (isLogged) {
Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyCarteDeVisiteCMP");
60
// Reference a l’interface locale de l’EJB
CarteDeVisiteCMPHome home = (CarteDeVisiteCMPHome)
PortableRemoteObject.narrow(objref ,
CarteDeVisiteCMPHome.class );
65
// Objet de type CarteDeVisite , en vue de le supprimer
// de la table
CarteDeVisiteCMP test = home.findByPrimaryKey(id);
if (test != null){
70 test.remove ();
return true;
} else return false;
} else return false;
}
75 catch (Exception e) {
System.err.println("Erreur : " + e);
}
return false;
}
80
public void ejbCreate () { this.isLogin = false; }
public void ejbCreate(String username , String password) {
if (username.equals("admin") && password.equals("admin"))
85 this.isLogin = true;
else
this.isLogin = false;
}
90 public void ejbRemove () {}
9.3. LA PARTIE METIER - STATEFULL SESSION BEAN 17
public void ejbActivate () {}
public void ejbPassivate () {}
public void setSessionContext(SessionContext sc) {}
95 }
Listing 9.14 – Fichier AdministratorBean.java
Descripteur J2EE
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<ejb -jar >
<description >Descripteur de deploiement du bean administratif
</description >
5 <display -name >Administrator </display -name >
<enterprise -beans >
<session >
<description >Administrator </ description >
<display -name >Administrator </display -name >
10 <ejb -name >Administrator </ejb -name >
<home >administrators.AdministratorHome </home >
<remote >administrators.Administrator </remote >
<ejb -class >administrators.AdministratorBean </ejb -class >
<session -type >Stateful </session -type >
15 <transaction -type >Container </ transaction -type >
</session >
</enterprise -beans >
<assembly -descriptor >
<container -transaction >
20 <method >
<ejb -name >Administrator </ejb -name >
<method -name >*</method -name >
</method >
<trans -attribute >Required </trans -attribute >
25 </container -transaction >
</assembly -descriptor >
</ejb -jar >
Listing 9.15 – Fichier ejb-jar.xml
Descripteur Jonas
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<jonas -ejb -jar >
3 <jonas -session >
<ejb -name >Administrator </ejb -name >
<jndi -name >MyAdministrator </jndi -name >
</jonas -session >
</jonas -ejb -jar >
Listing 9.16 – Fichier jonas-ejb-jar.xml
18 CHAPITRE 9. PREMIERS PAS J2EE
9.3.3 Ecriture d’un client du session bean
Comme pour l’entity bean, nous allons construire un client capable de se connecter ausession bean precedemment decrit.
package administrators;
3 import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
8 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
13
import java.util .*;
import carte_cmp .*;
18 public class AdministratorClient {
public static void main(String args []) {
try {
23
InputStreamReader isr = new InputStreamReader ( System.in );
BufferedReader br = new BufferedReader ( isr );
boolean isQuit = false;
// Recherche de l’interface home de l’EJB
28 Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyAdministrator");
// Reference a l’interface locale de l’EJB
AdministratorHome home = (AdministratorHome)
33 PortableRemoteObject.narrow(objref ,
AdministratorHome.class );
// Creation d’un administrateur
Administrator myAdministrator = home.create ();
38 while (isQuit == false) {
System.out.println("1. Connexion");
System.out.println("2. Quitter");
System.out.println(">");
String principalChoice = null;
43 principalChoice = br.readLine ();
if (principalChoice.equals("2")){
isQuit = true;
System.out.println("Bye bye ...");
48 }
else if (principalChoice.equals("1")){
System.out.println("Username : ");
String username = null;
9.3. LA PARTIE METIER - STATEFULL SESSION BEAN 19
username = br.readLine ();
53
System.out.println("Password : ");
String password = null;
password = br.readLine ();
if (myAdministrator.login(username , password )){
58 boolean isLog = true;
while (isLog == true){
System.out.println("1. Ajouter une carte "
+"de visite");
System.out.println("2. Retirer une carte "
63 +"de visite");
System.out.println("3. Se deconnecter");
System.out.println(">");
String secondaryChoice = null;
secondaryChoice = br.readLine ();
68 if (secondaryChoice.equals("1")){
System.out.println("Ajout d’une "
+"carte de visite ...");
System.out.println("Entrer le nom : ");
String nom = null;
73 nom = br.readLine ();
System.out.println("Entrer le prenom : ");
String prenom = null;
prenom = br.readLine ();
System.out.println("Entrer le mail : ");
78 String mail = null;
mail = br.readLine ();
System.out.println("Entrer le numero de "
+"tel : ");
String phone = null;
83 phone = br.readLine ();
boolean isAdd = myAdministrator.add(nom ,
prenom ,
mail ,
phone );
88 if (isAdd ){
System.out.println("Ajout reussi ...");
}
else{
System.out.println("Ajout echoue ...");
93 }
}
else if (secondaryChoice.equals("2")){
System.out.println("Suppression d’une"
+" carte de visite ...");
98 System.out.println("Entrer l’ID : ");
String id = null;
id = br.readLine ();
int idToDelete = Integer.parseInt(id);
boolean isDelete =
103 myAdministrator.delete(idToDelete );
if (isDelete ){
System.out.println("Suppression "
+"reussie ...");
}
20 CHAPITRE 9. PREMIERS PAS J2EE
108 else{
System.out.println("Supression "
+"echouee ...");
}
}
113 else if (secondaryChoice.equals("3")){
myAdministrator.logout ();
isLog = false;
System.out.println("Logout ...");
}
118 else{
System.out.println("Choix incorrect ...");
}
}
}
123 else{
System.out.println("Username ou Password "
+"incorrect ...");
}
}
128 else{
System.out.println("Choix incorrect ...");
}
}
} catch (Exception e) {
133 System.err.println("Erreur : " + e);
System.exit (2);
}
}
}
Listing 9.17 – Fichier AdministratorClient.java
9.3.4 Compilation du bean et du client, deploiement du bean etexecution du client
Il est essentiel que le repertoire du session bean connaisse les interfaces de l’entitybean qu’il va acceder. Il est donc necessaire de copier les interfaces home et remote del’entity bean (CarteDeVisiteCMPHome.java et CarteDeVisiteCMP.java) dans le repertoiresrc du session bean avec l’ensemble du package2.
Il reste aussi a copier le script associe a l’entity bean (manage.sh) dans le repertoiredu session bean et de le mettre a jour avec les modifications suivantes :
JAR_NAME=Administrator.jar
CLIENT_CLASS_NAME=administrators.AdministratorClient
L’execution du client doit etre parametree de la maniere suivante :
jclient -cp /opt/JONAS_4_7_7/ejbjars/$JAR_NAME :\
$JONAS_ROOT/ejbjars/CarteDeVisiteCMP.jar \
3 -argclient $CLIENT_CLASS_NAME
2Une solution plus eleguante, laisxssee au lecteur en exercice, serait d’implementer un systeme de char-gement de classe dynamique qui telechargerait ces classes depuis le serveur Jonas a l’execution.
9.3. LA PARTIE METIER - STATEFULL SESSION BEAN 21
Il ne reste plus qu’a utiliser le script pour compiler le bean et le client, deployer le beanpuis execution le client.
LINUX :~/ Administrator > ./ manage.sh compile
2 ## src --> bin compilation
## Deploying xml descriptors
## Building Administrator.jar
LINUX :~/ Administrator >
LINUX :~/ Administrator > ./ manage.sh load
7 ## Moving Administrator.jar --> /opt/JONAS_4_7_7/ejbjars
## Loading Administrator.jar in JONAS
LINUX :~/ Administrator > ./ manage.sh run
## Runnning client ...
ClientContainer.info : Starting client ...
12 1. Connexion
2. Quitter
>
toto
Choix incorrect ...
17 1. Connexion
2. Quitter
>
1
Username :
22 toto
Password :
titi
Username ou Password incorrect ...
1. Connexion
27 2. Quitter
>
1
Username :
admin
32 Password :
admin
1. Ajouter une carte de visite
2. Retirer une carte de visite
3. Se deconnecter
37 >
1
Ajout d’une carte de visite ...
Entrer le nom :
MOSSER
42 Entrer le prenom :
sebastien
Entrer le mail :
Entrer le numero de tel :
47 01234566
Ajout reussi ...
1. Ajouter une carte de visite
2. Retirer une carte de visite
3. Se deconnecter
52 >
1
22 CHAPITRE 9. PREMIERS PAS J2EE
Ajout d’une carte de visite ...
Entrer le nom :
JOFFROY
57 Entrer le prenom :
Cedric
Entrer le mail :
Entrer le numero de tel :
62 987654321
Ajout reussi ...
1. Ajouter une carte de visite
2. Retirer une carte de visite
3. Se deconnecter
67 >
3
Logout ...
1. Connexion
2. Quitter
72 >
2
Bye bye ...
9.4 La partie metier (suite) - stateless session bean
Apres avoir ecrit la partie metier qui sera utilise par l’administrateur de l’application,nous allons construire celle utilisee par tous les utilisateurs souhaitant consulter la base decartes de visite. La consultation d’une carte ne necessite pas de session, nous utiliseronsdonc un stateless session bean.
Comme tout bean, un stateless session bean a une remote interface, une home interface,une implementation et deux descripteurs.
9.4.1 Ecriture du stateless session bean
Remote interface
1 package consultators;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
6 import java.util .*;
public interface Consultator extends EJBObject {
// Find a card looking on name
11 public Collection rechercherNom(String nom)
throws RemoteException;
// Find a card with a prefix
public Collection rechercherPrefix(String prefix)
16 throws RemoteException;
}
9.4. LA PARTIE METIER (SUITE) - STATELESS SESSION BEAN 23
Listing 9.18 – Fichier Consultator.java
Home interface
package consultators;
3 import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface ConsultatorHome extends EJBHome {
8
Consultator create () throws RemoteException , CreateException;
}
Listing 9.19 – Fichier ConsultatorHome.java
Implementation du bean
package consultators;
import java.rmi.RemoteException;
4 import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.rmi .*;
import javax.naming.InitialContext;
9 import javax.naming.Context;
import java.util .*;
import carte_cmp .*;
14
public class ConsultatorBean implements SessionBean {
public Collection rechercherNom(String nom) {
try {
19 Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyCarteDeVisiteCMP");
// Reference a l’interface locale de l’EJB
CarteDeVisiteCMPHome home = (CarteDeVisiteCMPHome)
24 PortableRemoteObject.narrow(objref ,
CarteDeVisiteCMPHome.class );
// Objet de type client pour faire nos tests
CarteDeVisiteCMP test;
29
// Recherche par le nom de la personne
Collection c1 = home.findByNom(nom);
24 CHAPITRE 9. PREMIERS PAS J2EE
return c1;
34 }
catch (Exception e) {
System.err.println("Erreur : " + e);
}
return null;
39 }
public Collection rechercherPrefix(String prefix) {
try {
Context initialContext = new InitialContext ();
44 Object objref = initialContext.lookup("MyCarteDeVisiteCMP");
// Reference a l’interface locale de l’EJB
CarteDeVisiteCMPHome home = (CarteDeVisiteCMPHome)
PortableRemoteObject.narrow(objref ,
49 CarteDeVisiteCMPHome.class );
// Objet de type client pour faire nos tests
CarteDeVisiteCMP test;
54 // Recherche par le prefix de la personne
Collection c1 = home.findByPrefix(prefix );
return c1;
}
59 catch (Exception e) {
System.err.println("Erreur : " + e);
}
return null;
}
64
public void ejbCreate () {}
public void ejbRemove () {}
public void ejbActivate () {}
public void ejbPassivate () {}
69 public void setSessionContext(SessionContext sc) {}
}
Listing 9.20 – Fichier ConsultatorBean.java
Descripteur J2EE
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<ejb -jar >
<description >Descripteur de deploiement du consultator </ description >
<display -name >Consultator </display -name >
5 <enterprise -beans >
<session >
<description >Consultator </ description >
<display -name >Consultator </display -name >
<ejb -name >Consultator </ejb -name >
10 <home >consultators.ConsultatorHome </home >
<remote >consultators.Consultator </remote >
9.4. LA PARTIE METIER (SUITE) - STATELESS SESSION BEAN 25
<ejb -class >consultators.ConsultatorBean </ejb -class >
<session -type >Stateless </session -type >
<transaction -type >Container </ transaction -type >
15 </session >
</enterprise -beans >
<assembly -descriptor >
<container -transaction >
<method >
20 <ejb -name >Consultator </ejb -name >
<method -name >*</method -name >
</method >
<trans -attribute >Required </trans -attribute >
</container -transaction >
25 </assembly -descriptor >
</ejb -jar >
Listing 9.21 – Fichier ejb-jar.xml
Descripteur Jonas
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<jonas -ejb -jar >
<jonas -session >
4 <ejb -name >Consultator </ejb -name >
<jndi -name >MyConsultator </jndi -name >
</jonas -session >
</jonas -ejb -jar >
Listing 9.22 – Fichier jonas-ejb-jar.xml
9.4.2 Client d’un session bean
Nous commencons a etre rode... aucune difficulte particuliere.
package consultators;
3 import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
8 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
13
import java.util .*;
import carte_cmp .*;
public class ConsultatorClient {
18
public static void main(String args []) {
26 CHAPITRE 9. PREMIERS PAS J2EE
try {
23 // Recherche de l’interface home de l’EJB
Context initialContext = new InitialContext ();
Object objref = initialContext.lookup("MyConsultator");
// Reference a l’EJB
28 ConsultatorHome home = (ConsultatorHome)
PortableRemoteObject.narrow(objref , ConsultatorHome.class );
Consultator myConsultator = home.create ();
// On va chercher des gens
33 InputStreamReader isr = new InputStreamReader ( System.in );
BufferedReader br = new BufferedReader ( isr );
boolean isQuit = false;
38 while (isQuit == false){
System.out.println("1. Rechercher par nom");
System.out.println("2. Rechercher par prefixe (sur le nom)");
System.out.println("3. Quitter");
System.out.println(">");
43
String choice = null;
choice = br.readLine ();
if (choice.equals("1")){
System.out.println("Recherche par nom ...");
48 String nom = null;
System.out.println("Entrez le nom : ");
nom = br.readLine ();
CarteDeVisiteCMP test = null;
Collection cl = myConsultator.rechercherNom(nom);
53 System.out.println("recherche sur le nom : "+nom);
if(cl != null){
Iterator iLast = cl.iterator ();
while (iLast.hasNext ()) {
test = iLast.next ();
58 System.out.println("->" + test.getPrenom ());
}
}
else{
System.out.println("Echec de recherche ...");
63 }
}
else if (choice.equals("2")){
System.out.println("Recherche par prefixe ...");
String prefix = null;
68 System.out.println("Entrez le prefixe : ");
prefix = br.readLine ();
CarteDeVisiteCMP test = null;
Collection c2 = myConsultator.rechercherPrefix(prefix );
System.out.println("recherche sur le prefix : "+prefix );
73 if(c2 != null){
Iterator iLast2 = c2.iterator ();
while (iLast2.hasNext ()) {
test = iLast2.next ();
9.4. LA PARTIE METIER (SUITE) - STATELESS SESSION BEAN 27
System.out.println("->" + test.getPrenom ());
78 }
}
else {
System.out.println("Echec de recherche ...");
}
83 }
else if (choice.equals("3")){
System.out.println("Bye bye ...");
isQuit = true;
}
88 else{
System.out.println("Choix incorrect ...");
}
}
} catch (Exception e) {
93 System.err.println("Erreur : " + e);
System.exit (2);
}
}
}
Listing 9.23 – Fichier ConsultatorClient.java
9.4.3 Compilation, deploiement et execution
A vous de jouer. Voici un exemple d’execution :
LINUX :~/ Consultator > ./ manage.sh run
## Runnning client ...
3 ClientContainer.info : Starting client ...
1. Rechercher par nom
2. Rechercher par prefixe (sur le nom)
3. Quitter
>
8 1
Recherche par nom...
Entrez le nom :
mosser
recherche sur le nom : mosser
13 ->sebastien
1. Rechercher par nom
2. Rechercher par prefixe (sur le nom)
3. Quitter
>
18 2
Recherche par prefixe ...
Entrez le prefixe :
m
recherche sur le prefix : m
23 ->sebastien
1. Rechercher par nom
2. Rechercher par prefixe (sur le nom)
3. Quitter
>
28 CHAPITRE 9. PREMIERS PAS J2EE
28 3
Bye bye ...
9.5 La partie presentation - servlet
9.5.1 Principe
Apres avoir construit plusieurs clients lourds, il nous semble essentiel de pouvoir offriraux utilisateurs eventuels la possibilite de consulter les cartes depuis un client leger.
Dans l’approche J2EE, les clients legers sont offerts par exemple par l’utilisation deservlet qui generent des pages html consultables depuis n’importe quel butineur web.
9.5.2 Ecriture de la servlet
Les differents repertoires utilises sont :– src : contient les sources de la servlet– bin/WEB-INF/ : contient les descripteurs de deploiements– bin/WEB-INF/classes : le code compile de la servlet.La servlet implementee reagira a une requete GET3 et son code est le suivant :
1 import java.io.PrintWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import javax.servlet.ServletException;
6 import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.naming.Context;
11 import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import consultators .*;
import carte_cmp .*;
16
public class Consult extends HttpServlet {
protected void doGet(HttpServletRequest req , HttpServletResponse res)
throws ServletException , IOException {
21 res.setContentType("text/html");
PrintWriter out = res.getWriter ();
head(out);
Object prefix = req.getParameter("prefix");
look(prefix , out);
26 foot(out);
}
private void look(Object p, PrintWriter out) {
3Il est possible de construire une servlet reagissant a une requete POST en implementant unemethode doPost.
9.5. LA PARTIE PRESENTATION - SERVLET 29
if (p == null) {
31 out.println("You must enter a name !");
return;
}
String prefix = (String) p;
if (prefix.equals("")) {
36 out.println("You must enter a name !");
return;
}
// Initializing context
41 Context initialContext = null;
try {
initialContext = new InitialContext ();
}
catch(Exception e) {
46 out.println("<h3 > Unable to find InitialContext !</h3 >");
out.println(e + "<br />");
return;
}
51 // Connecting to the bean
ConsultatorHome home = null;
try {
home = (ConsultatorHome)
PortableRemoteObject.narrow(
56 initialContext.lookup("MyConsultator"),
ConsultatorHome.class);
}
catch(Exception e) {
out.println("<h3 > Unable to retrieve MyConsultator !</h3 >");
61 out.println(e + "<br />");
return;
}
// Instanciation
66 Consultator consult = null;
try {
consult = home.create ();
}
catch(Exception e) {
71 out.println("<h3 > Unable to create a Consultator"
+ " instance !</h3 >");
out.println(e + "<br />");
return;
}
76
// Doing the search ...
Collection result = null;;
try {
result = consult.rechercherPrefix(prefix );
81 out.println("<h2 > Search Result for " + prefix + "</h2 >");
printResult(result , out);
}
catch(Exception e) {
out.println("<h3 > Unable to invoke the Consultator !</h3 >");
30 CHAPITRE 9. PREMIERS PAS J2EE
86 out.println(e + "<br />");
return;
}
91 }
private void printResult(Collection c, PrintWriter out)
throws Exception {
if (c.size() == 0) {
96 out.println("<strong > No match found ! </strong >");
}
Iterator i = c.iterator ();
while (i.hasNext ()) {
CarteDeVisiteCMP card = (CarteDeVisiteCMP) i.next ();
101 out.println("<h4 > " + card.getNom () + " " + card.getPrenom ()
+ " </h4>");
out.println("<ul >");
out.println("<li > Telephone : "+ card.getPhone () +"</li >");
out.println("<li > Email : "+ card.getEmail () +"</li >");
106 out.println("</ul >");
}
}
111
private void head(PrintWriter out) {
out.println("<html ><head ><title >Card Consultation Form </title >"
+" </head >");
out.println("<body >");
116 out.println("<h1 >Looking for Someone ?</h1 ><br >");
out.println("<form method =\" get\">");
out.println("<p>");
out.println("Name : "
+ "<input type =\" text\" name =\" prefix \" />");
121 out.println("<br /> <input type =\" submit \" value =\" Search !\"/>");
out.println("</p>");
out.println("</form >");
}
126 private void foot(PrintWriter out) {
out.println("</body >");
out.println("</html >");
out.close ();
}
131 }
Listing 9.24 – Fichier Consult.java
Descripteur J2EE
Le descripteur permet de decrire l’URL associee a la servlet ainsi que les liens avec lesbeans utilises.
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
9.5. LA PARTIE PRESENTATION - SERVLET 31
<web -app xmlns ="http :// java.sun.com/xml/ns/j2ee"
xmlns:xsi="http ://www.w3.org /2001/ XMLSchema -instance"
4 xsi:schemaLocation ="http :// java.sun.com/xml/ns/j2ee
http :// java.sun.com/xml/ns/j2ee/web -app_2_4.xsd"
version ="2.4" >
<servlet >
<servlet -name >CardManager </servlet -name >
9 <servlet -class >Consult </servlet -class >
</servlet >
<servlet -mapping >
<servlet -name >CardManager </servlet -name >
<url -pattern >/card/consult </url -pattern >
14 </servlet -mapping >
<ejb -ref >
<ejb -ref -name >Consultator </ejb -ref -name >
<ejb -ref -type >Session </ejb -ref -type >
<home >consultators.ConsultatorHome </home >
19 <remote >consultators.Consultator </remote >
<ejb -link >Consultator.jar </ejb -link >
</ejb -ref >
</web -app >
Listing 9.25 – Fichier web.xml
Descripteur Jonas
Ce descripteur decrit les liens avec le session bean utilise.
<?xml version ="1.0" encoding ="ISO -8859 -1"? >
<jonas -web -app xmlns ="http :// www.objectweb.org/jonas/ns"
3 xmlns:xsi="http ://www.w3.org /2001/ XMLSchema -instance"
xsi:schemaLocation ="http :// www.objectweb.org/jonas/ns
http :// www.objectweb.org/jonas/ns/jonas -web -app_4_0.xsd" >
<jonas -ejb -ref >
<ejb -ref -name >Consultator </ejb -ref -name >
8 <jndi -name >MyConsultator </jndi -name >
</jonas -ejb -ref >
<host >localhost </host >
<context -root >web -application </context -root >
</jonas -web -app >
Listing 9.26 – Fichier jonas-web.xml
9.5.3 Compilation et deploiement
Les servlets sont chargees comme des applications web, et doivent etre packagees commetelles. Ainsi, on archivera le contenu du repertoire bin dans un fichier war (pour WebArchive) et non dans un jar (Java Archive)4.
4Un fichier .war se genere comme un fichier .jar en utilisant la commande jar
32 CHAPITRE 9. PREMIERS PAS J2EE
Compilation
La servlet accede au session bean et entity bean via son interface remote qu’il fautdonc copier dans le repertoire src.
TODO pourquoi aussi l’entity bean ?TODO pourquoi pas via un proxy ?
LINUX:~> javac -cp $JONAS\_ROOT/lib/commons/j2ee.servlet.jar -d bin/WEB -INF/classes src/*java
LINUX:~> cp web.xml jonas -web.xml bin/WEB -INF/.
3 LINUX:~> cd bin
LINUX :~/bin > jar cf ../ Consult.war *
LINUX :~/bin > cd ..
Chargement
LINUX:~> mv Consult.war >JONAS_ROOT/webapps /.
LINUX:~> cd $JONAS_ROOT/webapps
LINUX:~> jonas admin -a Consult.war
Execution
Il suffit d’ouvrir son butineur prefere, et de se rendre a l’adresse decrite dans le fichierde mapping : http://localhost:9000/web-application/card/consult.
9.6 Pour aller plus loin
– Ecrire une servlet pour l’administration de l’annuaire.– Utiliser la securite J2EE– Utiliser les transactions