|
EJB 2 - Les Entreprise Java Bean (JavaBeans)
4.4.Spécifications d’un
Entity Bean
4.4.1.Interfaces
Home Interface
La home interface définit les méthodes create(),
finder() et home().
La méthode create
Chaque méthode create() dans la home interface
doit répondre aux exigences suivantes :
-
Elle a le même nombre et type d'arguments que la méthode
ejbCreate() correspondante dans la classe de
l'enterprise bean.
-
Elle renvoie le type de la remote interface du bean.
-
La clause throws inclut les exceptions indiquées par
la clause throws des méthodes ejbCreate()
et ejbPostCreate() correspondantes.
-
La clause throws inclut javax.ejb.CreateException.
-
Si la méthode est définie dans une remote home
interface (pas local home interface), alors la clause throws
inclut java.rmi.RemoteException.
Les méthodes Finder
Chaque méthode finder dans la home interface correspond à
une méthode finder dans la classe de l'entity bean. Le nom
d'une méthode finder dans la home interface commence par find,
tandis que le nom correspondant dans la classe de l'entity bean
commence par ejbFind. Par exemple, l’interface
SavingsAccountHome
définit la méthode findByLastName(),
et la classe SavingsAccountBean
implémente la méthode ejbFindByLastName().
Voici les règles pour définir les signatures des
méthodes finder des home interfaces.
-
Le nombre et les types d'arguments doivent correspondre à
ceux de la méthode correspondante dans la classe de l'entity
bean.
-
Le type de retour est le type de la remote interface de l’entity
bean, ou une collection de ces types.
-
Les exceptions de la clause throws incluent ceux de la
méthode correspondante dans la classe de l'entity bean.
-
La clause throws contient javax.ejb.FinderException.
-
Si la méthode est définie dans une remote home
interface, alors la clause throws inclut
java.rmi.RemoteException.
Les méthodes home
Chaque définition de méthode home dans la home
interface correspond à une méthode dans la classe de
l’entity bean. Dans l'interface home, le nom de méthode
est arbitraire, à condition qu’il ne commence pas par
create ou find. Dans la classe du bean, le nom de
méthode correspondant commence par ejbHome. Par
exemple, dans la classe SavingsAccountBean le nom est
ejbHomeChargeForLowBalance(),
mais dans l'interface SavingsAccountHome le nom est
chargeForLowBalance().
La signature de la méthode home doit suivre les mêmes
règles indiquées pour les méthodes de finder
dans le chapitre précédent (sauf qu'une méthode
home ne lève pas de FinderException).
Remote Interface
La remote interface hérite de javax.ejb.EJBObject et
définit les méthodes métiers qu'un client
distant peut appeler.
Les conditions pour les définitions de méthode dans une
remote interface sont les mêmes pour les session beans et les
entity beans :
-
Chaque méthode dans la remote interface doit correspondre à
une méthode de la classe de l'enterprise bean.
-
Les signatures des méthodes dans la remote interface doivent
être identiques aux signatures des méthodes
correspondantes de la classe de l'enterprise bean.
-
Les arguments et les valeurs de retour doivent être des types
valides pour RMI.
-
La clause throws doit inclure java.rmi.RemoteException.
Une interface locale a les mêmes conditions, aux exceptions
près suivantes :
-
Les arguments et les valeurs de retour ne sont pas obligés
d’être valides pour RMI.
-
La clause throws n'inclut pas java.rmi.RemoteException.
4.4.2.Classe du Bean
L’interface EntityBean hérite de l’interface
EnterpriseBean, qui hérite de l’interface
Serializable. L’interface EntityBean déclare
plusieurs méthodes, telles que ejbActivate() et
ejbLoad(), que vous devez implémenter dans la classe
de votre entity bean. Ces méthodes seront vues en détail
dans les chapitres qui suivent.
BMP (Bean Managed
Persistance)
La classe de l’entity bean de notre exemple s’appelle
SavingAccountBean. Elle doit répondre aux exigeances de
n’importe quel entity bean BMP. Tout d’abord elle
implémente les points suivants :
-
L’interface EntityBean
-
Zero ou plus méthodes ejbCreate() et
ejbPostCreate()
-
Des méthodes finder
-
Des méthodes métiers
-
Des méthodes home
En plus, une classe d’entity bean BMP répond aux
exigeances suivantes :
-
La classe est déclarée public
-
Elle ne peut être abstract ou final
-
Elle contient un constructeur vide
-
Elle n’implémente pas de méthode finalize()
La méthode ejbCreate
Quand le client appele une méthode create(), le
conteneur d’EJB appele la méthode ejbCreate()
correspondante. Typiquement, une méthode ejbCreate()
effectue les tâches suivantes :
-
Insère l’état de l’entité dans la
base de données
-
Initialise les variables d’instances
-
Retourne la clé primaire
La méthode ejbCreate() de SavingAccountBean
insere l’état de l’instance dans la base en
appelant la méthode privée insertRow(), qui exécute
la requête SQL INSERT.
Bien que la classe de SavingsAccountBean ait juste une méthode
ejbCreate(), un enterprise bean peut contenir de
multiples méthodes ejbCreate().
En écrivant une méthode ejbCreate() pour
un entity bean, soyez sûr de suivre ces règles :
-
Le modificateur d’accès doit être public.
-
La valeur de retour doit être la clé primaire.
-
Les arguments doivent avoir un type adéquat à l’API
Java RMI.
-
Les modificateurs de la méthode ne peuvent être final
ou static.
La clause throws peut inclure javax.ejb.CreateException
et les exceptions qui sont spécifiques à votre
application. Une méthode ejbCreate() génère
habituellement une CreateException si un paramètre
n’est pas valide. Si la méthode ne peut créer une
entité parcequ’une autre entité avec la même
clé primaire existe déjà, elle devrait générer
une javax.ejb.DuplicateKeyException (une sous-classe de
CreateException).
Si un client reçoit une CreateException ou une
DuplicateKeyException, il devrait supposer que l'entité
n’a pas été créée.
L’état d'un entity bean peut être directement
inséré dans la base de données par n’importe
quelle application (même inconnue par le serveur J2EE). Par
exemple, un script SQL pourrait insérer une ligne dans la
table savingsaccount.
Bien que l'entity bean pour cette ligne n’ait pas été
créé par une méthode ejbCreate(),
le bean peut être utilisé par un programme client.
La méthode
ejbPostCreate
Pour chaque méthode ejbCreate(), vous devez
écrire une méthode ejbPostCreate() dans
la classe de l'entity bean. Le conteneur d’EJB appelle
ejbPostCreate() juste après l’appel
d’ejbCreate(). A la différence de la
méthode ejbCreate(), la méthode
ejbPostCreate() peut appeler les méthodes
getPrimaryKey() et getEJBObject() de
l’interface EntityContext. Souvent, vos méthodes
ejbPostCreate() seront vides.
La signature d'une méthode ejbPostCreate() doit
répondre aux exigences suivantes :
-
Le nombre et le type des arguments doivent correspondre à une
méthode ejbCreate() correspondante.
-
Le modificateur d’accès doit être public.
-
Les modificateurs de la méthode ne peuvent être final
ou static.
-
Le type de retour doit être void.
La clause throws peut inclure javax.ejb.CreateException
et les exceptions qui sont spécifiques à votre
application.
La méthode ejbRemove
Un client supprime un entity bean en appelant la méthode
remove(). Cette invocation provoque l’appel de
ejbRemove() par le conteneur d’EJB, qui supprime
l’état de l’entité de la base de données.
Dans la classe SavingsAccountBean, la méthode
ejbRemove() appelle une méthode privée appelée
deleteRow(),
qui exécute la requête SQL DELETE.
Si la méthode ejbRemove() rencontre un problème
système, elle devrait lever une javax.ejb.EJBException.
Si elle rencontre une erreur d’application, elle devrait lever
une javax.ejb.RemoveException.
Un entity bean peut également être supprimé
directement par une suppression dans la base de données. Par
exemple, si un script SQL supprime une ligne qui contient un état
d'un entity bean, alors cet entity bean est supprimé.
Les méthodes ejbLoad
et ejbStore
Si le conteneur à besoin de synchroniser les variables
d'instance d'un entity bean avec les valeurs correspondantes stockées
dans la base de données, il appelle les méthodes
ejbLoad() et ejbStore(). La méthode
ejbLoad() régénère les variables
d'instance de la base de données, et la méthode
ejbStore() écrit les variables dans la base de
données. Le client peut ne pas appeler ejbLoad()
et ejbStore().
Si une méthode métier est associée à une
transaction, le conteneur appelle ejbLoad() avant que
la méthode soit exécutée. Juste après que
la méthode soit exécutée, le conteneur appelle
ejbStore(). Puisque le conteneur appelle ejbLoad()
et ejbStore(), vous ne devez pas régénérer
et stocker les variables d’instance dans vos méthodes
métiers. La classe SavingsAccountBean compte sur le
conteneur pour synchroniser les variables d'instance avec la base de
données. Par conséquent, les méthodes métiers
de SavingsAccountBean devraient être associées aux
transactions.
Si les méthodes ejbLoad() et ejbStore()
ne peuvent pas localiser une entité dans la base de données,
elles devraient lever une javax.ejb.NoSuchEntityException.
Cette exception est une sous-classe d'EJBException.
Puisqu'EJBException est une sous-classe de RuntimeException,
vous ne devez pas l’inclure dans la clause throws. Quand
une NoSuchEntityException est générée, le
conteneur d’EJB l'englobe dans une RemoteException avant
de la renvoyer au client.
Dans la classe SavingsAccountBean, ejbLoad() appelle la
méthode loadRow(), qui exécute la reqûete
SQL SELECT et assigne les données récupérées
aux variables d'instance. La méthode ejbStore()
appelle la méthode storeRow(), qui stocke les variables
d'instance dans la base de données avec une requête SQL
UPDATE.
Les méthodes Finder
Les méthodes finder permettent aux clients de charger les
entity beans. L’application SavingAccountClient utilise trois
méthodes finder : findByPrimaryKey(),
findByLastName(),
findInRange().
Pour chaque méthode finder disponible pour le client, la
classe de l’entity bean doit implémenter une méthode
correspondante dont le nom a le préfixe ejbFind. Les
méthodes finder qui sont spécifiques à votre
application, telles que findByLastName()
et findInRange(),
sont optionnelles. En revanche, la méthode
ejbFindByPrimaryKey()
est obligatoire. Comme son nom l’indique, elle prend pour
argument la clé primaire, qui est utilisé pour
localiser un entity bean. Dans la classe SavingAccountBean, la
clé primaire est la variable id.
La méthode ejbFindByPrimaryKey()
peut vous sembler étrange, parce qu'elle utilise une clé
primaire comme paramètre et valeur de retour. Cependant,
rappelez-vous que le client n’appelle pas la méthode
ejbFindByPrimaryKey()
directement. C'est le conteneur qui appelle cette méthode.
Le client appelle la méthode de findByPrimaryKey(),
qui est définie dans la home interface. La liste suivante
récapitule les règles pour les méthodes finder
que vous appliquez dans une classe d'entity bean BMP :
-
La méthode ejbFindByPrimaryKey()
doit être implémentée.
-
Une méthode finder doit avoir son nom qui commence par
ejbFind.
-
Le modificateur d’accès doit être public.
-
Les modifiacteurs de la méthode ne peuvent être final
ou static.
-
Les paramètres et valeurs de retour doivent d’un type
adéquat à l’API Java RMI (cette condition
s'applique seulement aux méthodes définies dans une
remote home interface et non local home interface).
-
Le type de retour doit être celui de la clé primaire ou
une collection de clés primaires.
La clause throws peut inclure javax.ejb.FinderException
et les exceptions spécifiques à votre application. Si
une méthode finder retourne une seule clé primaire et
que l'entité demandée n’existe pas, la méthode
devrait lever une javax.ejb.ObjectNotFoundException (une
sous-classe de FinderException). Si une méthode finder
renvoie une collection de clés primaires et qu’elle ne
trouve aucun objet, elle devrait renvoyer une collection vide.
Les méthodes métiers
Les méthodes métiers contiennent la logique métier
que vous voulez encapsulez dans l’entity bean. Habituellement,
les méthodes métiers n’accèdent pas à
la base de données, vous permettant de séparer la
logique métier du code d’accès aux bases de
données.
Les conditions pour la signature d’une méthode métier
sont les mêmes pour les session beans et les entity beans :
-
Le nom de méthode ne doit pas être en conflit avec un
nom de méthode défini par l'architecture EJB. Par
exemple, vous ne pouvez pas appeler une méthode ejbCreate()
ou ejbActivate().
-
Le modificateur d'accès doit être public.
-
Le modificateur de méthode ne peut pas être final
ou static.
-
Les arguments et les types de retour doivent être des types
adéquats pour l’API Java RMI. Cette condition
s'applique seulement aux méthodes définies dans une
remote home interface.
La clause throws peut inclure les exceptions que vous
définissez pour votre application. La méthode debit(),
par exemple, génère une InsufficientBalanceException.
Pour indiquer un problème au niveau système, une
méthode métier devrait lever une
javax.ejb.EJBException.
Les méthodes home
Une méthode home contient la logique métier qui
s'applique à tous les entity beans d'une classe particulière.
En revanche, la logique dans une méthode métier
s’applique à un seul entity bean, une instance avec une
identité unique. Lors d’un appel d’une méthode
home, l’instance n'a pas d’identité unique ni
d’état qui représente un objet métier. En
conséquence, une méthode home ne doit pas accéder
à l'état persistant du bean (variables d'instance).
Pour un CMP, une méthode home ne doit pas non plus accéder
à des relations.
Typiquement, une méthode home localise une collection
d'instances de bean et appelle les méthodes métiers
pendant qu'elle itère dans la collection. Cette approche est
adoptée par la méthode ejbHomeChargeForLowBalance()
de classe de SavingsAccountBean.
Cette méthode applique des frais administratifs à tous
les comptes d’épargne ayant un solde inférieur à
une quantité indiquée. La méthode localise ces
comptes en appelant la méthode findInRange().
Pendant qu'elle itère dans la collection d'instances de
SavingsAccount, la méthode ejbHomeChargeForLowBalance()
vérifie le solde et appelle la méthode métier
debit().
Dans la classe d’entity bean, l’implémentation
d’une méthode home doit appliquer ces règles :
-
Un nom de méthode home doit commencer par le préfixe
ejbHome.
-
Le modificateur d’accès doit être public.
-
Le modificateur de méthode ne peut pas être static.
La clause throws peut inclure les exceptions qui sont
spécifiques à votre application ; elle ne doit pas
lever de java.rmi.RemoteException.
Les appels à la base
de données
Le Tableau ci-dessous récapitule les appels aux bases de
données de la classe SavingsAccountBean.
Les méthodes métiers de la classe SavingsAccountBean
sont absentes parce qu'elles n'accèdent pas à la base
de données. Au lieu de cela, ces méthodes métiers
mettent à jour les variables d’instance, qui sont
écrites dans la base de données quand le conteneur
appelle ejbStore(). Un autre développeur
pourrait avoir choisi d’accéder à la base de
données dans les méthodes métiers de la classe
SavingsAccountBean.
Ce choix est une des décisions de conception qui dépendent
des besoins spécifiques de votre application.
Méthode
|
Requête
SQL
|
ejbCreate
|
INSERT
|
ejbFindByPrimaryKey
|
SELECT
|
ejbFindByLastName
|
SELECT
|
ejbFindInRange
|
SELECT
|
ejbLoad
|
SELECT
|
ejbRemove
|
DELETE
|
ejbStore
|
UPDATE
|
Les requêtes SQL de SavingAccountBean
Clé
primaire pour la BMP
Vous spécifiez la classe de la clé primaire dans le
descripteur de déploiement de l’entity bean. Dans la
plupart des cas, votre classe de clé primaire sera un String,
un Integer, ou une autre classe qui appartient aux
bibliothèques standards de J2SE ou de J2EE. Pour quelques
entity beans, vous devrez définir votre propre classe de clé
primaire. Par exemple, si le bean a une clé primaire composée
(c'est-à-dire, composée de plusieurs champs), alors
vous devez créer une classe de clé primaire.
Classe de clé
primaire
La classe de clé primaire suivante est une clé
composée : les champs productId et vendorId, ensemble
uniquement, identifient un entity bean.
public
class
ItemKey implements
java.io.Serializable {
public
String productId;
public
String
vendorId;
public
ItemKey() {};
public
ItemKey(String productId, String vendorId) {
this.productId
= productId;
this.vendorId
=
vendorId;
}
public
String getProductId() {
return
productId;
}
public
String getVendorId() {
return
vendorId;
}
public
boolean
equals(Object other) {
if
(other instanceof
ItemKey) {
return
(
productId.equals(((ItemKey)
other).productId)
&&
vendorId.equals(((ItemKey)
other).vendorId));
}
return
false;
}
public
int
hashCode() {
return
productId.concat(vendorId).hashCode();
}
}
Pour la persistance gérée par le bean (BMP), une classe
de clé primaire doit répondre aux conditions
suivantes :
-
Le modificateur d’accès de la classe est public.
-
Tous les champs sont déclarés public.
-
La classe possède un constructeur public par défaut.
-
La classe implémente les méthodes hashCode()
et equals(Object other).
-
La classe est sérialisable.
Clés primaires dans
la classe entity bean
Avec la persistance gérée par le conteneur, la méthode
ejbCreate() assigne les paramètres d’entrée
aux variables d’instance et ensuite retourne la classe de clé
primaire :
public
ItemKey ejbCreate(String productId, String vendorId,
String
description) throws
CreateException {
if
(productId
==
null
||
vendorId
==
null)
{
throw
new
CreateException("The
productId and vendorId are required.");
}
this.productId
= productId;
this.vendorId
= vendorId;
this.description
= description;
return
new
ItemKey(productId,
vendorId);
}
La méthode ejbFindByPrimaryKey() vérifie
l’existence dans le base de données d’une ligne
pour la clé primaire passé en paramètre :
public
ItemKey ejbFindByPrimaryKey(ItemKey primaryKey) throws
FinderException {
try
{
if
(selectByPrimaryKey(primaryKey))
return
primaryKey;
...
}
private
boolean
selectByPrimaryKey(ItemKey primaryKey)
throws
SQLException {
String
selectStatement
=
"select
productid "
+
"from item where productid = ? and vendorid = ?";
PreparedStatement
prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1,
primaryKey.getProductId());
prepStmt.setString(2,
primaryKey.getVendorId());
ResultSet
rs = prepStmt.executeQuery();
boolean
result
=
rs.next();
prepStmt.close();
return
result;
}
Récupérer la
clé primaire
Un client peut chercher la clé primaire d'un entity bean en
appelant la méthode de getPrimaryKey() de la
classe EJBObject :
SavingsAccount
account;
...
String
id = (String)account.getPrimaryKey();
L’entity bean recherche sa propre clé primaire en
appelant la méthode getPrimaryKey() de la classe
EntityContext :
EntityContext
context;
...
String
id = (String) context.getPrimaryKey();
CMP (Container Managed
Persistance)
Un entity bean avec une persistance gérée par le
conteneur offre d’importants avantages au développeur.
D'abord, le conteneur d'EJB s’occupe de toutes les
manipulations de stockage et de récupération dans la
base de données. En second lieu, le conteneur gère les
relations entre les entity beans. En raison de ces services, vous
n’avez pas à coder les accès aux bases de données
dans l'entity bean. Au lieu de cela, vous spécifiez des
paramètres dans le descripteur de déploiement du bean.
Non seulement cette approche vous fait gagner du temps, mais elle
rend le bean portable à travers divers serveurs de base de
données.
Le code de la classe de l’entity bean doit répondre aux
exigences syntaxtiques de la persistance gérée par le
conteneur. D’abord, la classe doit être définie en
public et abstract. En second lieu, la classe doit
implémenter ce qui suit :
-
L’interface EntityBean
-
Zero ou plus méthodes ejbCreate() et
ejbPostCreate()
-
Les méthodes d’accès get et set,
définies en abstract, pour les champs persistants
et relationels
-
Les méthodes select, définies en abstract
-
Les méthodes home
-
Les méthodes métiers
La classe de l’entity bean ne doit pas implémenter ces
méthodes :
-
Les méthodes finder
-
La méthode finalize()
Méthodes d’accès
Un entity bean CMP a des champs persistants et relationnels. Ces
champs sont virtuels, ainsi vous ne les codez pas dans la classe
comme variables d'instance. Au lieu de cela, vous les spécifiez
dans le descripteur de déploiement du bean. Pour permettre
l'accès à ces champs, vous définissez des
méthodes abstraites get et set dans la classe de l'entity
bean.
Méthodes d’accès pour les champs persistants
Le conteneur d’EJB effectue automatiquement la sauvegarde et la
récupération des champs persistants du bean dans la
base de données. Le descripteur de déploiement de
PlayerEJB indique les champs persistants suivants :
-
playerId (clé primaire)
-
name
-
position
-
salary
Le nom d'une méthode d'accès commence par get ou
set, suivi du nom du champ persistant ou relationnel avec sa
première lettre en majuscule. Par exemple, les méthodes
d'accès pour le champ salary
sont getSalary()
et setSalary().
Cette convention d’appellation est semblable à celle des
composants JavaBeans.
Méthodes d’accès pour les champs relationnels
Dans l’application RosterApp, puisqu’un joueur peut
appartenir à plusieurs équipes, une instance de
PlayerEJB peut être lié à de nombreuses instances
de TeamEJB. Pour indiquer cette relation, le descripteur de
déploiement de PlayerEJB définit un champ relationnel
appelé teams. Dans la classe PlayerBean, les méthodes
d’accès pour le champ relationnel teams sont définies
de la manière suivante :
public
abstract
Collection getTeams();
public
abstract
void
setTeams(Collection teams);
Méthodes finder et
select
Les méthodes finder et select utilisent les requêtes EJB
QL pour retourner les objets et les informations d’état
des entity beans utilisant la persistance gérée par le
conteneur.
Une méthode « select » est similaire à
une méthode finder sur les points suivants :
-
Une méthode select peut retourner une interface locale ou
distante (ou une collection d’interface).
-
Une méthode select interoge la base de donnée.
-
Le descripteur de déploiement spécifie une requête
EJB QL pour une méthode select.
-
La classe de l’entity bean n’implémente pas les
méthodes select.
Cependant, une méthode « select »
diffère de manière significative d'une méthode
finder :
-
Une méthode select peut renvoyer un champ persistant (ou une
collection) d'un entity bean relatif. Une méthode finder peut
renvoyer seulement une interface locale ou distante (ou une
collection d'interfaces).
-
Puisqu'elle n’est exposée dans aucune des interfaces
locales ou distantes, une méthode select ne peut pas être
appelée par un client. Elle peut seulement être appelée
par les méthodes implémentées à
l’intérieur de la classe de l’entity bean. Une
méthode select est habituellement appelée par des
méthodes métiers ou home.
-
Une méthode select est définie dans la classe de
l'entity bean. Pour la persistance gérée par le bean,
une méthode finder est définie dans la classe de
l'entity bean, mais pas pour la persistance gérée par
le conteneur.
La classe PlayerBean définit ces méthodes « select » :
public
abstract
Collection ejbSelectLeagues(LocalPlayer player)
throws
FinderException;
public
abstract
Collection ejbSelectSports(LocalPlayer player)
throws
FinderException;
La signature pour une méthode « select »
doit suivre ces règles :
-
Le préfixe du nom de la méthode doit être
ejbSelect.
-
Le modificateur d’accès doit être public.
-
La méthode doit être déclarée abstract.
-
La clause throws doit inclure javax.ejb.FinderException.
Méthodes métiers
Puisque les clients ne peuvent pas appeler de méthodes select,
la classe PlayerBean les enveloppe dans les méthodes métiers
getLeagues()
et getSports() :
public
Collection getLeagues() throws
FinderException {
LocalPlayer
player
=
(team.LocalPlayer)
context.getEJBLocalObject();
return
ejbSelectLeagues(player);
}
public
Collection getSports() throws
FinderException {
LocalPlayer
player
=
(team.LocalPlayer)
context.getEJBLocalObject();
return
ejbSelectSports(player);
}
Méthodes de l’Entity
Bean
Puisque le conteneur manipule la persistance, les méthodes du
cycle de vie dans la classe PlayerBean sont presque vides.
La méthode ejbCreate() initialise l’instance
du bean en assignant les paramètres d'entrée aux champs
persistants. À la fin de la transaction qui contient la
demande de création, le conteneur insère une ligne dans
la base de données. Voici le code source pour la méthode
ejbCreate() :
public
String ejbCreate(String id, String name, String position,
double
salary)
throws
CreateException
{
Debug.print("PlayerBean
ejbCreate");
setPlayerId(id);
setName(name);
setPosition(position);
setSalary(salary);
return
null;
}
La méthode ejbPostCreate() renvoie void
et elle a les mêmes paramètres d'entrée que la
méthode ejbCreate(). Si vous voulez placer un
champ relationnel pour initialiser l'instance du bean, vous devriez
le faire dans la méthode ejbPostCreate(). Vous
ne pouvez pas initialiser un champ relationnel dans la méthode
ejbCreate().
Excepté pour faire du debug, la méthode ejbRemove()
de la classe PlayerBean est vide. Le conteneur appelle ejbRemove()
avant de supprimer l'objet.
Le conteneur synchronise automatiquement l’état de
l'entity bean avec la base de données. Après que le
conteneur ait chargé l’état du bean depuis la
base de données, il appelle la méthode ejbLoad().
De la même manière, avant de stocker l’état
dans la base de données, le destinataire appelle la méthode
ejbStore().
4.4.3.Descripteur de déploiement
Le descripteur de déploiement pour les BMP est bien moins
important que pour les CMP. En effet, les Enity CMP étant géré
en très grande partie par le container, il faut
obligatoirement déclarer plus d’informations que pour le
cas des BMP.
BMP
Voici un exemple de descripteur de déploiement concernant un
Entity BMP :
<entity
>
<description><![CDATA[Description
for ShopUser]]></description>
<display-name>Name
for ShopUser</display-name>
<ejb-name>ShopUser</ejb-name>
<local-home>ejb.shopuser.ShopUserLocalHome</local-home>
<local>ejb.shopuser.ShopUserLocal</local>
<ejb-class>ejb.shopuser.ShopUserBean</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
</entity>
Nous retrouvons, ici, une déclaration d’entity très
basique.
CMP
À l’opposé, les Entity CMP doivent déclarer
l’ensemble des champs persistants et relationnels. De ce fait,
la description de l’entity sera plus importante.
Voici un exemple de descripteur pour un Entity CMP :
<entity
>
<description><![CDATA[Description
for ProductFamily]]></description>
<display-name>Name
for ProductFamily</display-name>
<ejb-name>ProductFamily</ejb-name>
<local-home>com.society.stockmanager.interfaces.ProductFamilyLocalHome
</local-home>
<local>com.society.stockmanager.interfaces.ProductFamilyLocal</local>
<ejb-class>com.society.stockmanager.ejb.ProductFamilyBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>ProductFamily</abstract-schema-name>
<cmp-field
>
<description><![CDATA[Getter
for CMP Field code]]></description>
<field-name>code</field-name>
</cmp-field>
<cmp-field
>
<description><![CDATA[Getter
for CMP Field description]]></description>
<field-name>description</field-name>
</cmp-field>
<primkey-field>code</primkey-field>
<query>
<query-method>
<method-name>findAll</method-name>
<method-params>
</method-params>
</query-method>
<result-type-mapping>Local</result-type-mapping>
<ejb-ql><![CDATA[select
Object(p) from ProductFamily p]]></ejb-ql>
</query>
</entity>
…
<relationships>
<ejb-relation>
<ejb-relation-name>products-providers</ejb-relation-name>
<ejb-relationship-role
>
<ejb-relationship-role-name>providers-products
</ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source
>
<ejb-name>Provider</ejb-name>
</relationship-role-source>
<cmr-field
>
<cmr-field-name>products</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role
>
<ejb-relationship-role-name>products-providers
</ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source
>
<ejb-name>Product</ejb-name>
</relationship-role-source>
<cmr-field
>
<cmr-field-name>providers</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
</ejb-relation>
</relationships>
Nous pouvons maintenant remarquer que l’ensemble des champs
persistants et des requêtes ejb-ql (cf. chapitre EJB-QL) est
déclaré entre les balises « entity ».
Les relations (champs relationnels) sont déclarées
entre les balises « relationships » et
« ejb-relation ».
4.4.4.Cycle de vie
Le schéma ci-dessous montre les étapes par lesquelles
passe un entity bean durant sa vie. Après que le conteneur
d’EJB a créé l’instance, il appelle la
méthode setEntityContext() de la classe de
l’entity bean. Cette méthode passe l’EntityContext
au bean.
Après l’instanciation, l’entity bean est déplacé
vers un pool d’instances disponibles. A cette étape
(pooled), l’instance n’est associée à
aucune identité d’EJB particulière. Toutes les
instances dans le pool sont identiques. Le conteneur d’EJB
assigne une identité à une instance quand elle passe à
l’état ready.
Il existe deux façons de passer de l’état pooled
à l’état ready. Soit le client appelle
la méthode create(), provoquant l’appel
des méthodes ejbCreate() et ejbPostCreate()
par le conteneur, soit le conteneur appelle la méthode
ejbActivate(). A l’état ready, les
méthodes métiers de l’entity bean peuvent être
appelées.
Il existe également deux manières de passer de l’état
ready à l’état pooled. La
première : un client peut appeler la méthode
remove(), qui provoque l’appel de la méthode
ejbRemove() par le conteneur. La seconde : le
conteneur d’EJB peut appeler la méthode ejbPassivate().

Cycle de vie d’un Entity Bean
A la fin du cycle de vie, le conteneur d’EJB supprime
l’instance du pool et appelle la méthode
unsetEntityContext().
Dans l’état pooled, une instance n’est
associée à aucune identité d’EJB
particulière. Avec la bean-managed persistence, quand le
conteneur d’EJB déplace une instance de l’état
pooled à l’état ready, il n’affecte
pas automatiquement la clé primaire. Par conséquent,
les méthodes ejbCreate() et ejbPostCreate()
doivent assigner une valeur à la clé primaire. Si la
clé primaire est incorrecte, les méthodes ejbLoad()
et ejbStore() ne peuvent synchroniser les variables
d’instances avec la base de données.
4.4.5.Différence entre BMP et
CMP
Puisqu’il ne contient aucun accès à la base de
données, un CMP entity bean nécessite beaucoup moins de
code qu’un BMP. Par exemple, le fichier source PlayerBean.java
est beaucoup plus léger que celui vu au chapitre précédent
SavingAccountBean.java. Le tableau 5-2 compare les codes des deux
types d’entity beans.
Différence
Container-Managed
|
Bean-Managed
|
Définition
de la classe
|
Abstract
|
Not
abstract
|
Accès
à la base de données
|
Géré
par le conteneur
|
Codé
par le développeur
|
Etat
persistant
|
Representé
par des champs persistants virtuels
|
Codé
comme variables d’instance
|
Méthodes
d’accès aux champs persistants et relationnels
|
Requises
|
Aucune
|
Méthode
findByPrimaryKey
|
Gérée
par le conteneur
|
Codé
par le développeur
|
Méthodes
finder personnalisés
|
Gérée
par le conteneur, mais le développeur doit écrire
les requêtes EJB QL
|
Codé
par le développeur
|
Méthodes
select
|
Gérées
par le conteneur
|
Aucune
|
Valeur
de retour de ejbCreate
|
null
|
Doit
être la clé primaire
|
Différence de code entre les deux types persistance
On notera que pour les deux types de persistance, les règles à
appliquer pour les méthodes métiers et home sont les
mêmes.
|
|
 |