Utilisation de XDoclet : 
Développement d'un EJB avec uniquement la classe Bean

Exemple : Création d'un Session Bean avec les balises JavaDoc XDoclet.

Nous allons créer un Session EJB. Peu importe ce que ce Bean fait, nous allons simplement nous intéresser à comment développer un Java Bean en prenant une classe bean, en la commentant avec les balises JavaDoc spécifiques et en utilisant XDoclet pour générer les méta fichiers.

Le fichier ReceiverBean.java va contenir le méthode documentReady(Document doc). Cette méthode prend un document DOM et le transmet au prochain Xbean dans la chaîne.

Pour télécharger tous les fichiers de cet exemple cliquez sur l'image :  

Définitions spécifiques au niveau de la Classe

Au niveau de la classe, nous devons définir :

  1. Le fait que le session bean est sans état : stateless.
  2. Le nom JNDI.
  3. Les entrées d'environment.
  4. Les attributs spécifiques à la plate-forme (WebLogic, JBoss, ... ).

Balise: @ejb:bean

Le seul attribut indispensable pour cette balise est de donner à XDoclet le nom du bean. Nous allons aussi définir le type du bean, son nom JNDI (pour le lier avec le home stub) et son nom d'affichage :

/**
 *   This is the EJB Receiver Xbean
 *
 *   @ejb:bean type="Stateless"
 *             name="ejbReceiver"
 *             jndi-name="org.xbeans.ejb.receiver.Receiver"
 *             display-name="EJB Receiver Xbean"
 *
 * ... other javadoc tags ...
 */
