Fiches / Articles

Cadre Fonctionnel

Développement d’un session bean

Cadre Technique

NT/JonAS (Java Open Application Server)

Identifiant 

SB_EJB_01

Référent Technique 


Version 

1.0

Auteur 

Alexandre Brillant

Date 

04/01

Source

Documentation JonAS

Dépendance 

INS_EJB_01

Cible 

BD_EJB_01



Les session bean ont une courte durée de vie. Ils agissent principalement pour réaliser une opération. Il n'ont pas pour rôle de stocker des données. Cependant, on distingue les 'stateful' et 'stateless' beans respectivement pour conserver entre plusieurs appels l'état du bean et pour ne permettre que l'appel de méthode sans conservation de l'état. Dans ce dernier cas, il n'y a pas de garanti qu'entre deux appels la même instance de bean soit appelée, cela permet donc une utilisation par plusieurs utilisateurs.


- Transactions :


Les transactions sont manipulables dans le cas 'stateful' par l'interface SessionSynchronization comprenant les méthodes afterBegin, beforeCompletion, afterCompletion respectivement appelée lors d'un début de transaction, avant un "commit" et aprés un "rollback" ou un "commit".


Il existe deux types de transaction :



- Conception :


Différentes interfaces sont nécessaires. Une interface (Home) s'occupe du cycle de vie du bean (activation, destruction...). Une autre interface (Bean) concerne davantage les fonctionnalités du bean. Ces interfaces masquent la provenance des implémentations et en particulier le transfert des amorces RMI pour la relation Client/Serveur. Côté serveur,un containeur offre toutes les fonctions de manipulation du bean.



La communication Client/Serveur utilise un mécanisme à base de pont. Chaque intervenant se trouve à une extrémité du pont et croit être directement en contact avec l'autre intervenant. Les amorces et squelettes implémentent l'interface client correspondant aux services du bean et redirige les appels locaux avec le serveur. Les messages circulant sur le pont correspondent aux arguments et retourne des méthodes et fonctions.


Derrière les squelettes, le serveur maintient une collection ou pool d’implémentation correspond aux objets construits par le développeur. Ce sont eux qui effectueront en réalité tous les traitements, cependant par le biais des squelettes, ils n’auront pas de perception d’une communication avec un client distant.


Les concepts de Serveur et Containeur sont distingués par la norme EJB. Le premier contient toutes les fonctionnalités de bases des containeurs (transaction…). Ces derniers se chargent de l’intégration des beans utilisateur. Concernant JonAS, nous n’en ferons pas la distinction dans la suite.


Les différentes étapes de construction d'un EJB Session sont décrites dans la suite. Une convention de nommage indispensable consiste à faire suivre le nom d'une classe par une série de préfixe dépendant de son rôle (Home, Bean, Client).



package hexadev;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

/**
 * Interface de gestion du cycle de vie du bean. 
 */
public interface AbHome extends EJBHome {
/**
 * Création d'un bean de type Ab
 */
 Ab create() throws CreateException, RmiException;
}


Remarque : Toutes les méthodes de cette interface devront être présentes dans l’implémentation du bean et être préfixées par le nom ‘ejb’.


- Exemple d'interface des opérations à fournir :



package hexadev;

import java.rmi.RemoteException;
import javax.ejb.EJBObject;

/**
 * Interface du bean utilisée par un client distant.
 */
public interface Ab extends EJBObject {    

/**
 * Exemple d'opérations 
 */
 public void operation1(int value) throws RemoteException;
 public void operation2(int value) throws RemoteException;

}


Remarque : Cette interface servira à la construction des amorces et squelettes, elle intègre les problèmes de communication par l'exception RemoteException. Elle n'est en théorie par directement implémentée par le bean utilisateur contenant les diverses opérations.

- Exemple d'implémentation des opérations:


package hexadev;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
/** * Exemple d'implémentation du bean contenant * operation1 et operation2 */ public class AbBean implements SessionBean { protected SessionContext sessionContext = null; /** * Création du bean */ public void ejbCreate() {} /** * Activation du bean */ public void ejbActivate() {} /** * Désactivation du bean */ public void ejbPassivate() {} /** * Suppression du bean */ public void ejbRemove() { } /** * Récupère le contexte du bean. Utilisable pour récupérer des * propriétés statiques du fichier ejb-jar.xml */ public void setSessionContext(SessionContext sessionContext) { this.sessionContext = sessionContext; } /** * Réalisation des opérations utilisateurs */ public void operation1( int value ) { System.out.println( "{" + this + "} " + "Operation 1:" + value ); } public void operation2( int value ) { System.out.println( "{" + this + "} " +"Operation 2:" + value ); } } }


