Les Enterprise Java Beans (La norme 3.0) - LITIS

publicité
NFP111 — Systèmes et Applications Réparties
1 de 48
Plan
Objectifs de la norme
3.0
Un premier exemple
NFP111 — Systèmes et Applications Réparties
Cours 15 - Les Enterprise Java Beans (La norme 3.0)
Cycle de vie
Beans sessions
Claude Duvallet
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Université du Havre
UFR Sciences et Techniques
25 rue Philippe Lebon - BP 540
76058 LE HAVRE CEDEX
Courriel : [email protected]
http://litis.univ-lehavre.fr/∼duvallet/
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
Plan
La norme 3.0
Objectifs de la norme
3.0
1
Objectifs de la norme 3.0
2
Un premier exemple
3
Cycle de vie
4
Beans sessions
5
Beans messages
6
Beans entités
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
2 de 48
NFP111 — Systèmes et Applications Réparties
3 de 48
Plan
Introduction
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La norme EJB 3.0 constitue une évolution importante dans le
domaine des EJB.
Elle constitue une partie importante de la norme Java 2 EE 5.
Un nouveau modèle de gestion de la persistance des
données inspiré d’Hibernate de Jboss.
Une simplification très importante des développements.
Utilisation des annotations introduites dans la version 5.0 du
langage Java.
Adoption du modèle de programmation POJO.
Suppression des descripteurs de déploiement.
Suppression des interfaces métiers et des interfaces Home.
La norme EJB 3.0 intègre aussi une approche
Programmation Orientée Aspect (AOP) en introduisant la
notion d’intercepteur (Interceptor).
NFP111 — Systèmes et Applications Réparties
4 de 48
Plan
Objectifs de la norme 3.0
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Simplification de la conception des Beans coté développeur.
Simplification de la définition des interfaces, suppression d’un
certain nombre de pré-requis présents dans la norme 2.1
(absence d’héritage de super classes ou interfaces).
Simplification de la création du Bean.
Simplification des API pour l’accès à l’environnement du
Bean : définition par simple injection dépendante.
Introduction des annotations en Java en lieu et place du
descripteur de déploiement.
Simplification concernant la persistance d’objet par
l’utilisation facilitée de mapping objet/relationnel basée sur
l’utilisation directe de classes Java et non de composants
persistants.
NFP111 — Systèmes et Applications Réparties
5 de 48
Plan
Les annotations
Objectifs de la norme
3.0
Un premier exemple
Métadonnées permettant à certains outils de générer des
constructions additionnelles à la compilation ou à l’exécution.
Cycle de vie
Elles simplifient considérablement l’écriture de programmes.
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Elles permettent de se passer du descripteur de déploiement.
Néanmoins, il est toujours possible de l’utiliser.
Elle permettent de spécifier les interfaces locales ou
distantes du Bean avec uniquement les mots clefs
"@Remote" et "@Local".
Elle permettent de définir un Bean session avec ou sans état
avec uniquement les mots clefs "@Statefull" ou "@Stateless".
NFP111 — Systèmes et Applications Réparties
6 de 48
Plan
Hello World avec les EJB 3.0 (1/4)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Définition de l’interface Hello :
Désormais, cette interface est la seule à définir.
Interface extrêmement simplifiée : pas besoins d’avoir recours
à de quelconques héritages.
package hello;
public interface Hello {
public String hello (String msg);
}
NFP111 — Systèmes et Applications Réparties
7 de 48
Plan
Hello World avec les EJB 3.0 (2/4)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Définition du Bean :
Cette classe est aussi très simplifiée.
Elle n’hérite pas de classes spécifiques.
Elle doit pallier à la suppression des interfaces distantes et
locales en utilisant des annotations.
On utilise une annotation pour spécifier qu’il s’agit d’un bean
Session sans état.
Beans messages
package hello;
Beans entités
import javax.ejb.*;
@Stateless
@Remote (Hello.class)
public class HelloBean implements Hello {
public String hello (String msg){
System.out.println ("Message reçu : "+msg);
return "Hello "+msg;
}
}
NFP111 — Systèmes et Applications Réparties
8 de 48
Plan
Hello World avec les EJB 3.0 (3/4)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Définition du descripteur de déploiement : il n’en reste
presque rien ce qui simplifie son écriture
Beans sessions
Beans sessions sans état
<?xml version="1.0" encoding="ISO-8859-1"?>
Beans sessions avec état
Beans messages
Beans entités
<ejb-jar xmlns="http://java.sun.com/xmlns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd"
version="3.0">
<enterprise-beans>
</enterprise-beans>
</ejb-jar>
NFP111 — Systèmes et Applications Réparties
9 de 48
Plan
Hello World avec les EJB 3.0 (4/4)
Objectifs de la norme
3.0
Définition du client : lui aussi est simplifié par rapport au
même client dans les EJB 2.1.
Un premier exemple
Cycle de vie
Beans sessions
import
import
import
import
javax.naming.Context;
javax.naming.InitialContext;
hello.*;
java.util.*;
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
public class HelloClient{
public static void main(String[] args) throws Exception {
Properties props = System.getProperties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Context ctx = new InitialContext(props);
Hello hello = (Hello) ctx.lookup("HelloBean/remote");
System.out.println(hello.hello("World"));
}
}
NFP111 — Systèmes et Applications Réparties
10 de 48
Plan
Cycle de vie des Beans 3.0 (1/3)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Disparition des interface Home : les références sur les beans
se font directement.
Utilisation des méthodes "callback" pour la gestion du cycle
de vie.
Les méthodes callback peuvent être définies :
soit directement dans le bean : la signature de la méthode
doit être public void nom_methode (),
soit dans une classe Listener Callback qui ressemble à une
interface home.
La classe Listener Callback :
toutes les méthodes sont définies dans la classe.
les méthodes prennent en argument le bean correspondant.
il suffit d’importer cette classe dans la classe du bean
CallbackListener.
la signature de la méthode doit être public void
nom_methode (Object) où Object est le type du bean,
NomDeLaClasseCallback.
NFP111 — Systèmes et Applications Réparties
11 de 48
Plan
Cycle de vie des Beans 3.0 (2/3)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Les méthodes "callback" doivent être annotées avec les
annotations de callback :
@CallBackListener(String classname)
@PostConstruct
@PreDestroy
@PostActivate
@PrePassivate
@EntityListener(String classname)
@PrePersist
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostLoad
Exemple 1 : Définition des méthodes "callback" directement
dans le bean.
@Stateful
public class MonBean {
private float total;
private Vector productCodes;
public int desMethods(){...};
...
@PreDestroy uneMethodeCallback() {...};
...
}
NFP111 — Systèmes et Applications Réparties
12 de 48
Plan
Cycle de vie des Beans 3.0 (3/3)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Exemple 2 : Définition des méthodes "callback" en dehors du
bean.
Tout d’abord, on définit une classe Listener qui contiendra les
méthodes "callback".
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
public class MonBeanListener {
@PreDestroy uneMethodeCallback() {...};
...
}
Puis, on fait appel au "callback listener" dans le bean.
@CallbackListener MonBeanListener
@Stateful
public class MonBean {
private float total;
private Vector productCodes;
public int desMethods(){...};
...
}
NFP111 — Systèmes et Applications Réparties
13 de 48
Plan
L’injection de dépendance (1/2)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Elle permet à un bean d’acquérir des références sur d’autres
ressources ou d’autres objets de l’application.
Auparavant, il fallait avoir recours aux fichiers XML (avec
ejb-ref) et se servir du JNDI pour accéder à une
ressource :
Pour accéder à un EJB, il était obligatoire de passer par son
interface Home pour récupérer l’interface et utiliser ses
méthodes métiers.
Maintenant, c’est le conteneur qui injecte ces références
avant que toute méthode liée au cycle de vie de l’EJB ou
méthode métier ne soit appelée.
Le conteneur se charge d’initialiser toutes les ressources
dont le bean a besoin.
NFP111 — Systèmes et Applications Réparties
14 de 48
Plan
L’injection de dépendance (2/2)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Exemple de récupération d’une ressource de type base de
données :
// On récupère une ressource maBD et on l’affecte à clientBD
// Le type de maBD est déduit de la variable clientBD
@Ressource (name="maBD")
public SourceDesDonnees clientBD;
Exemple de récupération de la référence d’un autre EJB :
Beans sessions avec état
Beans messages
Beans entités
@EJB
public AddressHome addressHome;
On peut aussi passer par les méthodes set... pour récupérer
une ressource :
// récupère la ressource de nom clientBD et de type SourceDesDonnees
@Ressource(name="clientBD")
public void setSourceDesDonnees(SourceDesDonnees clientBD){
this.sdd = clientBD;
}
// récupère la ressource de nom maBD et de type SourceDesDonnees
@Ressource
public void setClientBD(SourceDesDonnees maBD){
this.clientBD = maBD;
}
NFP111 — Systèmes et Applications Réparties
15 de 48
Plan
Les méthodes d’interception
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Appelées méthodes "interceptors", elles seront exécutées à
chaque appel d’une méthode métier définissant ces
méthodes.
Elles sont de la forme :
public Object <methodName>(javax.ejb.InvocationContext)
throws Exception
Toute méthode interceptor doit prendre en argument
l’interface suivante :
public interface InvocationContext {
// retourne le bean cible de la méthode interceptor
public Object getTarget ();
// retourne la méthode déclenchant l’interceptor
public Method getMethod ();
// retourne les paramètres de la méthode métier
public Object[] getParameters();
public void setParameters (Object[] params);
public java.util.Map<String, Object> getContextData();
// exécute la méthode interceptor suivante ou
// la méthode annotée @AroundInvoke
public Object proceed() throws Exception;
}
NFP111 — Systèmes et Applications Réparties
16 de 48
Plan
Exemple de méthodes interceptor
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
@Stateless
@Interceptor("TestInterceptor")
public class LoginBean {
@AroundInvoke
public Object testInterceptor (InvocationContext invContext) throw Exception {
invContext.proceed ();
}
}
public class TestInterceptor {
@AroundInvoke
public Object myInterceptor (InvocationContext invContext) throws Exception{
invContext.proceed ();
}
}
NFP111 — Systèmes et Applications Réparties
17 de 48
Plan
Beans sessions sans état
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La classe doit être annotée avec @Stateless (import
javax.ejb.Stateless ;)
Ces beans supportent les callback d’évènements :
PostConstruct, PreDestroy, mais aussi PostActivate et
PrePassivate qui correpondent aux méthodes
ejbActivate et ejbPassivate présentes dans les EJB 2.x.
La méthode callback PostConstruct intervient après toutes
les injections de dépendances effectuées par le conteneur et
avant le premier appel d’une méthode métier.
La méthode callback PreDestroy est appelée au moment où
l’instance du bean est détruite.
NFP111 — Systèmes et Applications Réparties
Plan
Beans sessions sans état (Exemple) (1/2)
Objectifs de la norme
3.0
Un premier exemple
L’interface distante du Bean :
package calc;
import javax.ejb.Remote;
Cycle de vie
Beans sessions
Beans sessions sans état
@Remote public interface Calc {
public double add(double val1, double val2);
public double mult(double val1, double val2);
}
Beans sessions avec état
Beans messages
La classe du Bean :
package calc;
Beans entités
import javax.ejb.Stateless;
@Stateless public class CalcBean implements Calc {
public double add(double val1, double val2) {
return val1 + val2;
}
public double mult(double val1, double val2) {
return val1 * val2;
}
}
18 de 48
NFP111 — Systèmes et Applications Réparties
Plan
Beans sessions sans état (Exemple) (2/2)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Le client du bean :
import
import
import
import
javax.naming.Context;
javax.naming.InitialContext;
calc.*;
java.util.*;
public class CalcClient{
public static void main(String[] args) throws Exception {
Properties props = System.getProperties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Context ctx = new InitialContext(props);
Calc calc = (Calc) ctx.lookup("CalcBean/remote");
double somme = 0;
somme = calc.add(5.643, 8.2921);
System.out.println("Addition de 5.643 + 8.2921 = "+somme);
}
}
19 de 48
NFP111 — Systèmes et Applications Réparties
20 de 48
Plan
Beans sessions avec état
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
La classe doit être annotée avec @Statefull (import
javax.ejb.Statefull ;)
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Ces beans supportent les callback d’évènements :
PostConstruct, PreDestroy, PostActivate et
PrePassivate.
Il existe l’annotation @Remove applicable à une méthode
métier et qui implique la destruction du bean après son appel.
NFP111 — Systèmes et Applications Réparties
Plan
Beans sessions avec état (Exemple) (1/3)
Objectifs de la norme
3.0
Un premier exemple
L’interface distante du Bean :
Cycle de vie
package panier;
Beans sessions
Beans sessions sans état
import javax.ejb.Remote;
import java.util.*;
Beans sessions avec état
Beans messages
Beans entités
@Remote public interface Panier{
public void ajouterArticle(int idArticle);
public void supprimerArticle(int idArticle);
public Vector listerArticles();
public void setNom(String nomClient);
public String getNom();
public void remove();
}
21 de 48
NFP111 — Systèmes et Applications Réparties
Plan
Beans sessions avec état (Exemple) (2/3)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
La classe du Bean :
package panier;
import
import
import
import
javax.ejb.Stateful;
javax.annotation.PostConstruct;
javax.ejb.Remove;
java.util.*;
@Stateful public class PanierBean implements Panier{
Vector articles;
String nomClient;
Beans sessions
@PostConstruct public void initialise() {
articles = new Vector();
nomClient = "";
}
Beans sessions sans état
Beans sessions avec état
public void ajouterArticle(int idArticle) {
System.out.println ("Ajout d’un nouvel article");
articles.add(new Integer(idArticle));
}
Beans messages
Beans entités
public void supprimerArticle(int idArticle){
System.out.println ("Suppression d’un article");
articles.remove(new Integer(idArticle));
}
public Vector listerArticles(){
return articles;
}
public void setNom(String nomClient) {
this.nomClient = nomClient;
}
public String getNom() {
return nomClient;
}
@Remove public void remove() {
articles = null;
}
}
22 de 48
NFP111 — Systèmes et Applications Réparties
23 de 48
Plan
Beans sessions avec état (Exemple) (3/3)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Le client du bean :
import
import
import
import
javax.naming.*;
javax.rmi.PortableRemoteObject;
java.util.*;
panier.*;
public class PanierClient {
public static void main(String[] args) throws Exception {
Properties props = System.getProperties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Context ctx = new InitialContext(props);
Panier monPanier = (Panier) ctx.lookup("PanierBean/remote");
monPanier.ajouterArticle(65);
monPanier.ajouterArticle(53);
Beans sessions avec état
Beans messages
Vector mesArticles = monPanier.listerArticles();
System.out.println ("Il y a "+mesArticles.size()+" article(s) dans le panier !");
Enumeration e = mesArticles.elements();
while (e.hasMoreElements()) {
System.out.println((Integer)e.nextElement());
}
Beans entités
monPanier.ajouterArticle(23);
monPanier.ajouterArticle(18);
monPanier.supprimerArticle(65);
mesArticles = monPanier.listerArticles();
System.out.println ("Il y a "+mesArticles.size()+" article(s) dans le panier !");
e = mesArticles.elements();
while (e.hasMoreElements()) {
System.out.println((Integer)e.nextElement());
}
monPanier.remove ();
}
}
NFP111 — Systèmes et Applications Réparties
24 de 48
Plan
Beans messages
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La classe du bean doit être annotée avec @MessageDriven
(import javax.ejb.MessageDriven ;).
L’interface du bean doit être du type des que le bean va
utiliser. Dans la plupart des cas, il s’agira de
javac.jms.MessageListener.
Ces beans supportent les callback d’évènements :
PostConstruct et PreDestroy.
Dans le cas d’une utilisation avec JMS, la méthode public
void onMessage (Message msg) doit être redéfinit.
Il faut également définir les différents paramètres à utiliser
pour la connexion à la destination.
Pour cela, on utilise les propriétés : destinationType et
destination.
NFP111 — Systèmes et Applications Réparties
25 de 48
Plan
Beans messages : exemple (1/2)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La classe du Bean :
import javax.annotation.Resource;
import javax.ejb.*;
import javax.jms.*;
@MessageDriven(activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "queue/MessageBean")
})
public class MessageBean implements MessageListener {
@Resource MessageDrivenContext mdc;
//Méthode de réception des messages
public void onMessage(Message msg) {
TextMessage tm;
try {
if (msg instanceof TextMessage){
tm = (TextMessage) msg;
String text = tm.getText(); System.out.println("Message Bean Reçu : " + text);
}
else {
System.out.println ("Message de mauvais type : "+msg.getClass().getName());
}
}catch(JMSException e) {
e.printStackTrace();
mdc.setRollbackOnly ();
}catch(Throwable te) {
te.printStackTrace();
}
}
}
NFP111 — Systèmes et Applications Réparties
26 de 48
Plan
Beans messages : exemple (1/2)
Objectifs de la norme
3.0
Le client :
Un premier exemple
import javax.naming.*;
import javax.jms.*;
import java.util.*;
Cycle de vie
public class Client {
public static void main (String[] args) throws Exception {
// Initialisation JNDI
Properties props = System.getProperties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Context ctx = new InitialContext(props);
// 1: recherche d’une fabrique de connection via JNDI
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
// 2: Utilisation de la fabrique de connexions pour créer une connexion JMS
QueueConnection connection = factory.createQueueConnection();
// 3: Utilisation de la connection pour créer une session
QueueSession session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
// 4: Recherche du sujet (topic) via JNDI
javax.jms.Queue queue = (javax.jms.Queue) ctx.lookup("queue/MessageBean");
// 5: Création d’un producteur de message
QueueSender sender = session.createSender(queue);
// 6: Creation d’un message texte et publication
TextMessage msg = session.createTextMessage();
for (int i=0;i<10;i++){
msg.setText("Envoi du message : " + i);
sender.send(msg);
}
Beans entités
}
}
NFP111 — Systèmes et Applications Réparties
27 de 48
Plan
Beans entités (1/5)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Ce sont eux aussi des POJOs mais leurs spécifications ont
été définies à part car ils ont subi beaucoup de modifications
dans la norme 3.0.
L’annotation @Entity (import
javax.persistance.Entity ;) définit le bean comme
étant de type entité.
Le bean doit posséder au moins un constructeur par défaut et
devra hériter de l’interface Serializable afin d’être utilisable à
travers le réseau pour la gestion de la persistance.
On peut spécifier deux méthodes différentes pour la gestion
de la persistance au moyen de l’option access :
@Entity(access=AccessType.FIELD) permet d’accéder
directement aux champs à rendre persistant.
@Entity(access=AccessType.PROPERTY) oblige le
fournisseur à utiliser les accesseurs.
NFP111 — Systèmes et Applications Réparties
28 de 48
Plan
Beans entités (2/5)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
La clé primaire peut-être simple ou composée et doit être
déclarée avec l’annotation @Id.
Par exemple, pour obtenir une clé qui s’incrémente
automatiquement : @Id(generate=GenerateType.AUTO).
Pour les clés composées, il faut respecter certains principes :
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La classe de la clé primaire doit être public et posséder un
constructeur sans arguments.
Si l’accès est de type PROPERTY, la classe peut-être soit de
type public soit de type protected.
La classe doit être sérialisable (implémenter Serializable).
Implémentation des méthodes equals() et hashCode().
Si la clé primaire est mappée à de multiples champs ou
propriétés, les noms des champs de cette clé doivent être les
mêmes ceux utilisés dans le bean entité.
Les annotations permettent d’effectuer le mapping
objet/relationnel et la gestion des relations entre les entités.
NFP111 — Systèmes et Applications Réparties
29 de 48
Plan
Beans entités (3/5)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Lors de la création d’un bean entité, il faut effectuer le
mapping de tous ses champs. Un mapping par défaut
intervient lorsqu’aucune annotation précède le champ :
@Basic spécifie ce comportement.
@Table définit la table correspondant à la classe, elle prend
en argumant le nom de la table.
@Entity(access=accessType.FIELD)
@Table(name="PAYS")
public class Pays implements Serializable {
@Id(generate=GeneratorType.AUTO) private int id;
@Basic private String nom;
public Pays() {
}
public Pays(String nom) {
this.nom = nom;
}
public int getId() {
return id;
}
}
NFP111 — Systèmes et Applications Réparties
30 de 48
Plan
Beans entités (4/5)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
On peut faire correspondre une valeur à un champ spécifique
de la base de données en utilisant l’annotation @Column et
des options comme name qui spécifie le nom de la colonne,
ou des options pour définir si champ peut être nul, ...
@Column(name="DESC", nullable=false)
public String getDescription() {
return description;
}
Il existe les relations OneToOne, OneToMany, ManyToOne,
ManyToMany (définies par les annotations correspondantes).
Dans ces cas, il ne faut pas oublier de spécifier les colonnes
faisant les jointures.
@ManyToOne(optional=false)
@JointColumn(name = "CLIENT_ID", nullable = false, updatable = false)
public Client getClient (){
return client;
}
NFP111 — Systèmes et Applications Réparties
31 de 48
Plan
Beans entités (5/5)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Les beans entités se manipulent par l’intermédiaire d’un
EntityManager.
Cet EntityManager peut être obtenu à partir d’un Bean
Session par injection de dépendance.
@Stateless public class EmployeeManager{
@Resource EntityManager em;
Beans entités
public void void updateEmployeeAddress (int employeeId, Address address) {
//Recherche d’un bean
Employee emp = (Employee)em.find ("Employee", employeId);
emp.setAddress (address);
}
}
NFP111 — Systèmes et Applications Réparties
32 de 48
Plan
Beans entités : exemple (1/12)
Objectifs de la norme
3.0
Principe de base :
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
On crée un bean entité qui permettra de manipuler des objets
persistants.
Dans le bean entité, on met en place un mapping entre les
attributs du bean et une table de la base de données.
Le client n’accède pas directement aux beans entités mais
passe par des beans sessions qui effectueront les
manipulations nécessaires sur les beans entités.
Les beans de l’exemple :
ArticleBean : il s’agit du bean entité.
ArticleAccessBean : il s’agit d’un bean session sans état. Il
est composé de la classe ArticleAccessBean.java et de
l’interface ArticleAccess.java.
NFP111 — Systèmes et Applications Réparties
33 de 48
Plan
Beans entités : exemple (2/12)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
L’interface ArticleAccess.java : définition des méthodes
métiers.
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
package article;
import javax.ejb.Remote;
import java.util.*;
@Remote public interface ArticleAccess {
public int addArticle (String libelle, double prixUnitaire, String categorie);
public void delArticle (int idArticle);
public InfosArticle rechercherArticle (int idArticle);
public List rechercherLesArticlesParCategorie (String categorie);
public List rechercherTousLesArticles ();
}
NFP111 — Systèmes et Applications Réparties
Plan
Beans entités : exemple (3/12)
Objectifs de la norme
3.0
La classe ArticleAccessBean.java : la méthode
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
addArticle
package article;
import javax.ejb.*;
import javax.persistence.*;
import java.util.*;
Beans sessions avec état
@Stateless public class ArticleAccessBean implements ArticleAccess {
Beans messages
@PersistenceContext(unitName="Articles")
EntityManager em;
Beans entités
public int addArticle (String libelle, double prixUnitaire, String categorie){
ArticleBean ab = new ArticleBean ();
ab.setCategorie (categorie);
ab.setLibelle (libelle);
ab.setPrixUnitaire (prixUnitaire);
em.persist(ab);
em.flush();
System.out.println ("AccessBean : Ajout de l’article "+ab.getIdArticle ());
return ab.getIdArticle ();
}
34 de 48
NFP111 — Systèmes et Applications Réparties
35 de 48
Plan
Beans entités : exemple (4/12)
Objectifs de la norme
3.0
Un premier exemple
La classe ArticleAccessBean.java : la méthode
Cycle de vie
delArticle
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
public void delArticle (int idArticle){
Query query = em.createQuery("DELETE FROM ArticleBean AS a WHERE a.idArticle="+idArticle
}
public InfosArticle rechercherArticle (int idArticle){
Query query = em.createQuery("SELECT a FROM ArticleBean AS a WHERE a.idArticle="+idArticle);
List<ArticleBean> allArticles = query.getResultList();
Beans entités
ArticleBean article = allArticles.get(0);
return new InfosArticle (article.getIdArticle(), article.getLibelle(),
article.getPrixUnitaire(), article.getCategorie());
}
NFP111 — Systèmes et Applications Réparties
36 de 48
Plan
Beans entités : exemple (5/12)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
La classe ArticleAccessBean.java : la méthode
rechercherTousLesArticles
public List rechercherTousLesArticles (){
Query query = em.createQuery("SELECT a FROM ArticleBean AS a");
List<ArticleBean> articlesbean = query.getResultList();
Vector<InfosArticle> articles = new Vector();
Iterator i = articlesbean.iterator();
ArticleBean article;
while (i.hasNext()) {
article = (ArticleBean) i.next();
InfosArticle infos = new InfosArticle (article.getIdArticle(), article.getLibelle(),
article.getPrixUnitaire(), article.getCategor
articles.add(infos);
}
return articles;
}
NFP111 — Systèmes et Applications Réparties
37 de 48
Plan
Beans entités : exemple (6/12)
Objectifs de la norme
3.0
Un premier exemple
La classe ArticleAccessBean.java : la méthode
Cycle de vie
rechercherLesArticlesParCategorie
Beans sessions
public List rechercherLesArticlesParCategorie (String categorie){
Query query = em.createQuery("SELECT a FROM ArticleBean AS a WHERE categorie=’"+categori
List<ArticleBean> articlesbean = query.getResultList();
Vector<InfosArticle> articles = new Vector();
Iterator i = articlesbean.iterator();
ArticleBean article;
while (i.hasNext()) {
article = (ArticleBean) i.next();
articles.add(new InfosArticle (article.getIdArticle(), article.getLibelle(),
article.getPrixUnitaire(), article.getCategorie()));
}
return articles;
}
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
}
NFP111 — Systèmes et Applications Réparties
38 de 48
Plan
Beans entités : exemple (7/12)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Le fichier de gestion de la persistance : persistence.xml
<persistence 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"
version="1.0">
<persistence-unit name="Articles">
<jta-data-source>java:/DefaultDS</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>
NFP111 — Systèmes et Applications Réparties
39 de 48
Plan
Beans entités : exemple (8/12)
Objectifs de la norme
3.0
Le client ArticleClient.java : la méthode creerArticle
Un premier exemple
Cycle de vie
Beans sessions
import
import
import
import
import
javax.naming.*;
javax.rmi.*;
javax.ejb.*;
java.util.*;
article.*;
public class ArticleClient {
Beans sessions sans état
Beans sessions avec état
Beans messages
public void creerArticle(String libelle, double montantUnitaire, String categorie) {
ArticleAccess ah;
Properties props = System.getProperties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
Beans entités
try {
Context ctx = new InitialContext(props);
ah = (ArticleAccess) ctx.lookup("ArticleAccessBean/remote");
System.out.println ("Ajout d’un article : "+ah);
int id = ah.addArticle(libelle, montantUnitaire, categorie);
System.out.println ("Affichage de l’article "+id);
afficherArticle(id);
} catch (Throwable th) {
System.out.println("Erreur dans creerArticle : " + th);
}
}
NFP111 — Systèmes et Applications Réparties
40 de 48
Plan
Beans entités : exemple (9/12)
Objectifs de la norme
3.0
Un premier exemple
Le client ArticleClient.java : la méthode
afficherArticle
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
public void afficherArticle(int numeroArticle) {
ArticleAccess ah;
Properties props = new Properties();
props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
props.put("java.naming.provider.url", "localhost:1099");
try {
Context ic = new InitialContext(props);
ah = (ArticleAccess) ic.lookup("ArticleAccessBean/remote");
InfosArticle infos = ah.rechercherArticle(numeroArticle);
System.out.println("voici les infos sur l’article : " + infos.idArticle);
System.out.println("
id : " + infos.idArticle);
System.out.println("
libelle : " + infos.libelle);
System.out.println("
prix unitaire : " + infos.prixUnitaire);
System.out.println("
categorie : " + infos.categorie);
} catch (Throwable th) {
System.out.println("GereCommande.creerArticle : " + th);
}
}
NFP111 — Systèmes et Applications Réparties
41 de 48
Plan
Beans entités : exemple (10/12)
Objectifs de la norme
3.0
Le client ArticleClient.java : la méthode
Un premier exemple
Cycle de vie
afficherArticlesParCategorie
public void afficherArticlesParCategorie(String categorie) {
ArticleAccess ah;
Properties props = new Properties();
props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
props.put("java.naming.provider.url", "localhost:1099");
try {
Context ic = new InitialContext(props);
ah = (ArticleAccess) ic.lookup("ArticleAccessBean/remote");
List<InfosArticle> articles = ah.rechercherLesArticlesParCategorie(categorie);
Iterator i = articles.iterator();
InfosArticle article;
while (i.hasNext()) {
article = (InfosArticle) i.next();
afficherArticle(article.idArticle);
}
} catch (Throwable th) {
System.out.println("Erreur dans rechercherArticlesParCategorie : " + th);
}
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
}
NFP111 — Systèmes et Applications Réparties
42 de 48
Plan
Beans entités : exemple (11/12)
Objectifs de la norme
3.0
Le client ArticleClient.java : la méthode
Un premier exemple
Cycle de vie
afficherTousLesArticles
public void afficherTousLesArticles() {
ArticleAccess ah;
Properties props = new Properties();
props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
props.put("java.naming.provider.url", "localhost:1099");
try {
Context ic = new InitialContext(props);
ah = (ArticleAccess) ic.lookup("ArticleAccessBean/remote");
List<InfosArticle> articles = ah.rechercherTousLesArticles();
Iterator i = articles.iterator();
InfosArticle article;
while (i.hasNext()) {
article = (InfosArticle) i.next();
afficherArticle(article.idArticle);
}
} catch (Throwable th) {
System.out.println("Erreur dans rechercherArticlesParCategorie : " + th);
}
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
}
NFP111 — Systèmes et Applications Réparties
Plan
Beans entités : exemple (12/12)
Objectifs de la norme
3.0
Le client ArticleClient.java : la méthode main
Un premier exemple
public static void main(java.lang.String[] args) {
Cycle de vie
ArticleClient a = new ArticleClient ();
a.creerArticle("Les miserables", 21, "LIVRE");
a.creerArticle("Celine Dion au stade de France", 120, "CD");
a.creerArticle("Je l’aime a mourir", 28, "LIVRE");
a.creerArticle("La mer", 38, "LIVRE");
Beans sessions
Beans sessions sans état
Beans sessions avec état
// Recherche de l’article 3
System.out.println ("================================");
a.afficherArticle(3);
System.out.println ("================================");
a.afficherTousLesArticles();
System.out.println ("================================");
Beans messages
Beans entités
// Recherche de la categorie
a.afficherArticlesParCategorie("CD");
System.out.println ("================================");
}
}
43 de 48
NFP111 — Systèmes et Applications Réparties
44 de 48
Plan
Connexion avec une base de données MySQL (1/2)
Objectifs de la norme
3.0
Un premier exemple
Créer une base de données (Exemple : JBossDB)
Cycle de vie
Créer un fichier mysql-ds.xml (Le nom importe peu !)
Beans sessions
Copier ce fichier dans le répertoire de déploiement
/usr/local/jboss/server/default/deploy ou encore
c :\jboss\server\default\deploy.
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Télécharger le connecteur JDBC pour MySQL (fichier JAR) et
copier dans le répertoire
/usr/local/jboss/server/default/lib ou encore
c :\jboss\server\default\deploy.
NFP111 — Systèmes et Applications Réparties
45 de 48
Plan
Connexion avec une base de données MySQL (2/2)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Le fichier mysql-ds.xml
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MySQLDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/JBossDB</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>duvallet</user-name>
<password>duvallet</password>
<exception-sorter-class-name>
org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
</exception-sorter-class-name>
<!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
NFP111 — Systèmes et Applications Réparties
46 de 48
Plan
Les relations Un à Un (One To One)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Une relation « One To One » est utilisée pour lier deux entités
uniques indissociables.
Ce type de relation peux-être mappé de trois manières dans
la base de données :
en utilisant les mêmes valeurs pour les clés primaires des
deux entités via l’annotation @PrimaryKeyJoinColumn.
en utilisant une clé étrangère d’un coté de la relation via
l’annotation @JoinColumn (name="identifiant",
referencedColumnName="clé primaire dans l’autre
table").
en utilisant une table d’association de liens entre les deux
entités via l’annotation @JoinTable(name =
"NomDeLaTableDeJointure", joinColumns =
@JoinColumn (name="1ère clé étrangère",
unique=true), inverseJoinColumns =
@JoinColumns(name="2ième clé étrangère",
unique=true)
NFP111 — Systèmes et Applications Réparties
47 de 48
Plan
Les relations Un à Plusieurs (One To Many) et Plusieurs à
Objectifs de la norme
3.0
Un (Many To One)
Un premier exemple
Cycle de vie
Beans sessions
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Ces deux relations sont utilisées pour lier à une unique
instance d’une entité A, un groupe d’instances d’une entité B.
L’association « Many To One » est définie par l’annotation
@ManyToOne
Dans le cas d’une relation bidirectionnelle, l’autre coté doit
utiliser l’annotation @OneToMany.
Les attributs de ces deux annotations correspondent à ceux
de l’annotation @OneToOne.
NFP111 — Systèmes et Applications Réparties
48 de 48
Plan
Les relations Plusieurs à Plusieurs (Many To Many)
Objectifs de la norme
3.0
Un premier exemple
Cycle de vie
Beans sessions
Ces relations sont utilisées pour lier des instances de deux
entités entre elles.
Beans sessions sans état
Beans sessions avec état
Beans messages
Beans entités
Exemple : un article appartient à éventuellement plusieurs
catégories et une catégorie contient plusieurs articles.
Il est nécessaire d’utiliser une table d’association pour mettre
en œuvre cette association.
Téléchargement