public class ReceiverBean implements SessionBean, DOMSource {

Les interfaces les plus communes pour la balise ejb:bean sont :

name
Le nom de l'EJB (utilisé dans les descripteurs).
type
Définit le "type" du bean. Pour les session beans, c'est soit Stateful ou Stateless. Pour les entités (Entities), c'est CMP ou BMP.
jndi-name
Fourni le nom JNDI du bean qui sera utilisé dans les descripteurs de déploiement spécifique à la plate-forme (pour l'interface "remote").
local-jndi-name
Le même que jndi-name, mais utilisé pour l'interface locale (Local interface).
view-type
Indique quelles visibilités doivent être supportées par le bean. Soit remote, soit local, soit both.

Comme pour toutes les balises, vérifier la documentation pour voir la liste complète des options.

Balise: @ejb:env-entry

Cette balise définit une entrée d'environnement qui sera configurée dans le JNDI via le contexte spécifique java:comp/env. Nous allons définir une entrée d'environnement que le bean utilisera pour aller voir le prochain Xbean dans la chaîne :

/**
 *   This is the EJB Receiver Xbean
 *
 * ... other javadoc tags ...
 *
 *   @ejb:env-entry name="channelBean" type="java.lang.String"
 *                  value="com.your.ChannelBean"
 *
 * ... other javadoc tags ...
 */
public class ReceiverBean implements SessionBean, DOMSource {

Balise: @weblogic:pool

Maintenant, nous allons configurer les caractéristiques de mise en commun spécifiques aux plate-formes en utilisant WebLogic. Pour signifier que nous sommes dans un monde spécifique aux plate-formes (et donc spécifique envers un distributeur), nous avons l'espace de nom weblogic :

/**
 *   This is the EJB Receiver Xbean
 *
 * ... other javadoc tags ...
 *
 *   @weblogic:pool max-beans-in-free-pool="1000"   
 *                  initial-beans-in-free-pool="10"
 *
 * ... other javadoc tags ...
 */
public class ReceiverBean implements SessionBean, DOMSource {

Cette balise va configurer les paramètres de pooling dans le descripteur de déploiement spécifique  WebLogic (weblogic-ejb-jar.xml).

Il y a beaucoup d'autres balises au niveau des classes qui vous permettent de régler tout ce qui est possible dans le déploiement de descripteurs. Voici un bref aperçu de quelques balises standards que vous pourrez utiliser dans votre développement :

@ejb:bean
La seule balise obligatoire. Elle configure les bases du bean.
@ejb:home
Cette balise donne des informations sur les interfaces locales. Vous pouvez signifier à XDoclet d'étendre une interface dont les interfaces communes devraient être générées (none, remote, local,or both), placées dans un paquetage ou plus encore.
@ejb:interface
Identique à la balise home, mais configure des informations liées à l'interface du composant (remote and/or local).
@ejb:finder
Définit les méthodes finder sur une interface locale d'entity beans (entity beans home interface).
@ejb:select
Définit les méthodes select sur une interface locale d'entity beans (entity beans home interface).
@ejb:pk
Définit les clés primaires (primary key) pour un entity bean. XDoclet peut générer les classes des clés primaires pour vous.
@ejb:data-object
Les Data objects (objets valeurs) peuvent être générés automatiquement pour les entity beans par le biais de cette balise.
@ejb:ejb-ref
Configure les références EJB.
@ejb:ejb-external-ref
Configure les références EJB des beans qui sont localisées dans d'autres applications. Ici, il est nécessaire de passer les informations comme le type du bean, et les classes home/remote.
@ejb:resource-ref
Configure une référence de ressource.
@ejb:security-role-ref
Configure une référence de sécurité (security role reference).
@ejb:transaction
Définit le comportement transactionnel pour toutes les méthodes dans les interfaces distantes et locales (remote et home) du bean.
@ejb:permission
Permet au role-name d'appeler des méthodes dans les interfaces distantes et locales du bean.
@ejb:security-identity
Spécifie si l'identité de l'appelant (en terme de sécurité) doit être utilisé pour l'exécution des méthodes de l'ejb ou si une identité spécifique d'exécution doit être utilisée.

Définitions spécifiques au niveau des Méthodes

Nous voulons définir des balises au niveau de la méthode. Si nous voulons qu'une méthode donnée soit une partie d'une interface distante, nous l'indiquerons simplement à XDoclet via les balises de méthode :

  /**
   *  The method that the sender uses to pass the Document 
   *
   *  @ejb:interface-method view-type="remote"
   */
  public void documentReady(Document incomingDocument) {

Vous utiliserez toujours cette balise. Vous parcourrez les méthodes dans votre classe bean, et si vous souhaitez qu'un client puisse y accéder,  il suffit de placer cette balise au-dessus de la déclaration de la méthode. Si vou vouliez que cet accès se fasse via l'interface locale, il suffit de changer la valeur view-type à local.

Voici quelques autres balises de niveau méthode pour EJB :

@ejb:relation
Définit une relation pour un entity bean EJB2.0 CMP.
@ejb:home-method
Définit la méthode comme une méthode ejbHome*.
@ejb:pk-field
Met un indicateur (un flag) sur le champ the primary key.
@ejb:transaction
Définit le comportement transactionnel pour cette méthode (donner un attribut transactionnel valide : NotSupported | Supports | Required | RequiresNew | Mandatory | Never).
@ejb:permission
Définit les permissions des méthodes (Donner une liste de rôles (séparés par de virgules) qui seront autorisés à accéder à cette méthode).

Construction : Lancer XDoclet sur le Bean

Maintenant que nous avons une fichier source java, ReceiverBean.java, qui a été balisé pour XDoclet, nous allons devoir lancer XDoclet, lui demandant de nous générer tous les enrobages. La méthode préférée pour lancer l'outil est au travers du système Jakarta-Ant. Ant est le système de construction (compilation, déploiement, ..) Java omniprésent.

Le lancement de XDoclet par Ant se fait par l'insertion de tâches Ant spécialement développées par XDoclet dans le fichier de construction (build.xml). Il y a deux tâches principales : <ejbdoclet/> et <webdoclet/>. Comme nous travaillons avec un EJB, nous allons utiliser la target ejbdoclet dans notre fichier build.xml :

<target name="ejbdoclet" depends="prepare">

<taskdef name="ejbdoclet"
         classname="xdoclet.ejb.EjbDocletTask"
classpath="${java.class.path};${xdoclet.jar.path};
        ${log4j.jar.path};${ant.jar.path}"/>

<ejbdoclet
sourcepath="${java.dir}"
destdir="${generated.java.dir}"
ejbspec="2.0">

	<fileset dir="${java.dir}">
	    <include name="**/ReceiverBean.java" />
	</fileset>

	<remoteinterface/>
	<homeinterface/>
	<deploymentdescriptor destdir="${build.dir}/ejb/META-INF"/>

	<jboss     destdir="${build.dir}/ejb/META-INF"
	            version="2.4" xmlencoding="UTF-8" />
	<weblogic  destdir="${build.dir}/ejb/META-INF"  
	            xmlencoding="UTF-8"
	            validatexml="true"/>
	<webSphere destdir="${build.dir}/ejb/META-INF" />
	<orion     destdir="${build.dir}/ejb/META-INF" />

</ejbdoclet>
</target>

Il y a beaucoup d'information dans ce fichier. Nous allons donc le diviser et expliquer chacune des parties séparément :

Balise: <taskdef>

Avant tout, il va être nécessaire d'informer Ant de la signification de la nouvelle balise <ejbdoclet/>. Nous définissons donc le nom de la balise, la classe qui implémente cette balise et le chemin de celle-ci (classpath). Dans notre cas, nous utilisons les propriétés qui ont été définies au sommet du fichier build.xml qui recense les différentes bibliothèques requises :

<taskdef name="ejbdoclet" classname="xdoclet.ejb.EjbDocletTask"
classpath="${java.class.path};${xdoclet.jar.path};${log4j.jar.path};
${ant.jar.path}"/>

Balise: <ejbdoclet>

Cette balise englobante indique à Ant de lancer la tâche EJBDoclet. Nous indiquons où se trouve notre code (sourcepath), où générer le descripteur XML et les sources Java (destdir), et la version de l'EJB spec auquel nous nous référons :

<ejbdoclet
 sourcepath="${java.dir}"
 destdir="${generated.java.dir}"
 ejbspec="2.0">

Balise: <fileset>

Nous indiquons à la balise <ejbdoclet> où trouver nos beans, en utilisant la directive <fileset>. Notre exemple trouvera tout le code nommé ReceiverBean.java situé dans le sous-répertoire de ${java.dir}:

<fileset dir="${java.dir}">
    <include name="**/ReceiverBean.java" />
 </fileset>

Balises: ..interface et deploymentdescriptor

Le prochain groupe de balises assure la génération des interfaces distantes, locales, et les descripteurs XML standards de déploiement (ejb-jar.xml) :

<remoteinterface/>
<homeinterface/>
<deploymentdescriptor destdir="${build.dir}/ejb/META-INF"/>

Balises spécifiques à la plate-forme : Interfaces et Descripteurs de Déploiement  XML

Le dernier groupe de balises permet la génération des descripteurs de déploiement spécifiques aux plate-formes. Si vous ne déployez vos EJBs que sur un type de serveur, vous n'aurez qu'une entrée à spécifier. Dans notre cas, notre Xbean EJB devra être apte à être déployé sur autant de serveurs spécifiques (aux distributeurs) que possible. Toutes les balises spécifiques aux plate-formes ont été ajoutées. On remarquera que tous ces fichiers spécifiques aux plate-formes (et au distributeurs) ont été générés sans même que l'on ne connaisse les particularités de ces serveurs applicatifs.

<jboss     destdir="${build.dir}/ejb/META-INF"
           version="2.4" xmlencoding="UTF-8" />
<weblogic  destdir="${build.dir}/ejb/META-INF"  
           xmlencoding="UTF-8" 
           validatexml="true"/>
<webSphere destdir="${build.dir}/ejb/META-INF" />
<orion     destdir="${build.dir}/ejb/META-INF" />

Maintenant, pour tout construire pour cet EJB, il suffit de lancer Ant dans le même répertoire que celui contenant le fichier build.xml. Il faut s'assurer que les bibliothèques Ant (ant.jar, jaxp.jar, un parseur XML) et que le fichier xdoclet.jar  sont dans le CLASSPATH.  Par exemple sous Windows on pourrait avoir :

% set CLASSPATH=%CLASSPATH%;c:/lib/ant.jar;c:/lib/jaxp.jar;c:/lib/xerces.jar;
  c:/lib/xdoclet.jar;c;/lib/log4j.jar;c:/lib/ejb.jar

% ant ejbdoclet
[lance ant sur la tâche ejbdoclet]

% ant
[lance ant sur la tâche par défaut. Dans ce cas, cela va générer les sources,
descripteurs xml, puis les compiler, et empaqueter le tout comme un fichier ejb-jar]

Pour télécharger tous les fichiers de cet exemple cliquez sur l'image :  

Remarque : cet exemple est issu de l'article de Dion Almaer du site OnJava.com

Suite