correspondent respectivement à une sortie du pool des beans disponibles et une entrée dans ce même pool. Elles peuvent être utilisées pour allouer/désallouer des ressources sensibles (base de données, JMS...).


- Exemple de descripteur XML


Ce fichier ejb-jar.xml permet de décrire les différentes parties de l'EJB et intègre des propriétés statiques (alias pour une base de données...) utilisable par l'objet SessionContext. Attention à bien respecter le path vers les DTD (*.dtd) dans l’en-tête du document.



<!DOCTYPE ejb-jar SYSTEM "../../../xml/ejb-jar_1_1.dtd">

<ejb-jar>

  <description>Exemple AB</description>
<enterprise-beans>

    <session>

      <ejb-name>Ab</ejb-name>

      <home>hexadev.AbHome</home>

      <remote>hexadev.</remote>

      <ejb-class>hexadev.AbBean</ejb-class>

      <session-type>Stateless</session-type>
     
<transaction-type>Container</transaction-type>
<env-entry>

	<env-entry-name>prop1</env-entry-name>

	<env-entry-type>java.lang.String</env-entry-type>

	<env-entry-value>prop1 value</env-entry-value>

      </env-entry>

    </session>

  </enterprise-beans>

  <assembly-descriptor>

    <container-transaction>

      <method>

	<ejb-name>Ab</ejb-name>

	<method-name>*</method-name>

      </method>

      <trans-attribute>Required</trans-attribute>
    </container-transaction>

  </assembly-descriptor>

</ejb-jar>


Fichier jonas-ejb-jar.xml :



<!DOCTYPE jonas-ejb-jar SYSTEM "../../../xml/jonas-ejb-jar.dtd">

<jonas-ejb-jar>
<jonas-session>

    <ejb-name>Ab</ejb-name>
<jndi-name>AbHome</jndi-name>

  </jonas-session>

</jonas-ejb-jar>


package hexadev;

import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;

/**
 * Exemple de client pour le bean Ab
 */
public class ClientAb {

    public static void main(String args[]) { 


	// Contexte de communication avec le
serveur EJB
Context initialContext = null;	
	AbHome home = null;

	try {
	    initialContext = new InitialContext();
	    home = ( AbHome )PortableRemoteObject.narrow( 
	    initialContext.lookup( "AbHome" ), AbHome.class);
	} catch (Exception e) {
e.printStackTrace();
	}

	Ab ab1 = null;
	try {

		// Création du bean
ab1 = home.create();

	    	// Utilisation
	    	ab1.operation1( "Test1" );
	    	ab1.operation2( "Test2" );

	    	// Suppression
	    	ab1.remove();


	} catch (Exception e) {
		e.printStackTrace();

	}
    }

}

Le plus simple est de disposer d’un script de compilation contenant :


call %JONAS_ROOT%\bin\nt\config_env.bat javac -d classes Ab.java AbBean.java AbHome.java ClientAb.java
call %JONAS_ROOT%\bin\nt\GenIC.bat -d classes ejb-jar.xml


La première ligne initialise la variable d’environnement CLASSPATH. La deuxième ligne réalise la compilation du session bean et dépose les classes dans le répertoire courant classes. Enfin, la dernière ligne construit le squelette et l’amorce permettant au client de communiquer avec le serveur à l’aide de l’outil GenIC.


- Test :


Il faut maintenant indiquer la présence de l’EJB à JOnAS. Cela peut se faire à partir du fichier jonas.properties. Ce dernier se trouve dans le répertoire d’installation de JonAS et dans le répertoire courant de l’exemple.


Une autre possibilité est d’utiliser la console d’administration jonasAdmin et la commande add suivie d’un path vers un fichier ejb-jar.xml.


Exemple :


jonas.beans.descriptors ejb-jar.xml


JonAS doit aussi trouver les classes de l’utilisateur. Cela peut se faire simplement en modifiant le fichier config_env.bat ou en changeant la variable d’environnement XTRA_CLASSPATH.


Exemple :


Set XTRA_CLASSPATH=classes