EJB File - Plateforme e-learning Moodle de l`INSA de Rouen

Transcription

EJB File - Plateforme e-learning Moodle de l`INSA de Rouen
INSA - ASI
InfoRep : EJB
Informatique Répartie
Introduction aux EJB
Alexandre Pauchet
INSA Rouen - Département ASI
BO.B.RC.18, [email protected]
1/65
INSA - ASI
InfoRep : EJB
2/65
Plan
1
2
3
4
5
6
Introduction
7
Callbacks
8
EJB Session avec état
9
EJB/JSP
10
Persistance
11
Les EJB message
Architecture J2EE
EJB
EJB Session sans état
Envoi d’exception
Passage d’objets par valeur
INSA - ASI
InfoRep : EJB
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)
3/65
INSA - ASI
InfoRep : EJB
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
4/65
INSA - ASI
InfoRep : EJB
Introduction
5/65
(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
Architecture J2EE
InfoRep : EJB
(1/4)
Description de l’architecture J2EE
6/65
INSA - ASI
InfoRep : EJB
Architecture J2EE
7/65
(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
Architecture J2EE
8/65
(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
Application web
Application web
Servlets
Servlets
Page JSP
Page JSP
Classes Java
Archives
Classes Java
Archives
Description de déploiement
Description de déploiement
Conteneur web
INSA - ASI
InfoRep : EJB
Architecture J2EE
(4/4)
Rappels : J2EE et les conteneurs Web
Exemple de conteneur Web
Tomcat
http://www.apache.org
9/65
INSA - ASI
InfoRep : EJB
Les EJB
10/65
(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
Les EJB
11/65
(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
Les EJB
12/65
(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
Les EJB
13/65
(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
Les EJB
14/65
(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
web
Conteneur
EJB
Serveur d’applications
INSA - ASI
InfoRep : EJB
Les EJB
15/65
(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
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
16/65
INSA - ASI
InfoRep : EJB
Les EJB
17/65
(8/11)
Interposition
Votre EJB
Classe d’interposition
générée par le
conteneur
Skeleton RMI
Réseau
Stub RMI
Client
Interposition : RMI et le design pattern Remote Proxy
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
Les EJB
18/65
(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
Les EJB
(10/11)
Exemple d’annotations Java
Exemple
p u b l i c @ interface M a N o u v e l l e A n n o t a t i o n {
}
Exemple
@ MaNouvelleAnnotation
@ S u p p r e s s Warnings (" deprecation ")
p u b l i c c l a s s maClasse {
@ U n e A u t re An n ot a ti on ( champ =" type ")
p u b l i c String texte = " Texte " ;
@ Override
@ S u p p r e ssWarnings ({" deprecation " ," unchecked "})
p u b l i c String toString () {
r e t u r n t h i s . texte ;
}
}
19/65
INSA - ASI
InfoRep : EJB
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
20/65
INSA - ASI
InfoRep : EJB
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
21/65
INSA - ASI
InfoRep : EJB
Les EJB Session sans état
22/65
(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
Les EJB Session sans état
Côté serveur
HelloStatelessRemote.java
package HelloWorld ;
i m p o r t javax . ejb . Remote ;
@ Remote
public i n t e r f a c e H e l l o S t a t e l e s s R e m o t e {
p u b l i c String sayHello ( String s ) ;
}
HelloStatelessLocal.java
package HelloWorld ;
i m p o r t javax . ejb . Local ;
@ Local
public i n t e r f a c e H e l l o St a t e l e s s L oc a l {
p u b l i c String sayHello ( String s ) ;
}
(3/7)
23/65
INSA - ASI
InfoRep : EJB
Les EJB Session sans état
(4/7)
Côté serveur
HelloStatelessBean.java
package HelloWorld ;
i m p o r t javax . ejb . Stateless ;
@ Stateless
public c l a s s H el l oS ta t el e ss Be a n i m p l e m e n t s HelloStatelessLocal , H e l l o S t a t e l e s s R e m o t e {
p u b l i c String sayHello ( String s ) {
r e t u r n " 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 i m p l e m e n t s NomInterface {
...
}
24/65
INSA - ASI
InfoRep : EJB
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
25/65
INSA - ASI
InfoRep : EJB
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
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
HelloWorld . H e l l o S t a t e l e s s R e m o t e ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndi Properties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
H e l l o S t a t e l e s s R e m o t e obj = ( H e l l o S t a t e l e s s R e m o t e ) context . lookup ( " ejb :/
HelloStateless / He l lo St a te le s sB e an ! HelloWorld . H e l l o S t a t e l e s s R e m o t e " ) ;
System . out . println ( obj . sayHello ( args [0]) ) ;
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . p ri ntStackTrace () ;
}
}
}
26/65
INSA - ASI
InfoRep : EJB
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 . c o n n e c t io np r ov id e r . 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 . S A S L _ P O L I C Y _ N O A N O N Y M O U S =
false
27/65
INSA - ASI
Envoi d’exception
InfoRep : EJB
(1/3)
Côté serveur
EJB : HelloStatelessBean.java
package HelloWorld ;
i m p o r t javax . ejb . Stateless ;
@ Stateless
public c l a s s H el l oS ta t el e ss Be a n i m p l e m e n t s H e l l o S t a t e l e s s R e m o t e {
p u b l i c String sayHello ( String s ) t h r o w s ChaineVide {
i f ( s . length () ==0) {
throw new ChaineVide () ;
}
e l s e i f ( s . equals ( " test " ) ) {
s = " " + 1/0;
}
r e t u r n " Hello " + s + " ! " ;
}
}
28/65
INSA - ASI
Envoi d’exception
InfoRep : EJB
(2/3)
Côté serveur
Exception : ChaineVide.java
package HelloWorld ;
p u b l i c c l a s s ChaineVide e x t e n d s Exception {
p u b l i c ChaineVide () {
s u p e r ( " String vide ! " ) ;
}
}
Interface : HelloStatelessRemote.java
package HelloWorld ;
i m p o r t javax . ejb . Remote ;
@ Remote
public i n t e r f a c e H e l l o S t a t e l e s s R e m o t e {
p u b l i c String sayHello ( String s ) t h r o w s ChaineVide ;
}
29/65
INSA - ASI
InfoRep : EJB
Envoi d’exception
(3/3)
Côté client
Client.java
import
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
HelloWorld . H e l l o S t a t e l e s s R e m o t e ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndi Properties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
H e l l o S t a t e l e s s R e m o t e obj = ( H e l l o S t a t e l e s s R e m o t e ) context . lookup ( " ejb :/
HelloException / He l lo St a te le s sB e an ! HelloWorld . H e l l o S t a t e l e s s R e m o t e " ) ;
i f ( args . length >0)
System . out . println ( obj . sayHello ( args [0]) ) ;
else
System . out . println ( obj . sayHello ( " " ) ) ;
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . p ri ntStackTrace () ;
}
}
}
30/65
INSA - ASI
InfoRep : EJB
Passage d’objets par valeur
(1/4)
Côté serveur
Interface : HelloSerializableRemote.java
package HelloWorld ;
i m p o r t javax . ejb . Remote ;
@ Remote
public i n t e r f a c e H e l l o S e r i a l i z a b l e R e m o t e {
p u b l i c String sayHello ( Guy g ) ;
}
EJB : HelloSerializableBean.java
package HelloWorld ;
i m p o r t javax . ejb . Stateless ;
@ Stateless
public c l a s s H e l l o S e r i a l i z a b l e B e a n i m p l e m e n t s H e l l o S e r i a l i z a b l e R e m o t e {
p u b l i c String sayHello ( Guy g ) {
r e t u r n " Hello " + g . getName () + " ! " ;
}
}
31/65
INSA - ASI
InfoRep : EJB
Passage d’objets par valeur
(2/4)
Objet passé
Guy.java
package HelloWorld ;
i m p o r t java . io . Serializable ;
p u b l i c c l a s s Guy i m p l e m e n t s 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 () {
r e t u r n t h i s . name ;
}
p u b l i c v o i d setName ( String name ) {
t h i s . name = name ;
}
}
32/65
INSA - ASI
InfoRep : EJB
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
33/65
INSA - ASI
InfoRep : EJB
Passage d’objets par valeur
34/65
(4/4)
Côté client
Client.java
import
import
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
HelloWorld . H e l l o S e r i a l i z a b l e R e m o t e ;
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 v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndi Properties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
H e l l o S e r i a l i z a b l e R e m o t e obj = ( H e l l o S e r i a l i z a b l e R e m o t e ) context . lookup ( " ejb :/
He llo Seri ali zab le / H e l l o S e r i a l i z a b l e B e a n ! HelloWorld . H e l l o S e r i a l i z a b l e R e m o t e "
);
System . out . println ( obj . sayHello (new Guy ( args [0]) ) ) ;
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . p ri ntStackTrace () ;
}
}
}
INSA - ASI
Callbacks
InfoRep : EJB
35/65
(1/6)
Exemple
Client
Programme
Serveur
Guy
EJB
Guy
Guy
File
-
File
-
Callback
Passage d’un stub RMI
INSA - ASI
Callbacks
InfoRep : EJB
(2/6)
Côté serveur
Interface : HelloCallbackRemote.java
package HelloWorld ;
i m p o r t javax . ejb . Remote ;
i m p o r t java . rmi . RemoteException ;
@ Remote
public i n t e r f a c e H e l l o Ca l l b a c k R e mo t e {
p u b l i c String sayHello ( Guy g ) t h r o w s RemoteException ;
}
EJB : HelloCallbackBean.java
package HelloWorld ;
i m p o r t javax . ejb . Stateless ;
i m p o r t java . rmi . RemoteException ;
@ Stateless
public c l a s s He llo Cal lbac kBe an i m p l e m e n t s H e l l o Ca l l b a c k R e mo t e {
p u b l i c String sayHello ( Guy g ) t h r o w s RemoteException {
r e t u r n " Hello " + g . getName () + " ! " ;
}
}
36/65
INSA - ASI
Callbacks
InfoRep : EJB
(3/6)
Interface du stub paramètre
Guy.java
package HelloWorld ;
i m p o r t java . io . Serializable ;
i m p o r t java . rmi . Remote ;
i m p o r t java . rmi . RemoteException ;
p u b l i c i n t e r f a c e Guy e x t e n d s Remote , Serializable {
p u b l i c String getName () t h r o w s RemoteException ;
p u b l i c v o i d setName ( String name ) t h r o w s RemoteException ;
}
L’interface doit être accessible côté client et côté serveur
37/65
INSA - ASI
InfoRep : EJB
Callbacks
(4/6)
Déploiement
Arborescence des répertoires
HelloCallback.jar
|_ HelloWorld
|
|_ HelloCallbackRemote.class
|
|_ HelloCallbackBean.class
|
|_ Guy.class
|_ META-INF
|_ MANIFEST.MF
38/65
INSA - ASI
Callbacks
InfoRep : EJB
39/65
(5/6)
Implémentation du stub côté client uniquement
GuyImpl.java
package HelloWorld ;
i m p o r t java . io .*;
p u b l i c c l a s s GuyImpl i m p l e m e n t s 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 " ;
try {
Buffe redReader br = new BufferedReader (new In put Str eamR ead er (new FileInputStream (
fichier ) ) ) ;
name = br . readLine () ;
br . close () ;
} c a t c h ( IOException ioe ) { ioe . printStackTrace () ; }
r e t u r n name ;
}
p u b l i c v o i d setName ( String name ) {
String adr = System . getProperty ( " user . dir " ) + " / GuyName " ;
try {
Buffe redWriter output =new BufferedWriter (new FileWriter ( adr , f a l s e ) ) ;
output . write ( name ) ;
output . flush () ;
output . close () ;
} c a t c h ( IOException ioe ) { ioe . printStackTrace () ; }
}
}
INSA - ASI
InfoRep : EJB
Callbacks
(6/6)
Côté client
Client.java
import
import
import
import
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
java . rmi . server . U n i c a s t R em o t e O b j e c t ;
HelloWorld . H e ll o C a l l b a c kR e m o t e ;
HelloWorld . Guy ;
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 v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndiProperties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
H e l l oC a l l b a c k R em o t e obj = ( H el l o C a l l b a ck R e m o t e ) context . lookup ( " ejb :/
HelloCallback / Hel loC all back Bea n ! HelloWorld . He l l o C a l l b ac k R e m o t e " ) ;
Guy aGuy = new GuyImpl ( args [0]) ,
stub = ( Guy ) U n i c a st R e m o t e O b je c t . exportObject ( aGuy ,0) ;
System . out . println ( obj . sayHello ( stub ) ) ;
U n i c as t R e m o t e O bj e c t . unexportObject ( aGuy , t r u e ) ;
} c a t c h ( Exception e ) { System . out . println ( e ) ; }
}
}
40/65
INSA - ASI
InfoRep : EJB
Les EJB Session avec état
41/65
(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
Les EJB Session avec état
42/65
(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
Les EJB Session avec état
(3/6)
Côté serveur
CounterStatefulLocal.java
package Stateful ;
i m p o r t javax . ejb . Local ;
@ Local
public i n t e r f a c e C o u n t e r S t a t e f u l L o c a l {
p u b l i c i n t count () ;
}
CounterStatefulRemote.java
package Stateful ;
i m p o r t javax . ejb . Remote ;
@ Remote
public i n t e r f a c e C o u n t e r S t a t e f u l R e m o t e {
p u b l i c i n t count () ;
}
43/65
INSA - ASI
InfoRep : EJB
Les EJB Session avec état
44/65
(4/6)
Côté serveur
CounterStatefulBean.java
package Stateful ;
i m p o r t javax . ejb . Stateful ;
@ Stateful
public c l a s s C o u n te r S t a t e f u l Be a n i m p l e m e n t s CounterStatefulLocal , C o u n t e r S t a t e f u l R e m o t e
{
p r i v a t e i n t counter = 0;
p u b l i c i n t count () {
r e t u r n ++ t h i s . counter ;
}
}
Compteur session sans état
CounterStatelessLocal.class
CounterStatelessRemote.class
CounterStatelessBean.class
INSA - ASI
InfoRep : EJB
Les EJB Session avec état
45/65
(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 v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndiProperties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
C o u n t e r S t a t e l e s s R e m o t e stateless = ( C o u n t e r S t a t e l e s s R e m o t e ) context . lookup ( " ejb
:/ Counter / C o u n t e r S t a t e l e s s B e a n ! Stateless . C o u n t e r S t a t e l e s s R e m o t e " ) ;
C o u n t e r S t a t e f u l R e m o t e stateful = ( C o u n t e r S t a t e f u l R e m o t e ) context . lookup ( " ejb :/
Counter / C o un t e r S t a t e fu l B e a n ! Stateful . C o u n t e r S t a t e f u l R e m o t e ? stateful " ) ;
System . out . println ( " Decompte
System . out . println ( " Decompte
System . out . println ( " Decompte
System . out . println ( " Decompte
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . pr intStackTrace () ;
}
}
( stateless ) : " + stateless . count () ) ;
( stateless ) : " + stateless . count () ) ;
( stateful ) : " + stateful . count () ) ;
( stateful ) : " + stateful . count () ) ;
INSA - ASI
InfoRep : EJB
Les EJB Session avec état
(6/6)
Sorties
> runClient.sh
Decompte (stateless) : 1
Decompte (stateless) : 1
Decompte (stateful) : 1
Decompte (stateful) : 2
46/65
INSA - ASI
InfoRep : EJB
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
47/65
INSA - ASI
EJB/JSP
InfoRep : EJB
(2/6)
Côté serveur
WebCounterInterface.java
package EJBCounter ;
p u b l i c i n t e r f a c e W e b C o un t e r I n t e r fa c e {
p u b l i c i n t getCounter () ;
}
WebCounterBean.java
package EJBCounter ;
i m p o r t javax . ejb . Stateless ;
i m p o r t javax . ejb . Local ;
i m p o r t javax . ejb . Remote ;
@ Remote ( EJBCounter . W e b Co u n t e r I n t er f a c e . class )
@Stateless
public c l a s s WebCounterBean i m p l e m e n t s W e b C ou n t e r I n t e rf a c e {
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 () {
WebC ounterBean . counter ++;
r e t u r n WebCounterBean . counter ;
}
}
48/65
INSA - ASI
InfoRep : EJB
EJB/JSP
(3/6)
Côté client
Client.java
import
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
EJBCounter . W e bC o u n t e r I n te r f a c e ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndiProperties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
W e b C ou n t e r I n t e rf a c e counter = ( W e b C o u n t e rI n t e r f a c e ) context . lookup ( " ejb :
WebCounter / EJBCounter / WebCounterBean ! EJBCounter . We b C o u n t e r I nt e r f a c e " ) ;
System . out . println ( " Decompte : " + counter . getCounter () ) ;
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . pr intStackTrace () ;
}
}
}
49/65
INSA - ASI
EJB/JSP
InfoRep : EJB
(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 >
50/65
INSA - ASI
EJB/JSP
InfoRep : EJB
(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
51/65
INSA - ASI
EJB/JSP
InfoRep : EJB
(6/6)
Appel externe
counter.jsp
<% @ page contentType = " text / html ; charset = UTF -8 " % >
<% @ page i m p o r t = " EJBCounter . WebCounterInterface , javax . naming . InitialContext " % >
<%!
p r i v a t e W e b C o u n t e r I n t e r fa c e counter = n u l l ;
p u b l i c v o i d jspInit () {
try {
counter = ( W e b C ou n t e r I n t e rf a c e ) InitialContext . doLookup (
" ejb : WebCounter / EJBCounter / WebCounterBean ! EJBCounter . W e b C o u nt e r I n t e r f ac e " ) ;
} c a t c h ( Exception e ) {
e . pr i nt StackTrace () ;
}
}
%>
< html >
< head >
< title > JSP Counter </ title >
</ head >
< body >
<h1 > Hits : <%= counter . getCounter () % > </ h1 >
</ body >
</ html >
52/65
INSA - ASI
InfoRep : EJB
Persistance
53/65
(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
Persistance
54/65
(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
Persistance
InfoRep : EJB
55/65
(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
Persistance
InfoRep : EJB
(4/11)
EJB Entité
Name.java
package helloWorld ;
i m p o r t javax . persistence .*;
i m p o r t java . io . Serializable ;
@ Entity
@Table ( name =" names ")
public c l a s s Name i m p l e m e n t s Serializable {
@ Id
@ Ge neratedV alue ( strategy = GenerationType . IDENTITY )
p r i v a t e i n t id ;
@ Column ( unique = t r u e )
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 () { r e t u r n t h i s . id ; }
p u b l i c v o i d setId ( i n t id ) { t h i s . id = id ; }
p u b l i c String getName () { r e t u r n t h i s . name ; }
...
56/65
INSA - ASI
Persistance
InfoRep : EJB
(5/11)
EJB Entité
Name.java
...
@ Override
p u b l i c b o o l e a n equals ( Object o ) {
i f ( t h i s == o )
return true ;
i f ( o == n u l l || getClass () != o . getClass () )
return false ;
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 false ;
return true ;
}
@ Override
p u b l i c i n t hashCode () {
r e t u r n 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 () {
r e t u r n t h i s . name ;
}
}
57/65
INSA - ASI
InfoRep : EJB
Persistance
58/65
(6/11)
EJB Session sans état
PersistentHelloBean.java
package helloWorld ;
import
import
import
import
javax . ejb . Stateless ;
javax . persistence .*;
java . util . Collection ;
java . util . Iterator ;
@ Stateless
public c l a s s P e r s is t e n t H e l l o Be a n i m p l e m e n t s PersistentHelloLocal , P e r s i s t e n t H e l l o R e m o t e
{
@ P e r s i s t e n c e Co n te xt ( 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 ) ) ;
name Collection = 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 () ;
}
r e t u r n hello ;
}
}
INSA - ASI
InfoRep : EJB
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
59/65
INSA - ASI
Persistance
InfoRep : EJB
60/65
(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
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
61/65
INSA - ASI
InfoRep : EJB
Persistance
(10/11)
JTA/H2
Utilisation (par exemple) de H2 comme BD embarquée
1
2
3
4
Création d’un utilisateur ”Admin” pour administrer JBOSS en mode
console Web
Création d’une ”Datasource JDBC”
Activer la Datasource
Déployer l’archive J2EE
Exemple
Name : ”nameList”
JNDI : ”java :jboss/datasources/nameListDS”
Driver : ”h2”
Connection URL : ”jdbc :h2 :/tmp/BD”
62/65
INSA - ASI
InfoRep : EJB
Persistance
(11/11)
Côté client
Client.java
import
import
import
import
javax . naming . Context ;
javax . naming . InitialContext ;
java . util . Hashtable ;
helloWorld . P e r s i s t e n t H e l l o R e m o t e ;
p u b l i c c l a s s Client {
p u b l i c s t a t i c v o i d main ( String [] args ) {
try {
Hashtable jndiProperties = new Hashtable () ;
jndiProperties . put ( Context . URL_PKG_PREFIXES , " org . jboss . ejb . client . naming " ) ;
Context context = new InitialContext ( jndiProperties ) ;
P e r s i s t e n t H e l l o R e m o t e obj = ( P e r s i s t e n t H e l l o R e m o t e ) context . lookup ( " ejb :/
PersistentHello / P e rs i s t e n t H e ll o B e a n ! helloWorld . P e r s i s t e n t H e l l o R e m o t e " ) ;
System . out . println ( obj . sayHello ( args [ args . length -1]) ) ;
} c a t c h ( Exception e ) {
System . out . println ( e ) ;
e . pr intStackTrace () ;
}
}
}
63/65
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