SlideShare une entreprise Scribd logo
1  sur  65
Télécharger pour lire hors ligne
INSA - ASI InfoRep : EJB 1/65
Informatique Répartie
Introduction aux EJB
Alexandre Pauchet
INSA Rouen - Département ASI
BO.B.RC.18, pauchet@insa-rouen.fr
INSA - ASI InfoRep : EJB 2/65
Plan
1 Introduction
2 Architecture J2EE
3 EJB
4 EJB Session sans état
5 Envoi d’exception
6 Passage d’objets par valeur
7 Callbacks
8 EJB Session avec état
9 EJB/JSP
10 Persistance
11 Les EJB message
INSA - ASI InfoRep : EJB 3/65
Introduction (1/3)
Historique (rappel)
Années 70 : architectures Mainframe (1 tier)
Années 80 : architectures 2 tiers (BD)
Fin des années 80 : architectures 3 tiers (RPC)
Années 90 : architectures 3 tiers Objet (RMI/Corba)
Années 00 : architectures orientées services (Web Services)
Fin des années 00 : architectures orientées ressources (RESTful)
INSA - ASI InfoRep : EJB 4/65
Introduction (2/3)
Histoire
Aspect programmation
Années 70-80 : Programmation procédurale
alors que les premiers langages objets datent de la fin des années 60 !
Années 90 : Programmation objet
Fin des années 90 : Programmation par composants
Les composants peuvent être physiquement distants
Si changement, pas besoin de tout recompiler et de tout relinker
Bonne programmation objet : seules les interfaces sont connues
INSA - ASI InfoRep : EJB 5/65
Introduction (3/3)
J2EE
Volonté de SUN
Cadre de développement par composants avec services
J2EE (Java 2 Edition Enterprise), qui propose des API :
L’invocation de méthodes distantes : RMI, CORBA, Web Services
L’accès aux bases de données relationnelles : JDBC
L’accès aux annuaires et services de nommage : JNDI
L’utilisation du XML : DOM et SAX
HTML dynamique et traitement de requêtes HTTP : JSP et Servlet
La gestion du Mail : Java Mail
La gestion des composants : EJB
La gestion des messages entre composants : Java Message Service
La gestion des droits d’accès : Java Authentication and Authorization
Service (JAAS)
INSA - ASI InfoRep : EJB 6/65
Architecture J2EE (1/4)
Description de l’architecture J2EE
INSA - ASI InfoRep : EJB 7/65
Architecture J2EE (2/4)
Rappels : J2EE et les conteneurs Web
La spécification J2EE fournit les éléments suivants pour la
conception et la réalisation d’application Web :
Servlets Java et JSP
Les servlets et JSP constituent les blocs de construction du
développement d’applications web avec J2EE
En terme J2EE, les servlets et pages JSP sont des composants web
Application web
Collection de servlets et de pages JSP, d’autres classes annexes ou de
bibliothèques de classes, ainsi que des ressources statiques telles que
des documents HTML, XHTML ou XML, images, etc.
Conteneur web
Essentiellement un environnement d’exécution Java pour les
applications web
Responsable de l’initialisation, de l’invocation et de la gestion de la
durée de vie des servlets Java et des pages JSP
INSA - ASI InfoRep : EJB 8/65
Architecture J2EE (3/4)
Rappels : J2EE et les conteneurs Web
Éléments de la spécification J2EE (suite) :
structure de paquetage et descripteur de déploiement
le descripteur de déploiement est un fichier XML
Classes Java
Archives
Description de déploiement
Classes Java
Archives
Description de déploiement
Conteneur web
Servlets
Page JSP
Application web
Servlets
Page JSP
Application web
INSA - ASI InfoRep : EJB 9/65
Architecture J2EE (4/4)
Rappels : J2EE et les conteneurs Web
Exemple de conteneur Web
Tomcat
http://www.apache.org
INSA - ASI InfoRep : EJB 10/65
Les EJB (1/11)
Description
Un composant EJB est constitué d’une collection de
classes/interfaces Java
Les classes Java doivent respecter certaines règles (Spécifications)
Le composant EJB s’exécute dans un conteneur EJB, qui prend en
charge tout ce qui concerne le niveau système
Répartition des tâches entre le programmeur d’EJB et le conteneur
Les composant EJB fonctionnent avec tout type de client :
servlets et JSP
clients Java (via RMI)
clients et serveur divers (via RMI-IIOP, Services Web)
. . .
3 types d’EJB : entité, session, message
INSA - ASI InfoRep : EJB 11/65
Les EJB (2/11)
Variétés d’EJB : les EJB entité
Représentation orientée objet de données dans une base de données
Les clients peuvent y accéder en toute sécurité simultanément
La durée de vie de l’EJB est exactement identique à celle des données
qu’il représente
La relation d’un EJB entité avec les données de la base de données
peut être gérée par
le programmeur : persistance gérée par l’EJB
le conteneur : persistance gérée par le conteneur
Cette distinction se révélera souvent essentielle du point de vue des
performances
Cependant on peut utiliser n’importe quel type d’EJB de manière
interchangeable dans la conception
INSA - ASI InfoRep : EJB 12/65
Les EJB (3/11)
Variétés d’EJB : les EJB session
Client unique (extension du client sur le serveur)
Fournit de la logique métier (calcul d’un taux, panier d’un client, etc.)
La durée de vie de l’EJB ne doit pas dépasser celle de son client
Représente la logique métier
Seuls EJB interfaçable par les clients
Les EJB session sans état
ne possède aucune information sur son client
ex : EJB relatif à une calculatrice
Les EJB session avec état
peut conserver des informations au nom de son client
ex : EJB relatif à un panier d’achat électronique
INSA - ASI InfoRep : EJB 13/65
Les EJB (4/11)
Variétés d’EJB : les EJB message
EJB producteur ou consommateur de messages
Utilisation de JMS (le server d’application est un JMS provider, et les
EJB sont des JMS client : JMS producer et JMS consumer)
Permet l’envoi de messages asynchrones
Permet l’envoi multiple (1 → n)
INSA - ASI InfoRep : EJB 14/65
Les EJB (5/11)
Les conteneurs EJB
Conteneur = environnement d’exécution pour un composant
Le composant se trouve dans le conteneur
Le conteneur fournit des services au composant
Conteneur se trouve dans un serveur d’applications qui lui fournit un
environnement d’exécution
Conteneur
EJB
web
Serveur d’applications
Conteneur
INSA - ASI InfoRep : EJB 15/65
Les EJB (6/11)
Les services des conteneurs EJB
Sans écrire une seule ligne de code
Persistance. Possibilité pour l’EJB d’être persistant dans une BD
Transactions déclaratives. Possibilité de gérer des transactions
complexes (sans utiliser l’API JTA -Java Transaction- et JTS -Java
Transaction Service-)
Mémoire cache. Possibilité d’améliorer les performances
Sécurité déclarative. Possibilité de gérer l’accès aux composants
Gestion d’erreurs. La spécification EJB définit la manière dont les
erreurs affectent les transactions, les résultats au niveau client, la
connexion et la restauration des composants
Portabilité. EJB = Spécification = possibilité de porter un EJB sur
un autre serveur plus puissant
INSA - ASI InfoRep : EJB 16/65
Les EJB (7/11)
Comment le conteneur fournit-il ces services ?
3 concepts de bases pour les EJB
Le concept de contrat
Services orthogonaux aux EJB
Interposition du conteneur entre le client et l’EJB
Contrat
Répartition des responsabilités entre chaque couche du logiciel
(Client, Conteneur, EJB, Gestionnaire de persistance (≥ 2.0))
Services orthogonaux
Le conteneur EJB fournit des services au programmeur
Le programmeur de l’EJB n’a plus qu’à respecter les règles pour
exploiter automatiquement ces services
Ces règles sont spécifiées dans le descripteur de déploiement
INSA - ASI InfoRep : EJB 17/65
Les EJB (8/11)
Interposition
Interposition : RMI et le design pattern Remote Proxy
Client
Stub
RMI
Réseau
Skeleton
RMI
Classe
d’interposition
générée
par
le
conteneur
Votre
EJB
1 Le client exécute un appel sur un Stub RMI
2 Ce stub RMI assemble et envoie des informations au serveur
3 Le skeleton désassemble les paramètres et les transmets au conteneur EJB
4 Le conteneur examine les références de sécurité de l’appelant de la méthode
5 Le conteneur démarre ou rejoint toute transaction nécessaire
6 Le conteneur exécute tous les appels nécessaires aux fonctions de persistance
7 Le conteneur déclenche diverses méthodes callback pour permettre au composant EJB d’acquérir des ressources
8 La méthode “logique métier” est appelée
9 Le conteneur exécute quelques autres tâches relatives aux transactions, à la persistance, aux méthodes callback
10 Le conteneur renvoie le résultat de la méthode métier ou une exception au client
INSA - ASI InfoRep : EJB 18/65
Les EJB (9/11)
Annotations Java
Intégrées au JDK 1.5, elles permettent d’ajouter des Méta-informations au code
(i.e. marquer des éléments Java afin de leur ajouter une propriété)
Peuvent être utilisées sur n’importe quel type d’élément Java (package, class,
attribut, méthode, paramètre, etc.)
Plusieurs annotations peuvent être utilisées sur un même élément
Non prises en compte par la JVM (mais présente dans le .class) : il faut écrire
du code ou des outils qui utilise ces informations
Utilisées à la compilation ou à l’exécution
Utilisation : @ suivi du mot-clef correspondant à l’annotation
L’API Java 5.0 propose de base 3 annotations : @Deprecated, @Override et
@SuppressWarnings
Déclaration et création de nouvelles annotations : comme une interface en
utilisant le mot-clef @interface (java.lang.annotation.Annotation)
Possibilité de passer des informations à une annotation : nom=valeur
INSA - ASI InfoRep : EJB 19/65
Les EJB (10/11)
Exemple d’annotations Java
Exemple
p u b l i c @interface MaNouvelleAnnotation {
}
Exemple
@ MaNouvelleAnnotation
@ SuppressWarnings (" deprecation ")
p u b l i c c l a s s maClasse {
@ UneAutreAnnotation (champ =" type ")
p u b l i c String texte = "Texte";
@Override
@ SuppressWarnings ({" deprecation "," unchecked "})
p u b l i c String toString () {
return t h i s .texte;
}
}
INSA - ASI InfoRep : EJB 20/65
Les EJB (11/11)
EJB3 et les annotations
Les EJB3 utilisent les annotations pour simplifier le code à produire :
Moins de code à écrire
Génération automatique des descripteurs de déploiement
INSA - ASI InfoRep : EJB 21/65
Les EJB Session sans état (1/7)
Description
EJB Session sans état (Stateless)
Composé d’une ou deux interfaces et d’une classe métier :
Interface de description du contrat pour accès distant
(XXRemote.java)
Utilisation de l’annotation @Remote (importation de
javax.ejb.Remote) juste avant la définition de l’interface
Interface de description du contrat pour accès local
(XXLocal.java)
Utilisation de l’annotation @Local (importation de
javax.ejb.Local) juste avant la définition de l’interface
Classe de définition de la logique métier (XXBean.java)
Importation de javax.ejb.Stateless
Utilisation de l’annotation @Stateless avant la définition de classe
Implémentation des interfaces précédentes
Ne pas être final
INSA - ASI InfoRep : EJB 22/65
Les EJB Session sans état (2/7)
Cycle de vie
1
Dans XXXBean.java
@PostConstruct suivi de la méthode postConstruct
@PreDestroy suivi de la méthode preDestroy
1. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/
doc/EJBConcepts9.html
INSA - ASI InfoRep : EJB 23/65
Les EJB Session sans état (3/7)
Côté serveur
HelloStatelessRemote.java
package HelloWorld;
import javax.ejb.Remote;
@Remote
public i n t e r f a c e HelloStatelessRemote {
p u b l i c String sayHello(String s);
}
HelloStatelessLocal.java
package HelloWorld;
import javax.ejb.Local;
@Local
public i n t e r f a c e HelloStatelessLocal {
p u b l i c String sayHello(String s);
}
INSA - ASI InfoRep : EJB 24/65
Les EJB Session sans état (4/7)
Côté serveur
HelloStatelessBean.java
package HelloWorld;
import javax.ejb.Stateless;
@Stateless
public c l a s s HelloStatelessBean implements HelloStatelessLocal , HelloStatelessRemote {
p u b l i c String sayHello(String s) {
return "Hello " + s + " !";
}
}
@Local et @Remote peuvent être portées par la même interface
Il faut au moins une annotation @Local ou @Remote
Toutes les annotations peuvent éventuellement être placées
directement dans l’EJB. L’interface doit alors être précisé :
@Stateless
@Remote( NomInterface .class)
p u b l i c c l a s s EJBStateless implements NomInterface {
...
}
INSA - ASI InfoRep : EJB 25/65
Les EJB Session sans état (5/7)
Déploiement avec JBoss
Compilation et déploiement
A la compilation, inclure dans le classpath :
JBOSS_DIR/modules/javax/ejb/api/main/jboss-ejb-api_3.1_
spec-1.0.1.Final.jar (JBoss)
JBOSS_DIR/modules/system/layers/base/javax/ejb/api/main/
jboss-ejb-api_3.2_spec-1.0.0.Final.jar (WildFly)
Mettre dans un .jar
Pour déployer, déposer dans le répertoire
JBOSS DIR/server/JBOSS MODE/deploy (JBoss < 7)
JBOSS DIR/standalone/deployments (JBoss 7 et plus)
Arborescence des répertoires
HelloStateless.jar
|_ HelloWorld
| |_ HelloStatelessLocal.class
| |_ HelloStatelessBean.class
|_ META-INF
|_ MANIFEST.MF
INSA - ASI InfoRep : EJB 26/65
Les EJB Session sans état (6/7)
Côté client
Nommage d’un EJB
Service de nommage : JNDI
Nommage d’un EJB : ejb:AppName(ear)/ModuleName(jar)/BeanName!InterfaceName
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import HelloWorld. HelloStatelessRemote ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
HelloStatelessRemote obj = ( HelloStatelessRemote )context.lookup("ejb:/
HelloStateless / HelloStatelessBean !HelloWorld. HelloStatelessRemote ");
System.out.println(obj.sayHello(args [0]));
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
}
INSA - ASI InfoRep : EJB 27/65
Les EJB Session sans état (7/7)
Exécution Client
À l’exécution, inclure dans le classpath :
JBOSS_DIR/bin/client/jboss-client.jar
jboss-ejb-client.properties
jboss-ejb-client.properties
endpoint.name = client -endpoint
remote. connectionprovider .create.options.org.xnio.Options. SSL_ENABLED = f a l s e
remote. connections = d e f a u l t
remote.connection. d e f a u l t .host = localhost
remote.connection. d e f a u l t .port = 8080
remote.connection. d e f a u l t .connect.options.org.xnio.Options. SASL_POLICY_NOANONYMOUS =
f a l s e
INSA - ASI InfoRep : EJB 28/65
Envoi d’exception (1/3)
Côté serveur
EJB : HelloStatelessBean.java
package HelloWorld;
import javax.ejb.Stateless;
@Stateless
public c l a s s HelloStatelessBean implements HelloStatelessRemote {
p u b l i c String sayHello(String s) throws ChaineVide {
i f (s.length () ==0) {
throw new ChaineVide ();
}
e l s e i f (s.equals("test")) {
s = "" + 1/0;
}
return "Hello " + s + " !";
}
}
INSA - ASI InfoRep : EJB 29/65
Envoi d’exception (2/3)
Côté serveur
Exception : ChaineVide.java
package HelloWorld;
p u b l i c c l a s s ChaineVide extends Exception {
p u b l i c ChaineVide (){
super ("String vide !");
}
}
Interface : HelloStatelessRemote.java
package HelloWorld;
import javax.ejb.Remote;
@Remote
public i n t e r f a c e HelloStatelessRemote {
p u b l i c String sayHello(String s) throws ChaineVide;
}
INSA - ASI InfoRep : EJB 30/65
Envoi d’exception (3/3)
Côté client
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import HelloWorld. HelloStatelessRemote ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
HelloStatelessRemote obj = ( HelloStatelessRemote )context.lookup("ejb:/
HelloException / HelloStatelessBean !HelloWorld. HelloStatelessRemote ");
i f (args.length >0)
System.out.println(obj.sayHello(args [0]));
e l s e
System.out.println(obj.sayHello(""));
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
}
INSA - ASI InfoRep : EJB 31/65
Passage d’objets par valeur (1/4)
Côté serveur
Interface : HelloSerializableRemote.java
package HelloWorld;
import javax.ejb.Remote;
@Remote
public i n t e r f a c e HelloSerializableRemote {
p u b l i c String sayHello(Guy g);
}
EJB : HelloSerializableBean.java
package HelloWorld;
import javax.ejb.Stateless;
@Stateless
public c l a s s HelloSerializableBean implements HelloSerializableRemote {
p u b l i c String sayHello(Guy g) {
return "Hello " + g.getName () + " !";
}
}
INSA - ASI InfoRep : EJB 32/65
Passage d’objets par valeur (2/4)
Objet passé
Guy.java
package HelloWorld;
import java.io. Serializable ;
p u b l i c c l a s s Guy implements Serializable {
p r i v a t e String name;
p u b l i c Guy () { t h i s .name = ""; }
p u b l i c Guy(String name) { t h i s .name = name; }
p u b l i c String getName () {
return t h i s .name;
}
p u b l i c void setName(String name) {
t h i s .name = name;
}
}
INSA - ASI InfoRep : EJB 33/65
Passage d’objets par valeur (3/4)
Déploiement
Arborescence des répertoires
HelloSerializable.jar
|_ HelloWorld
| |_ HelloSerializableRemote.class
| |_ HelloSerializableBean.class
| |_ Guy.class
|_ META-INF
|_ MANIFEST.MF
INSA - ASI InfoRep : EJB 34/65
Passage d’objets par valeur (4/4)
Côté client
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import HelloWorld. HelloSerializableRemote ;
import HelloWorld.Guy;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
HelloSerializableRemote obj = ( HelloSerializableRemote )context.lookup("ejb :/
HelloSerializable / HelloSerializableBean !HelloWorld. HelloSerializableRemote "
);
System.out.println(obj.sayHello(new Guy(args [0])));
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
}
INSA - ASI InfoRep : EJB 35/65
Callbacks (1/6)
Exemple
Client Serveur
EJB
Programme Guy
File
-
-
Guy
File
-
-
Guy
Callback
Passage d’un stub RMI
INSA - ASI InfoRep : EJB 36/65
Callbacks (2/6)
Côté serveur
Interface : HelloCallbackRemote.java
package HelloWorld;
import javax.ejb.Remote;
import java.rmi. RemoteException ;
@Remote
public i n t e r f a c e HelloCallbackRemote {
p u b l i c String sayHello(Guy g) throws RemoteException ;
}
EJB : HelloCallbackBean.java
package HelloWorld;
import javax.ejb.Stateless;
import java.rmi. RemoteException ;
@Stateless
public c l a s s HelloCallbackBean implements HelloCallbackRemote {
p u b l i c String sayHello(Guy g) throws RemoteException {
return "Hello " + g.getName () + " !";
}
}
INSA - ASI InfoRep : EJB 37/65
Callbacks (3/6)
Interface du stub paramètre
Guy.java
package HelloWorld;
import java.io. Serializable ;
import java.rmi.Remote;
import java.rmi. RemoteException ;
p u b l i c i n t e r f a c e Guy extends Remote , Serializable {
p u b l i c String getName () throws RemoteException ;
p u b l i c void setName(String name) throws RemoteException ;
}
L’interface doit être accessible côté client et côté serveur
INSA - ASI InfoRep : EJB 38/65
Callbacks (4/6)
Déploiement
Arborescence des répertoires
HelloCallback.jar
|_ HelloWorld
| |_ HelloCallbackRemote.class
| |_ HelloCallbackBean.class
| |_ Guy.class
|_ META-INF
|_ MANIFEST.MF
INSA - ASI InfoRep : EJB 39/65
Callbacks (5/6)
Implémentation du stub côté client uniquement
GuyImpl.java
package HelloWorld;
import java.io.*;
p u b l i c c l a s s GuyImpl implements Guy {
p u b l i c GuyImpl(String name) { t h i s .setName(name); }
p u b l i c String getName () {
String name = "";
String fichier = System.getProperty("user.dir") + "/GuyName";
t r y {
BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream (
fichier)));
name = br.readLine ();
br.close ();
} catch ( IOException ioe){ ioe. printStackTrace (); }
return name;
}
p u b l i c void setName(String name) {
String adr = System.getProperty ("user.dir") + "/GuyName";
t r y {
BufferedWriter output=new BufferedWriter (new FileWriter(adr , f a l s e ));
output.write(name);
output.flush ();
output.close ();
} catch ( IOException ioe){ ioe. printStackTrace (); }
}
}
INSA - ASI InfoRep : EJB 40/65
Callbacks (6/6)
Côté client
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import java.rmi.server. UnicastRemoteObject ;
import HelloWorld. HelloCallbackRemote ;
import HelloWorld.Guy;
import HelloWorld.GuyImpl;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
HelloCallbackRemote obj = ( HelloCallbackRemote )context.lookup("ejb :/
HelloCallback / HelloCallbackBean !HelloWorld. HelloCallbackRemote ");
Guy aGuy = new GuyImpl(args [0]) ,
stub = (Guy) UnicastRemoteObject . exportObject (aGuy ,0);
System.out.println(obj.sayHello(stub));
UnicastRemoteObject . unexportObject (aGuy , true );
} catch (Exception e) { System.out.println(e); }
}
}
INSA - ASI InfoRep : EJB 41/65
Les EJB Session avec état (1/6)
Description
EJB Session avec état (Stateful)
Composé d’une ou deux interfaces et d’une classe métier :
Interface de description du contrat pour accès distant
(XXRemote.java)
Utilisation de l’annotation @Remote (importation de
javax.ejb.Remote) juste avant la définition de l’interface
Interface de description du contrat pour accès local
(XXLocal.java)
Utilisation de l’annotation @Local (importation de
javax.ejb.Local) juste avant la définition de l’interface
Classe de définition de la logique métier (XXBean.java)
importation de javax.ejb.Stateful
Utilisation de l’annotation @Stateful avant la définition de la classe
Implémentation des interfaces précédentes
Ne pas être final
INSA - ASI InfoRep : EJB 42/65
Les EJB Session avec état (2/6)
Les EJB session avec état
Méthodes liées au cycle de vie
a
@PostConstruct suivi de la méthode postConstruct
@Init suivi de la méthode init
@PrePassivate suivi de la méthode prePassivate
@PostActivate suivi de la méthode postActivate
@Remove suivi de la méthode remove
@PreDestroy suivi de la méthode preDestroy
a. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_
3-fcs/doc/EJBConcepts9.html
INSA - ASI InfoRep : EJB 43/65
Les EJB Session avec état (3/6)
Côté serveur
CounterStatefulLocal.java
package Stateful;
import javax.ejb.Local;
@Local
public i n t e r f a c e CounterStatefulLocal {
p u b l i c i n t count ();
}
CounterStatefulRemote.java
package Stateful;
import javax.ejb.Remote;
@Remote
public i n t e r f a c e CounterStatefulRemote {
p u b l i c i n t count ();
}
INSA - ASI InfoRep : EJB 44/65
Les EJB Session avec état (4/6)
Côté serveur
CounterStatefulBean.java
package Stateful;
import javax.ejb.Stateful;
@Stateful
public c l a s s CounterStatefulBean implements CounterStatefulLocal , CounterStatefulRemote
{
p r i v a t e i n t counter = 0;
p u b l i c i n t count () {
return ++ t h i s .counter;
}
}
Compteur session sans état
CounterStatelessLocal.class
CounterStatelessRemote.class
CounterStatelessBean.class
INSA - ASI InfoRep : EJB 45/65
Les EJB Session avec état (5/6)
Côté client
Attention !
Pour un EJB Stateful, une session JNDI doit être créée : on ajoute
"?stateful lors de la récupération du stub
Client.java
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
CounterStatelessRemote stateless = ( CounterStatelessRemote )context.lookup("ejb
:/ Counter/ CounterStatelessBean !Stateless. CounterStatelessRemote ");
CounterStatefulRemote stateful = ( CounterStatefulRemote )context.lookup("ejb:/
Counter/ CounterStatefulBean !Stateful. CounterStatefulRemote ?stateful");
System.out.println("Decompte (stateless) : " + stateless.count ());
System.out.println("Decompte (stateless) : " + stateless.count ());
System.out.println("Decompte (stateful) : " + stateful.count ());
System.out.println("Decompte (stateful) : " + stateful.count ());
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
INSA - ASI InfoRep : EJB 46/65
Les EJB Session avec état (6/6)
Sorties
> runClient.sh
Decompte (stateless) : 1
Decompte (stateless) : 1
Decompte (stateful) : 1
Decompte (stateful) : 2
INSA - ASI InfoRep : EJB 47/65
EJB/JSP (1/6)
Archive application J2EE
Arborescence des répertoires
WebCounter -> WebCounter.ear
|_ EJBCounter -> EJBCounter.jar
| |_ WebCounterBean.class
| |_ WebCounterInterface.class
|_ JSPCounter -> JSPCounter.war
|_ WEB-INF
| |_ web.xml
|_ index.jsp
|_ counter.jsp
INSA - ASI InfoRep : EJB 48/65
EJB/JSP (2/6)
Côté serveur
WebCounterInterface.java
package EJBCounter;
p u b l i c i n t e r f a c e WebCounterInterface {
p u b l i c i n t getCounter ();
}
WebCounterBean.java
package EJBCounter;
import javax.ejb.Stateless;
import javax.ejb.Local;
import javax.ejb.Remote;
@Remote(EJBCounter. WebCounterInterface .class)
@Stateless
public c l a s s WebCounterBean implements WebCounterInterface {
p r i v a t e s t a t i c i n t counter = 0;
p u b l i c i n t getCounter () {
WebCounterBean .counter ++;
return WebCounterBean .counter;
}
}
INSA - ASI InfoRep : EJB 49/65
EJB/JSP (3/6)
Côté client
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import EJBCounter. WebCounterInterface ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
WebCounterInterface counter = ( WebCounterInterface )context.lookup("ejb:
WebCounter/EJBCounter/ WebCounterBean !EJBCounter. WebCounterInterface ");
System.out.println("Decompte : " + counter.getCounter ());
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
}
INSA - ASI InfoRep : EJB 50/65
EJB/JSP (4/6)
Archive Web
web.xml
<?xml v e r s i o n ="1.0" encoding="utf -8"?>
<!DOCTYPE web -app
PUBLIC " -//Sun Microsystems , Inc .// DTD Web Application 2.3// EN"
"http: // java.sun.com/dtd/web -app_2_3.dtd">
<web -app >
<display -name >Archive J2EE </display -name >
<description >
Partie Web de ma première application J2EE complète
</description >
</web -app >
INSA - ASI InfoRep : EJB 51/65
EJB/JSP (5/6)
JSP
index.jsp
<%@ page contentType ="text/html; charset=UTF -8" %>
<!DOCTYPE html PUBLIC " -//W3C //DTD XHTML 1.0 Strict //EN"
"http :// www.w3.org/TR/xhtml1/DTD/xhtml1 -strict.dtd">
<html >
<head >
<title >JSP Counter </title >
</head >
<body >
<h1 >Une page JSP classique ... </h1 >
</body >
</html >
Remarque
Appel par http://SERVEUR:PORT/JSPCounter/index.jsp
INSA - ASI InfoRep : EJB 52/65
EJB/JSP (6/6)
Appel externe
counter.jsp
<%@ page contentType ="text/html; charset=UTF -8" %>
<%@ page import ="EJBCounter.WebCounterInterface , javax.naming. InitialContext "%>
<%!
p r i v a t e WebCounterInterface counter = n u l l ;
p u b l i c void jspInit () {
t r y {
counter = ( WebCounterInterface ) InitialContext .doLookup(
"ejb:WebCounter/EJBCounter/ WebCounterBean !EJBCounter. WebCounterInterface ");
} catch (Exception e) {
e. printStackTrace ();
}
}
%>
<html >
<head >
<title >JSP Counter </title >
</head >
<body >
<h1 >Hits: <%= counter.getCounter () %></h1 >
</body >
</html >
INSA - ASI InfoRep : EJB 53/65
Persistance (1/11)
Concepts
Les EJBs entité (Entity)
Le gestionnaire d’entités (entity manager)
détermine l’état de chaque objet :
créé mais non persistant (pas lié à un contexte de persistance)
persistant
détaché (sans lien avec le gestionnaire d’entités)
supprimé
peut être à la charge du conteneur (utilisation direct d’un
EntityManager via @PersistenceContext) ou de l’application
(création d’un EntityManager par l’intermédiaire une fabrique
-EntityManagerFactory- via @PersistenceUnit)
Le contexte de persistance
ensemble d’entités persistantes (par défaut dans une base de données
relationnelles)
INSA - ASI InfoRep : EJB 54/65
Persistance (2/11)
Les EJB entité
La classe représentant l’EJB entité doit
Utiliser les annotations @Entity, @Table et @Column
Posséder un constructeur par défaut en public ou protected
Ne pas être final
Implémenter Serializable si détaché
Être manipulable uniquement via les accesseurs (les attributs sont
private ou protected)
Posséder une clef primaire (annotation @Id) :
Si simple alors du type : type primitif, classe encapsulant type
primitif, String, Date (de java.util ou java.sql)
L’annotation @GeneratedValue permet de générer automatiquement
cette clef primaire
Implémenter hashCode, equals et toString
INSA - ASI InfoRep : EJB 55/65
Persistance (3/11)
Cycle de vie
2
2. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/
doc/EJBConcepts9.html
INSA - ASI InfoRep : EJB 56/65
Persistance (4/11)
EJB Entité
Name.java
package helloWorld;
import javax.persistence .*;
import java.io. Serializable ;
@Entity
@Table(name =" names ")
public c l a s s Name implements Serializable {
@Id
@ GeneratedValue (strategy = GenerationType .IDENTITY)
p r i v a t e i n t id;
@Column(unique = true )
p r i v a t e String name;
p u b l i c Name () { t h i s .name = ""; }
p u b l i c Name (String name) { t h i s .name = name; }
p u b l i c i n t getId () { return t h i s .id; }
p u b l i c void setId ( i n t id) { t h i s .id = id; }
p u b l i c String getName () { return t h i s .name; }
. . .
INSA - ASI InfoRep : EJB 57/65
Persistance (5/11)
EJB Entité
Name.java
. . .
@Override
p u b l i c boolean equals(Object o) {
i f ( t h i s == o)
return true ;
i f (o == n u l l || getClass () != o.getClass ())
return f a l s e ;
Name that = (Name)o;
i f ( t h i s .name != n u l l ? ! t h i s .name.equals(that.name) : that.name != n u l l )
return f a l s e ;
return true ;
}
@Override
p u b l i c i n t hashCode () {
return t h i s .name != n u l l ? t h i s .name.hashCode () : 0;
}
@Override
p u b l i c String toString () {
return t h i s .name;
}
}
INSA - ASI InfoRep : EJB 58/65
Persistance (6/11)
EJB Session sans état
PersistentHelloBean.java
package helloWorld;
import javax.ejb.Stateless;
import javax.persistence .*;
import java.util.Collection;
import java.util.Iterator;
@Stateless
public c l a s s PersistentHelloBean implements PersistentHelloLocal , PersistentHelloRemote
{
@ PersistenceContext (unitName =" nameList ")
EntityManager em;
p u b l i c String sayHello(String s) {
String hello = "Hello " + s + " !";
Collection <Name > nameCollection ;
em.persist(new Name(s));
nameCollection = em.createQuery("from Name n"). getResultList ();
hello += "nListe des personnes déjà passées : ";
f o r (Iterator <Name >names= nameCollection .iterator (); names.hasNext (); ){
hello += " " + names.next ().getName ();
}
return hello;
}
}
INSA - ASI InfoRep : EJB 59/65
Persistance (7/11)
Association à une BD
Tout ORM doit être associé à une BD
Extérieure : Oracle, MySQL, PostgreSQL, etc.
Embarquée : dans l’application J2EE (partie EJB ou web), dans le
serveur d’application (H2, etc.)
Interfacé par JDBC, Hibernate et JTA
INSA - ASI InfoRep : EJB 60/65
Persistance (8/11)
Définition du contexte de persistance
Contexte de persistance : persistence.xml
<persistence version="1.0" xmlns="http :// java.sun.com/xml/ns/persistence"
xmlns:xsi="http :// www.w3.org /2001/ XMLSchema -instance"
xsi: schemaLocation ="http :// java.sun.com/xml/ns/ persistence
http :// java.sun.com/xml/ns/persistence/ persistence_1_0
.xsd">
<persistence -unit name="nameList" transaction -type="JTA">
<jta -data -source >java:jboss/ datasources /nameListDS </jta -data -source >
<properties >
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create -drop"/>
</properties >
</persistence -unit >
</persistence >
INSA - ASI InfoRep : EJB 61/65
Persistance (9/11)
Archive application J2EE
Arborescence des répertoires
persistentHello.jar
|_HelloWorld
| |_ PersistentHelloBean.class
| |_ PersistentHelloLocal.class
| |_ PersistentHelloRemote.class
| |_ Name.class
|_META-INF
|_ persistence.xml
|_ MANIFEST.MF
INSA - ASI InfoRep : EJB 62/65
Persistance (10/11)
JTA/H2
Utilisation (par exemple) de H2 comme BD embarquée
1 Création d’un utilisateur ”Admin” pour administrer JBOSS en mode
console Web
2 Création d’une ”Datasource JDBC”
3 Activer la Datasource
4 Déployer l’archive J2EE
Exemple
Name : ”nameList”
JNDI : ”java :jboss/datasources/nameListDS”
Driver : ”h2”
Connection URL : ”jdbc :h2 :/tmp/BD”
INSA - ASI InfoRep : EJB 63/65
Persistance (11/11)
Côté client
Client.java
import javax.naming.Context;
import javax.naming. InitialContext ;
import java.util.Hashtable;
import helloWorld. PersistentHelloRemote ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c void main(String [] args) {
t r y {
Hashtable jndiProperties = new Hashtable ();
jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
Context context = new InitialContext ( jndiProperties );
PersistentHelloRemote obj = ( PersistentHelloRemote )context.lookup("ejb:/
PersistentHello / PersistentHelloBean !helloWorld. PersistentHelloRemote ");
System.out.println(obj.sayHello(args[args.length -1]));
} catch (Exception e) {
System.out.println(e);
e. printStackTrace ();
}
}
}
INSA - ASI InfoRep : EJB 64/65
Les EJB message
Description
3
Classe représentant l’EJB doit
implémenter l’interface javax.jms.MessageListener (donc
implémenter la méthode public void onMessage(Message m))
utiliser l’annotation @MessageDriven
ne pas être final
3. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/
doc/EJBConcepts9.html
INSA - ASI InfoRep : EJB 65/65
Références
Programmation J2EE, Conteneurs J2EE, servlets, JSP et EJB :
S. Allamaraju, K. Avedal, R.Browett, J. Diamond, J. Griffin, M. Holden, A.
Hoskinson, R. Johson, T. Karsjens, L. Kim, A. Longshaw, T. Myers, A.
Nakimovsky, D. O’Connor, S. Tyagi, G. Van Damme, G. Van Huizen, M.
Wilcox, S. Zeiger
Eyrolles - ISBN : 2-212-09260-1
Enterprise JavaBeans :
Richard Monson-Haefel
O’Reilly 3ème édition - ISBN 0-596-00226-2
JBoss 3.0 deployment and Administration
Meeraj Moidoo Kunnumpurath
Wrox - ISBN 1-86100-812-0

Contenu connexe

Similaire à EJB.pdf

Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Eric Bourdet
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Eric Bourdet
 
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnement
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnementJee005 formation-jee-ejb-3-les-bases-et-perfectionnement
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnementCERTyou Formation
 
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...ENSET, Université Hassan II Casablanca
 
Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Heithem Abbes
 
Développement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EEDéveloppement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EESabri Bouchlema
 
Environnements & Développements
Environnements & DéveloppementsEnvironnements & Développements
Environnements & DéveloppementsPaulin CHOUDJA
 
Introduction à Hibernate p.1
Introduction à Hibernate p.1Introduction à Hibernate p.1
Introduction à Hibernate p.1ATHMAN HAJ-HAMOU
 
Architecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesArchitecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesENSET, Université Hassan II Casablanca
 
Jee004 formation-jee-ejb-3-les-bases
Jee004 formation-jee-ejb-3-les-basesJee004 formation-jee-ejb-3-les-bases
Jee004 formation-jee-ejb-3-les-basesCERTyou Formation
 
Soutenance Stage Licence
Soutenance Stage LicenceSoutenance Stage Licence
Soutenance Stage LicenceMathias Kluba
 

Similaire à EJB.pdf (20)

Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
 
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnement
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnementJee005 formation-jee-ejb-3-les-bases-et-perfectionnement
Jee005 formation-jee-ejb-3-les-bases-et-perfectionnement
 
Java j2ee
Java j2eeJava j2ee
Java j2ee
 
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
 
Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)
 
Développement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EEDéveloppement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EE
 
Environnements & Développements
Environnements & DéveloppementsEnvironnements & Développements
Environnements & Développements
 
J2 ee
J2 eeJ2 ee
J2 ee
 
Introduction à Hibernate p.1
Introduction à Hibernate p.1Introduction à Hibernate p.1
Introduction à Hibernate p.1
 
#2 Architecture OSGi
#2 Architecture OSGi#2 Architecture OSGi
#2 Architecture OSGi
 
Architecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesArchitecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependances
 
Ejb
Ejb Ejb
Ejb
 
Architecture j2 ee
Architecture j2 eeArchitecture j2 ee
Architecture j2 ee
 
Jee004 formation-jee-ejb-3-les-bases
Jee004 formation-jee-ejb-3-les-basesJee004 formation-jee-ejb-3-les-bases
Jee004 formation-jee-ejb-3-les-bases
 
1 Introduction
1 Introduction1 Introduction
1 Introduction
 
Soutenance Stage Licence
Soutenance Stage LicenceSoutenance Stage Licence
Soutenance Stage Licence
 
Mysql
MysqlMysql
Mysql
 
Ejb 3
Ejb 3Ejb 3
Ejb 3
 
Support cours j2_ee
Support cours j2_eeSupport cours j2_ee
Support cours j2_ee
 

EJB.pdf

  • 1. INSA - ASI InfoRep : EJB 1/65 Informatique Répartie Introduction aux EJB Alexandre Pauchet INSA Rouen - Département ASI BO.B.RC.18, pauchet@insa-rouen.fr
  • 2. INSA - ASI InfoRep : EJB 2/65 Plan 1 Introduction 2 Architecture J2EE 3 EJB 4 EJB Session sans état 5 Envoi d’exception 6 Passage d’objets par valeur 7 Callbacks 8 EJB Session avec état 9 EJB/JSP 10 Persistance 11 Les EJB message
  • 3. INSA - ASI InfoRep : EJB 3/65 Introduction (1/3) Historique (rappel) Années 70 : architectures Mainframe (1 tier) Années 80 : architectures 2 tiers (BD) Fin des années 80 : architectures 3 tiers (RPC) Années 90 : architectures 3 tiers Objet (RMI/Corba) Années 00 : architectures orientées services (Web Services) Fin des années 00 : architectures orientées ressources (RESTful)
  • 4. INSA - ASI InfoRep : EJB 4/65 Introduction (2/3) Histoire Aspect programmation Années 70-80 : Programmation procédurale alors que les premiers langages objets datent de la fin des années 60 ! Années 90 : Programmation objet Fin des années 90 : Programmation par composants Les composants peuvent être physiquement distants Si changement, pas besoin de tout recompiler et de tout relinker Bonne programmation objet : seules les interfaces sont connues
  • 5. INSA - ASI InfoRep : EJB 5/65 Introduction (3/3) J2EE Volonté de SUN Cadre de développement par composants avec services J2EE (Java 2 Edition Enterprise), qui propose des API : L’invocation de méthodes distantes : RMI, CORBA, Web Services L’accès aux bases de données relationnelles : JDBC L’accès aux annuaires et services de nommage : JNDI L’utilisation du XML : DOM et SAX HTML dynamique et traitement de requêtes HTTP : JSP et Servlet La gestion du Mail : Java Mail La gestion des composants : EJB La gestion des messages entre composants : Java Message Service La gestion des droits d’accès : Java Authentication and Authorization Service (JAAS)
  • 6. INSA - ASI InfoRep : EJB 6/65 Architecture J2EE (1/4) Description de l’architecture J2EE
  • 7. INSA - ASI InfoRep : EJB 7/65 Architecture J2EE (2/4) Rappels : J2EE et les conteneurs Web La spécification J2EE fournit les éléments suivants pour la conception et la réalisation d’application Web : Servlets Java et JSP Les servlets et JSP constituent les blocs de construction du développement d’applications web avec J2EE En terme J2EE, les servlets et pages JSP sont des composants web Application web Collection de servlets et de pages JSP, d’autres classes annexes ou de bibliothèques de classes, ainsi que des ressources statiques telles que des documents HTML, XHTML ou XML, images, etc. Conteneur web Essentiellement un environnement d’exécution Java pour les applications web Responsable de l’initialisation, de l’invocation et de la gestion de la durée de vie des servlets Java et des pages JSP
  • 8. INSA - ASI InfoRep : EJB 8/65 Architecture J2EE (3/4) Rappels : J2EE et les conteneurs Web Éléments de la spécification J2EE (suite) : structure de paquetage et descripteur de déploiement le descripteur de déploiement est un fichier XML Classes Java Archives Description de déploiement Classes Java Archives Description de déploiement Conteneur web Servlets Page JSP Application web Servlets Page JSP Application web
  • 9. INSA - ASI InfoRep : EJB 9/65 Architecture J2EE (4/4) Rappels : J2EE et les conteneurs Web Exemple de conteneur Web Tomcat http://www.apache.org
  • 10. INSA - ASI InfoRep : EJB 10/65 Les EJB (1/11) Description Un composant EJB est constitué d’une collection de classes/interfaces Java Les classes Java doivent respecter certaines règles (Spécifications) Le composant EJB s’exécute dans un conteneur EJB, qui prend en charge tout ce qui concerne le niveau système Répartition des tâches entre le programmeur d’EJB et le conteneur Les composant EJB fonctionnent avec tout type de client : servlets et JSP clients Java (via RMI) clients et serveur divers (via RMI-IIOP, Services Web) . . . 3 types d’EJB : entité, session, message
  • 11. INSA - ASI InfoRep : EJB 11/65 Les EJB (2/11) Variétés d’EJB : les EJB entité Représentation orientée objet de données dans une base de données Les clients peuvent y accéder en toute sécurité simultanément La durée de vie de l’EJB est exactement identique à celle des données qu’il représente La relation d’un EJB entité avec les données de la base de données peut être gérée par le programmeur : persistance gérée par l’EJB le conteneur : persistance gérée par le conteneur Cette distinction se révélera souvent essentielle du point de vue des performances Cependant on peut utiliser n’importe quel type d’EJB de manière interchangeable dans la conception
  • 12. INSA - ASI InfoRep : EJB 12/65 Les EJB (3/11) Variétés d’EJB : les EJB session Client unique (extension du client sur le serveur) Fournit de la logique métier (calcul d’un taux, panier d’un client, etc.) La durée de vie de l’EJB ne doit pas dépasser celle de son client Représente la logique métier Seuls EJB interfaçable par les clients Les EJB session sans état ne possède aucune information sur son client ex : EJB relatif à une calculatrice Les EJB session avec état peut conserver des informations au nom de son client ex : EJB relatif à un panier d’achat électronique
  • 13. INSA - ASI InfoRep : EJB 13/65 Les EJB (4/11) Variétés d’EJB : les EJB message EJB producteur ou consommateur de messages Utilisation de JMS (le server d’application est un JMS provider, et les EJB sont des JMS client : JMS producer et JMS consumer) Permet l’envoi de messages asynchrones Permet l’envoi multiple (1 → n)
  • 14. INSA - ASI InfoRep : EJB 14/65 Les EJB (5/11) Les conteneurs EJB Conteneur = environnement d’exécution pour un composant Le composant se trouve dans le conteneur Le conteneur fournit des services au composant Conteneur se trouve dans un serveur d’applications qui lui fournit un environnement d’exécution Conteneur EJB web Serveur d’applications Conteneur
  • 15. INSA - ASI InfoRep : EJB 15/65 Les EJB (6/11) Les services des conteneurs EJB Sans écrire une seule ligne de code Persistance. Possibilité pour l’EJB d’être persistant dans une BD Transactions déclaratives. Possibilité de gérer des transactions complexes (sans utiliser l’API JTA -Java Transaction- et JTS -Java Transaction Service-) Mémoire cache. Possibilité d’améliorer les performances Sécurité déclarative. Possibilité de gérer l’accès aux composants Gestion d’erreurs. La spécification EJB définit la manière dont les erreurs affectent les transactions, les résultats au niveau client, la connexion et la restauration des composants Portabilité. EJB = Spécification = possibilité de porter un EJB sur un autre serveur plus puissant
  • 16. INSA - ASI InfoRep : EJB 16/65 Les EJB (7/11) Comment le conteneur fournit-il ces services ? 3 concepts de bases pour les EJB Le concept de contrat Services orthogonaux aux EJB Interposition du conteneur entre le client et l’EJB Contrat Répartition des responsabilités entre chaque couche du logiciel (Client, Conteneur, EJB, Gestionnaire de persistance (≥ 2.0)) Services orthogonaux Le conteneur EJB fournit des services au programmeur Le programmeur de l’EJB n’a plus qu’à respecter les règles pour exploiter automatiquement ces services Ces règles sont spécifiées dans le descripteur de déploiement
  • 17. INSA - ASI InfoRep : EJB 17/65 Les EJB (8/11) Interposition Interposition : RMI et le design pattern Remote Proxy Client Stub RMI Réseau Skeleton RMI Classe d’interposition générée par le conteneur Votre EJB 1 Le client exécute un appel sur un Stub RMI 2 Ce stub RMI assemble et envoie des informations au serveur 3 Le skeleton désassemble les paramètres et les transmets au conteneur EJB 4 Le conteneur examine les références de sécurité de l’appelant de la méthode 5 Le conteneur démarre ou rejoint toute transaction nécessaire 6 Le conteneur exécute tous les appels nécessaires aux fonctions de persistance 7 Le conteneur déclenche diverses méthodes callback pour permettre au composant EJB d’acquérir des ressources 8 La méthode “logique métier” est appelée 9 Le conteneur exécute quelques autres tâches relatives aux transactions, à la persistance, aux méthodes callback 10 Le conteneur renvoie le résultat de la méthode métier ou une exception au client
  • 18. INSA - ASI InfoRep : EJB 18/65 Les EJB (9/11) Annotations Java Intégrées au JDK 1.5, elles permettent d’ajouter des Méta-informations au code (i.e. marquer des éléments Java afin de leur ajouter une propriété) Peuvent être utilisées sur n’importe quel type d’élément Java (package, class, attribut, méthode, paramètre, etc.) Plusieurs annotations peuvent être utilisées sur un même élément Non prises en compte par la JVM (mais présente dans le .class) : il faut écrire du code ou des outils qui utilise ces informations Utilisées à la compilation ou à l’exécution Utilisation : @ suivi du mot-clef correspondant à l’annotation L’API Java 5.0 propose de base 3 annotations : @Deprecated, @Override et @SuppressWarnings Déclaration et création de nouvelles annotations : comme une interface en utilisant le mot-clef @interface (java.lang.annotation.Annotation) Possibilité de passer des informations à une annotation : nom=valeur
  • 19. INSA - ASI InfoRep : EJB 19/65 Les EJB (10/11) Exemple d’annotations Java Exemple p u b l i c @interface MaNouvelleAnnotation { } Exemple @ MaNouvelleAnnotation @ SuppressWarnings (" deprecation ") p u b l i c c l a s s maClasse { @ UneAutreAnnotation (champ =" type ") p u b l i c String texte = "Texte"; @Override @ SuppressWarnings ({" deprecation "," unchecked "}) p u b l i c String toString () { return t h i s .texte; } }
  • 20. INSA - ASI InfoRep : EJB 20/65 Les EJB (11/11) EJB3 et les annotations Les EJB3 utilisent les annotations pour simplifier le code à produire : Moins de code à écrire Génération automatique des descripteurs de déploiement
  • 21. INSA - ASI InfoRep : EJB 21/65 Les EJB Session sans état (1/7) Description EJB Session sans état (Stateless) Composé d’une ou deux interfaces et d’une classe métier : Interface de description du contrat pour accès distant (XXRemote.java) Utilisation de l’annotation @Remote (importation de javax.ejb.Remote) juste avant la définition de l’interface Interface de description du contrat pour accès local (XXLocal.java) Utilisation de l’annotation @Local (importation de javax.ejb.Local) juste avant la définition de l’interface Classe de définition de la logique métier (XXBean.java) Importation de javax.ejb.Stateless Utilisation de l’annotation @Stateless avant la définition de classe Implémentation des interfaces précédentes Ne pas être final
  • 22. INSA - ASI InfoRep : EJB 22/65 Les EJB Session sans état (2/7) Cycle de vie 1 Dans XXXBean.java @PostConstruct suivi de la méthode postConstruct @PreDestroy suivi de la méthode preDestroy 1. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/ doc/EJBConcepts9.html
  • 23. INSA - ASI InfoRep : EJB 23/65 Les EJB Session sans état (3/7) Côté serveur HelloStatelessRemote.java package HelloWorld; import javax.ejb.Remote; @Remote public i n t e r f a c e HelloStatelessRemote { p u b l i c String sayHello(String s); } HelloStatelessLocal.java package HelloWorld; import javax.ejb.Local; @Local public i n t e r f a c e HelloStatelessLocal { p u b l i c String sayHello(String s); }
  • 24. INSA - ASI InfoRep : EJB 24/65 Les EJB Session sans état (4/7) Côté serveur HelloStatelessBean.java package HelloWorld; import javax.ejb.Stateless; @Stateless public c l a s s HelloStatelessBean implements HelloStatelessLocal , HelloStatelessRemote { p u b l i c String sayHello(String s) { return "Hello " + s + " !"; } } @Local et @Remote peuvent être portées par la même interface Il faut au moins une annotation @Local ou @Remote Toutes les annotations peuvent éventuellement être placées directement dans l’EJB. L’interface doit alors être précisé : @Stateless @Remote( NomInterface .class) p u b l i c c l a s s EJBStateless implements NomInterface { ... }
  • 25. INSA - ASI InfoRep : EJB 25/65 Les EJB Session sans état (5/7) Déploiement avec JBoss Compilation et déploiement A la compilation, inclure dans le classpath : JBOSS_DIR/modules/javax/ejb/api/main/jboss-ejb-api_3.1_ spec-1.0.1.Final.jar (JBoss) JBOSS_DIR/modules/system/layers/base/javax/ejb/api/main/ jboss-ejb-api_3.2_spec-1.0.0.Final.jar (WildFly) Mettre dans un .jar Pour déployer, déposer dans le répertoire JBOSS DIR/server/JBOSS MODE/deploy (JBoss < 7) JBOSS DIR/standalone/deployments (JBoss 7 et plus) Arborescence des répertoires HelloStateless.jar |_ HelloWorld | |_ HelloStatelessLocal.class | |_ HelloStatelessBean.class |_ META-INF |_ MANIFEST.MF
  • 26. INSA - ASI InfoRep : EJB 26/65 Les EJB Session sans état (6/7) Côté client Nommage d’un EJB Service de nommage : JNDI Nommage d’un EJB : ejb:AppName(ear)/ModuleName(jar)/BeanName!InterfaceName Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import HelloWorld. HelloStatelessRemote ; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); HelloStatelessRemote obj = ( HelloStatelessRemote )context.lookup("ejb:/ HelloStateless / HelloStatelessBean !HelloWorld. HelloStatelessRemote "); System.out.println(obj.sayHello(args [0])); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } } }
  • 27. INSA - ASI InfoRep : EJB 27/65 Les EJB Session sans état (7/7) Exécution Client À l’exécution, inclure dans le classpath : JBOSS_DIR/bin/client/jboss-client.jar jboss-ejb-client.properties jboss-ejb-client.properties endpoint.name = client -endpoint remote. connectionprovider .create.options.org.xnio.Options. SSL_ENABLED = f a l s e remote. connections = d e f a u l t remote.connection. d e f a u l t .host = localhost remote.connection. d e f a u l t .port = 8080 remote.connection. d e f a u l t .connect.options.org.xnio.Options. SASL_POLICY_NOANONYMOUS = f a l s e
  • 28. INSA - ASI InfoRep : EJB 28/65 Envoi d’exception (1/3) Côté serveur EJB : HelloStatelessBean.java package HelloWorld; import javax.ejb.Stateless; @Stateless public c l a s s HelloStatelessBean implements HelloStatelessRemote { p u b l i c String sayHello(String s) throws ChaineVide { i f (s.length () ==0) { throw new ChaineVide (); } e l s e i f (s.equals("test")) { s = "" + 1/0; } return "Hello " + s + " !"; } }
  • 29. INSA - ASI InfoRep : EJB 29/65 Envoi d’exception (2/3) Côté serveur Exception : ChaineVide.java package HelloWorld; p u b l i c c l a s s ChaineVide extends Exception { p u b l i c ChaineVide (){ super ("String vide !"); } } Interface : HelloStatelessRemote.java package HelloWorld; import javax.ejb.Remote; @Remote public i n t e r f a c e HelloStatelessRemote { p u b l i c String sayHello(String s) throws ChaineVide; }
  • 30. INSA - ASI InfoRep : EJB 30/65 Envoi d’exception (3/3) Côté client Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import HelloWorld. HelloStatelessRemote ; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); HelloStatelessRemote obj = ( HelloStatelessRemote )context.lookup("ejb:/ HelloException / HelloStatelessBean !HelloWorld. HelloStatelessRemote "); i f (args.length >0) System.out.println(obj.sayHello(args [0])); e l s e System.out.println(obj.sayHello("")); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } } }
  • 31. INSA - ASI InfoRep : EJB 31/65 Passage d’objets par valeur (1/4) Côté serveur Interface : HelloSerializableRemote.java package HelloWorld; import javax.ejb.Remote; @Remote public i n t e r f a c e HelloSerializableRemote { p u b l i c String sayHello(Guy g); } EJB : HelloSerializableBean.java package HelloWorld; import javax.ejb.Stateless; @Stateless public c l a s s HelloSerializableBean implements HelloSerializableRemote { p u b l i c String sayHello(Guy g) { return "Hello " + g.getName () + " !"; } }
  • 32. INSA - ASI InfoRep : EJB 32/65 Passage d’objets par valeur (2/4) Objet passé Guy.java package HelloWorld; import java.io. Serializable ; p u b l i c c l a s s Guy implements Serializable { p r i v a t e String name; p u b l i c Guy () { t h i s .name = ""; } p u b l i c Guy(String name) { t h i s .name = name; } p u b l i c String getName () { return t h i s .name; } p u b l i c void setName(String name) { t h i s .name = name; } }
  • 33. INSA - ASI InfoRep : EJB 33/65 Passage d’objets par valeur (3/4) Déploiement Arborescence des répertoires HelloSerializable.jar |_ HelloWorld | |_ HelloSerializableRemote.class | |_ HelloSerializableBean.class | |_ Guy.class |_ META-INF |_ MANIFEST.MF
  • 34. INSA - ASI InfoRep : EJB 34/65 Passage d’objets par valeur (4/4) Côté client Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import HelloWorld. HelloSerializableRemote ; import HelloWorld.Guy; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); HelloSerializableRemote obj = ( HelloSerializableRemote )context.lookup("ejb :/ HelloSerializable / HelloSerializableBean !HelloWorld. HelloSerializableRemote " ); System.out.println(obj.sayHello(new Guy(args [0]))); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } } }
  • 35. INSA - ASI InfoRep : EJB 35/65 Callbacks (1/6) Exemple Client Serveur EJB Programme Guy File - - Guy File - - Guy Callback Passage d’un stub RMI
  • 36. INSA - ASI InfoRep : EJB 36/65 Callbacks (2/6) Côté serveur Interface : HelloCallbackRemote.java package HelloWorld; import javax.ejb.Remote; import java.rmi. RemoteException ; @Remote public i n t e r f a c e HelloCallbackRemote { p u b l i c String sayHello(Guy g) throws RemoteException ; } EJB : HelloCallbackBean.java package HelloWorld; import javax.ejb.Stateless; import java.rmi. RemoteException ; @Stateless public c l a s s HelloCallbackBean implements HelloCallbackRemote { p u b l i c String sayHello(Guy g) throws RemoteException { return "Hello " + g.getName () + " !"; } }
  • 37. INSA - ASI InfoRep : EJB 37/65 Callbacks (3/6) Interface du stub paramètre Guy.java package HelloWorld; import java.io. Serializable ; import java.rmi.Remote; import java.rmi. RemoteException ; p u b l i c i n t e r f a c e Guy extends Remote , Serializable { p u b l i c String getName () throws RemoteException ; p u b l i c void setName(String name) throws RemoteException ; } L’interface doit être accessible côté client et côté serveur
  • 38. INSA - ASI InfoRep : EJB 38/65 Callbacks (4/6) Déploiement Arborescence des répertoires HelloCallback.jar |_ HelloWorld | |_ HelloCallbackRemote.class | |_ HelloCallbackBean.class | |_ Guy.class |_ META-INF |_ MANIFEST.MF
  • 39. INSA - ASI InfoRep : EJB 39/65 Callbacks (5/6) Implémentation du stub côté client uniquement GuyImpl.java package HelloWorld; import java.io.*; p u b l i c c l a s s GuyImpl implements Guy { p u b l i c GuyImpl(String name) { t h i s .setName(name); } p u b l i c String getName () { String name = ""; String fichier = System.getProperty("user.dir") + "/GuyName"; t r y { BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream ( fichier))); name = br.readLine (); br.close (); } catch ( IOException ioe){ ioe. printStackTrace (); } return name; } p u b l i c void setName(String name) { String adr = System.getProperty ("user.dir") + "/GuyName"; t r y { BufferedWriter output=new BufferedWriter (new FileWriter(adr , f a l s e )); output.write(name); output.flush (); output.close (); } catch ( IOException ioe){ ioe. printStackTrace (); } } }
  • 40. INSA - ASI InfoRep : EJB 40/65 Callbacks (6/6) Côté client Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import java.rmi.server. UnicastRemoteObject ; import HelloWorld. HelloCallbackRemote ; import HelloWorld.Guy; import HelloWorld.GuyImpl; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); HelloCallbackRemote obj = ( HelloCallbackRemote )context.lookup("ejb :/ HelloCallback / HelloCallbackBean !HelloWorld. HelloCallbackRemote "); Guy aGuy = new GuyImpl(args [0]) , stub = (Guy) UnicastRemoteObject . exportObject (aGuy ,0); System.out.println(obj.sayHello(stub)); UnicastRemoteObject . unexportObject (aGuy , true ); } catch (Exception e) { System.out.println(e); } } }
  • 41. INSA - ASI InfoRep : EJB 41/65 Les EJB Session avec état (1/6) Description EJB Session avec état (Stateful) Composé d’une ou deux interfaces et d’une classe métier : Interface de description du contrat pour accès distant (XXRemote.java) Utilisation de l’annotation @Remote (importation de javax.ejb.Remote) juste avant la définition de l’interface Interface de description du contrat pour accès local (XXLocal.java) Utilisation de l’annotation @Local (importation de javax.ejb.Local) juste avant la définition de l’interface Classe de définition de la logique métier (XXBean.java) importation de javax.ejb.Stateful Utilisation de l’annotation @Stateful avant la définition de la classe Implémentation des interfaces précédentes Ne pas être final
  • 42. INSA - ASI InfoRep : EJB 42/65 Les EJB Session avec état (2/6) Les EJB session avec état Méthodes liées au cycle de vie a @PostConstruct suivi de la méthode postConstruct @Init suivi de la méthode init @PrePassivate suivi de la méthode prePassivate @PostActivate suivi de la méthode postActivate @Remove suivi de la méthode remove @PreDestroy suivi de la méthode preDestroy a. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_ 3-fcs/doc/EJBConcepts9.html
  • 43. INSA - ASI InfoRep : EJB 43/65 Les EJB Session avec état (3/6) Côté serveur CounterStatefulLocal.java package Stateful; import javax.ejb.Local; @Local public i n t e r f a c e CounterStatefulLocal { p u b l i c i n t count (); } CounterStatefulRemote.java package Stateful; import javax.ejb.Remote; @Remote public i n t e r f a c e CounterStatefulRemote { p u b l i c i n t count (); }
  • 44. INSA - ASI InfoRep : EJB 44/65 Les EJB Session avec état (4/6) Côté serveur CounterStatefulBean.java package Stateful; import javax.ejb.Stateful; @Stateful public c l a s s CounterStatefulBean implements CounterStatefulLocal , CounterStatefulRemote { p r i v a t e i n t counter = 0; p u b l i c i n t count () { return ++ t h i s .counter; } } Compteur session sans état CounterStatelessLocal.class CounterStatelessRemote.class CounterStatelessBean.class
  • 45. INSA - ASI InfoRep : EJB 45/65 Les EJB Session avec état (5/6) Côté client Attention ! Pour un EJB Stateful, une session JNDI doit être créée : on ajoute "?stateful lors de la récupération du stub Client.java p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); CounterStatelessRemote stateless = ( CounterStatelessRemote )context.lookup("ejb :/ Counter/ CounterStatelessBean !Stateless. CounterStatelessRemote "); CounterStatefulRemote stateful = ( CounterStatefulRemote )context.lookup("ejb:/ Counter/ CounterStatefulBean !Stateful. CounterStatefulRemote ?stateful"); System.out.println("Decompte (stateless) : " + stateless.count ()); System.out.println("Decompte (stateless) : " + stateless.count ()); System.out.println("Decompte (stateful) : " + stateful.count ()); System.out.println("Decompte (stateful) : " + stateful.count ()); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } }
  • 46. INSA - ASI InfoRep : EJB 46/65 Les EJB Session avec état (6/6) Sorties > runClient.sh Decompte (stateless) : 1 Decompte (stateless) : 1 Decompte (stateful) : 1 Decompte (stateful) : 2
  • 47. INSA - ASI InfoRep : EJB 47/65 EJB/JSP (1/6) Archive application J2EE Arborescence des répertoires WebCounter -> WebCounter.ear |_ EJBCounter -> EJBCounter.jar | |_ WebCounterBean.class | |_ WebCounterInterface.class |_ JSPCounter -> JSPCounter.war |_ WEB-INF | |_ web.xml |_ index.jsp |_ counter.jsp
  • 48. INSA - ASI InfoRep : EJB 48/65 EJB/JSP (2/6) Côté serveur WebCounterInterface.java package EJBCounter; p u b l i c i n t e r f a c e WebCounterInterface { p u b l i c i n t getCounter (); } WebCounterBean.java package EJBCounter; import javax.ejb.Stateless; import javax.ejb.Local; import javax.ejb.Remote; @Remote(EJBCounter. WebCounterInterface .class) @Stateless public c l a s s WebCounterBean implements WebCounterInterface { p r i v a t e s t a t i c i n t counter = 0; p u b l i c i n t getCounter () { WebCounterBean .counter ++; return WebCounterBean .counter; } }
  • 49. INSA - ASI InfoRep : EJB 49/65 EJB/JSP (3/6) Côté client Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import EJBCounter. WebCounterInterface ; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); WebCounterInterface counter = ( WebCounterInterface )context.lookup("ejb: WebCounter/EJBCounter/ WebCounterBean !EJBCounter. WebCounterInterface "); System.out.println("Decompte : " + counter.getCounter ()); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } } }
  • 50. INSA - ASI InfoRep : EJB 50/65 EJB/JSP (4/6) Archive Web web.xml <?xml v e r s i o n ="1.0" encoding="utf -8"?> <!DOCTYPE web -app PUBLIC " -//Sun Microsystems , Inc .// DTD Web Application 2.3// EN" "http: // java.sun.com/dtd/web -app_2_3.dtd"> <web -app > <display -name >Archive J2EE </display -name > <description > Partie Web de ma première application J2EE complète </description > </web -app >
  • 51. INSA - ASI InfoRep : EJB 51/65 EJB/JSP (5/6) JSP index.jsp <%@ page contentType ="text/html; charset=UTF -8" %> <!DOCTYPE html PUBLIC " -//W3C //DTD XHTML 1.0 Strict //EN" "http :// www.w3.org/TR/xhtml1/DTD/xhtml1 -strict.dtd"> <html > <head > <title >JSP Counter </title > </head > <body > <h1 >Une page JSP classique ... </h1 > </body > </html > Remarque Appel par http://SERVEUR:PORT/JSPCounter/index.jsp
  • 52. INSA - ASI InfoRep : EJB 52/65 EJB/JSP (6/6) Appel externe counter.jsp <%@ page contentType ="text/html; charset=UTF -8" %> <%@ page import ="EJBCounter.WebCounterInterface , javax.naming. InitialContext "%> <%! p r i v a t e WebCounterInterface counter = n u l l ; p u b l i c void jspInit () { t r y { counter = ( WebCounterInterface ) InitialContext .doLookup( "ejb:WebCounter/EJBCounter/ WebCounterBean !EJBCounter. WebCounterInterface "); } catch (Exception e) { e. printStackTrace (); } } %> <html > <head > <title >JSP Counter </title > </head > <body > <h1 >Hits: <%= counter.getCounter () %></h1 > </body > </html >
  • 53. INSA - ASI InfoRep : EJB 53/65 Persistance (1/11) Concepts Les EJBs entité (Entity) Le gestionnaire d’entités (entity manager) détermine l’état de chaque objet : créé mais non persistant (pas lié à un contexte de persistance) persistant détaché (sans lien avec le gestionnaire d’entités) supprimé peut être à la charge du conteneur (utilisation direct d’un EntityManager via @PersistenceContext) ou de l’application (création d’un EntityManager par l’intermédiaire une fabrique -EntityManagerFactory- via @PersistenceUnit) Le contexte de persistance ensemble d’entités persistantes (par défaut dans une base de données relationnelles)
  • 54. INSA - ASI InfoRep : EJB 54/65 Persistance (2/11) Les EJB entité La classe représentant l’EJB entité doit Utiliser les annotations @Entity, @Table et @Column Posséder un constructeur par défaut en public ou protected Ne pas être final Implémenter Serializable si détaché Être manipulable uniquement via les accesseurs (les attributs sont private ou protected) Posséder une clef primaire (annotation @Id) : Si simple alors du type : type primitif, classe encapsulant type primitif, String, Date (de java.util ou java.sql) L’annotation @GeneratedValue permet de générer automatiquement cette clef primaire Implémenter hashCode, equals et toString
  • 55. INSA - ASI InfoRep : EJB 55/65 Persistance (3/11) Cycle de vie 2 2. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/ doc/EJBConcepts9.html
  • 56. INSA - ASI InfoRep : EJB 56/65 Persistance (4/11) EJB Entité Name.java package helloWorld; import javax.persistence .*; import java.io. Serializable ; @Entity @Table(name =" names ") public c l a s s Name implements Serializable { @Id @ GeneratedValue (strategy = GenerationType .IDENTITY) p r i v a t e i n t id; @Column(unique = true ) p r i v a t e String name; p u b l i c Name () { t h i s .name = ""; } p u b l i c Name (String name) { t h i s .name = name; } p u b l i c i n t getId () { return t h i s .id; } p u b l i c void setId ( i n t id) { t h i s .id = id; } p u b l i c String getName () { return t h i s .name; } . . .
  • 57. INSA - ASI InfoRep : EJB 57/65 Persistance (5/11) EJB Entité Name.java . . . @Override p u b l i c boolean equals(Object o) { i f ( t h i s == o) return true ; i f (o == n u l l || getClass () != o.getClass ()) return f a l s e ; Name that = (Name)o; i f ( t h i s .name != n u l l ? ! t h i s .name.equals(that.name) : that.name != n u l l ) return f a l s e ; return true ; } @Override p u b l i c i n t hashCode () { return t h i s .name != n u l l ? t h i s .name.hashCode () : 0; } @Override p u b l i c String toString () { return t h i s .name; } }
  • 58. INSA - ASI InfoRep : EJB 58/65 Persistance (6/11) EJB Session sans état PersistentHelloBean.java package helloWorld; import javax.ejb.Stateless; import javax.persistence .*; import java.util.Collection; import java.util.Iterator; @Stateless public c l a s s PersistentHelloBean implements PersistentHelloLocal , PersistentHelloRemote { @ PersistenceContext (unitName =" nameList ") EntityManager em; p u b l i c String sayHello(String s) { String hello = "Hello " + s + " !"; Collection <Name > nameCollection ; em.persist(new Name(s)); nameCollection = em.createQuery("from Name n"). getResultList (); hello += "nListe des personnes déjà passées : "; f o r (Iterator <Name >names= nameCollection .iterator (); names.hasNext (); ){ hello += " " + names.next ().getName (); } return hello; } }
  • 59. INSA - ASI InfoRep : EJB 59/65 Persistance (7/11) Association à une BD Tout ORM doit être associé à une BD Extérieure : Oracle, MySQL, PostgreSQL, etc. Embarquée : dans l’application J2EE (partie EJB ou web), dans le serveur d’application (H2, etc.) Interfacé par JDBC, Hibernate et JTA
  • 60. INSA - ASI InfoRep : EJB 60/65 Persistance (8/11) Définition du contexte de persistance Contexte de persistance : persistence.xml <persistence version="1.0" xmlns="http :// java.sun.com/xml/ns/persistence" xmlns:xsi="http :// www.w3.org /2001/ XMLSchema -instance" xsi: schemaLocation ="http :// java.sun.com/xml/ns/ persistence http :// java.sun.com/xml/ns/persistence/ persistence_1_0 .xsd"> <persistence -unit name="nameList" transaction -type="JTA"> <jta -data -source >java:jboss/ datasources /nameListDS </jta -data -source > <properties > <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="create -drop"/> </properties > </persistence -unit > </persistence >
  • 61. INSA - ASI InfoRep : EJB 61/65 Persistance (9/11) Archive application J2EE Arborescence des répertoires persistentHello.jar |_HelloWorld | |_ PersistentHelloBean.class | |_ PersistentHelloLocal.class | |_ PersistentHelloRemote.class | |_ Name.class |_META-INF |_ persistence.xml |_ MANIFEST.MF
  • 62. INSA - ASI InfoRep : EJB 62/65 Persistance (10/11) JTA/H2 Utilisation (par exemple) de H2 comme BD embarquée 1 Création d’un utilisateur ”Admin” pour administrer JBOSS en mode console Web 2 Création d’une ”Datasource JDBC” 3 Activer la Datasource 4 Déployer l’archive J2EE Exemple Name : ”nameList” JNDI : ”java :jboss/datasources/nameListDS” Driver : ”h2” Connection URL : ”jdbc :h2 :/tmp/BD”
  • 63. INSA - ASI InfoRep : EJB 63/65 Persistance (11/11) Côté client Client.java import javax.naming.Context; import javax.naming. InitialContext ; import java.util.Hashtable; import helloWorld. PersistentHelloRemote ; p u b l i c c l a s s Client { p u b l i c s t a t i c void main(String [] args) { t r y { Hashtable jndiProperties = new Hashtable (); jndiProperties .put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming"); Context context = new InitialContext ( jndiProperties ); PersistentHelloRemote obj = ( PersistentHelloRemote )context.lookup("ejb:/ PersistentHello / PersistentHelloBean !helloWorld. PersistentHelloRemote "); System.out.println(obj.sayHello(args[args.length -1])); } catch (Exception e) { System.out.println(e); e. printStackTrace (); } } }
  • 64. INSA - ASI InfoRep : EJB 64/65 Les EJB message Description 3 Classe représentant l’EJB doit implémenter l’interface javax.jms.MessageListener (donc implémenter la méthode public void onMessage(Message m)) utiliser l’annotation @MessageDriven ne pas être final 3. extrait du tutoriel de SUN : http://java.sun.com/j2ee/tutorial/1_3-fcs/ doc/EJBConcepts9.html
  • 65. INSA - ASI InfoRep : EJB 65/65 Références Programmation J2EE, Conteneurs J2EE, servlets, JSP et EJB : S. Allamaraju, K. Avedal, R.Browett, J. Diamond, J. Griffin, M. Holden, A. Hoskinson, R. Johson, T. Karsjens, L. Kim, A. Longshaw, T. Myers, A. Nakimovsky, D. O’Connor, S. Tyagi, G. Van Damme, G. Van Huizen, M. Wilcox, S. Zeiger Eyrolles - ISBN : 2-212-09260-1 Enterprise JavaBeans : Richard Monson-Haefel O’Reilly 3ème édition - ISBN 0-596-00226-2 JBoss 3.0 deployment and Administration Meeraj Moidoo Kunnumpurath Wrox - ISBN 1-86100-812-0