Objectif : installer un EJB dans le serveur d'applications JOnAS et faire un appel via la console DOS.

JOnAS permet de mettre sur le réseau RMI (CORBA) des objets, accessibles par des applications J2EE hébergées, mais aussi d'autres application, pas forcément J2EE, et pas forcément en JAVA. Dans cet exemple, l'objet est accédé par un programme DOS (en JAVA), un client de JOnAS.

Coté serveur :

Coté client :

Fichiers à destination du serveur


"HelloWorld.java"
package helloWorld;

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

public interface HelloWorld extends EJBObject
{
  public String sayHello() throws RemoteException;
}

Cette interface permet de spécifier quelles méthodes sont utilisables avec l'objet partagé. Dans notre cas, une seule méthode "sayHello()" sera le point d'entrée du l'objet.

"HelloWorldBean.java"
package helloWorld;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class HelloWorldBean implements SessionBean
{
  protected SessionContext ctx;
  private static final long serialVersionUID = 1L;
  public String sayHello()
  {
    return "Hello, world !";
  }
  
  public void ejbCreate() {}
  public void ejbActivate() throws EJBException, RemoteException {}
  public void ejbPassivate() throws EJBException, RemoteException {}
  public void ejbRemove() throws EJBException, RemoteException {}
  public void setSessionContext(SessionContext arg0) 
    throws EJBException, RemoteException
  {
    ctx = arg0;
  }
}

Notre Bean sera pourvu d'un numéro de série (unique dans le serveur qui l'héberge). Pour notre cas, peut importe.

Il implémente la péthode déclarée dans son interface : "sayHello()".

Il impémente aussi les autres méthodes de SessionBean :
"ejbCreate()" : appel lors de la création du Bean en session
"ejbActivate()" : appel lors de l'activation du Bean (après sa création, avant son utilisation)
"ejbPassivate()" : appel lors de la desactivation du Bean (après la fin de son utilisation)
"ejbRemove()" : appel lors de la suppression du bean en session

Question : Quel lien y a-t-il entre l'EJBObject et le SessionBean ?
Réponse : ??
Question : Faut-il implémenter toutes les méthodes ?
Réponse : non, il est seulement necessaire d'implémenter "ejbActivate()", "ejbPassivate()", "ejbPassivate()", "ejbRemove()" et "setSessionContext()".
"HelloWorldHome.java"
package helloWorld;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface HelloWorldHome extends EJBHome
{
  public HelloWorld create() throws CreateException, RemoteException;
}

Cette surcharge permet uniquement de préciser que l'objet retourné par la méthode "create()" est de la classe "HelloWorld". 

"ejb-jar.xml"
<?xml version="1.0" encoding="ISO-8859-1"?>
<ejb-jar>
  <description>HelloWorld deployment descriptor</description>
  <display-name>HelloWorld</display-name>
  <enterprise-beans>
    <session>
      <description>HelloWorld deployment descriptor</description>
      <display-name>HelloWorld</display-name>
      <ejb-name>HelloWorld</ejb-name>
      <home>helloWorld.HelloWorldHome</home>
      <remote>helloWorld.HelloWorld</remote>
      <ejb-class>helloWorld.HelloWorldBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>
  <assembly-descriptor>
    <container-transaction>
      <method>
        <ejb-name>HelloWorld</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

Dans la description de l'EJB, on retrouve toutes les classes définies précédemment, avec leur package.

"jonas-ejb-jar.xml"
<?xml version="1.0" encoding="ISO-8859-1"?>
<jonas-ejb-jar>
  <jonas-session>
    <ejb-name>HelloWorld</ejb-name>
    <jndi-name>myHelloWorld</jndi-name>
  </jonas-session>
</jonas-ejb-jar>

L'EJB "HelloWorld" est accessible sur le réseau par l'identifiant "myHelloWorld". Coté client, cette information est primordiale,en plus des classes et interfaces.

Fichiers à destination du client

"HelloClient.java"
package client;

import helloWorld.HelloWorld;
import helloWorld.HelloWorldHome;

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

public class HelloClient
{
  public static void main(String[] args)
  {
    Context initialContext = null;
    try
    {
      initialContext = new InitialContext();
    } catch (Exception e)
    {
      System.err.println("Cannot get initial context for JNDI: " + e);
      System.exit(2);
    }
    try
    {
      Object objref = initialContext.lookup("myHelloWorld");
      HelloWorldHome home = (HelloWorldHome)PortableRemoteObject.narrow(
          objref, 
          HelloWorldHome.class);
      HelloWorld myHelloWorld = home.create();
      String message = myHelloWorld.sayHello();
      System.out.println(message);
    } catch (Exception e)
    {
      System.err.println(" Erreur : " + e);
      System.exit(2);
    }
  }
}

Le code client se décompose en :

  1. Récupérer du contexte : "initialContext"
  2. Rechercher l'objet référencé par "myHelloWorld"
  3. Récupérer la fabrique
  4. Créer une instance de "HelloWorld" via la fabrique
  5. Appel de la méthode "sayHello()"
  6. Affichage du message
Question : Sur quel contexte est-on placé ? Comment changer de contexte ?
Reponse : ???

Compilation

"build.xml"
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="FirstEJB" basedir="." default="deploy">

<property name="project.libs" value="C:\home\j_co\apps\JOnAS-4.7.7\lib" />
<property name="classes.dir" value="classes" />
<property name="deploy.dir" value="C:\home\j_co\workspace\FirstEJB\deploy" />
<property name="src.dir" value="."></property>


<path id="base.path">
<fileset dir="${project.libs}">
<include name="**/*.jar" />
</fileset>
</path>

<target name="clean" description="Delete all generated files">
<delete dir="${classes.dir}" />
</target>

<target name="compile" description="Compiles the Task">
<mkdir dir="${classes.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<classpath>
<path refid="base.path" />
</classpath>
</javac>
</target>

<target name="deploy" description="JARs the Task" depends="compile">
<jar destfile="${ant.project.name}.jar">
<metainf dir="${src.dir}/META-INF" />
<fileset dir="${classes.dir}">
<include name="**/*.class" />
</fileset>
</jar>
</target>

<target name="undeploy" description="Undeploy jar from server">
<delete file="${deploy.dir}/${ant.project.name}.jar" />
</target> </project>

Le fichier "build.xml" permet d'automatiser la compilation et la génération du JAR à déployer.

Execution du test

Une fois le JAR généré, il faut le déployer dans JOnAS, en utilisant par exemple l'interface d'administrationWEB.

Le JAR est ensuite copié, modifié et stocké dans le répertoire JONAS_DIR/ejbjars/. C'est ce JAR qu'il faut utiliser pour le client. Le JAR formé avec le "build.xml" ne contient pas les classes STUB ni SKEL de l'EJB.

Il faut copier le fichier JONAS_DIR/ejbjars/FirstEJB.jar dans un répertoire de test et lancer la commande suivante :

jclient -cp C:\home\j_co\apps\JOnAS-4.7.7\ejbjars\FirstEJB.jar client.HelloClient

Conclusion

Ce petit exemple ne montre qu'un des quatre types d'EJB...
Personnellement, je trouve ce cas (minimal) asser complexe : les configurations par défaut (rien n'est spécifié), l'astuce de prendre un autre JAR que celui qu'on a créé.
Contrairement à CORBA, on ne peut pas changer de langage pour developper son application.

Comment l'éviter ?

L'utilisation des EJB est possible lorsque l'option "base de données" n'est pas envisageable et que l'autre recours est le "fichier" pour communiquer entre les applications. On peut aussi penser à un serveur HTTP (ou d'un autre protocole) qui reçoit des messages en XML, mais la spécification et le respect des règles de formatage est certainement plus complexe à mettre en oeuvre et à faire respecter.
Autre piste : "Hibernate". Ce principe revient à mettre sous forme de table SQL un objet que l'on voudrait sauvegarder en base.

Finalement, pratique !

Lorsqu'on se place dans un environnement JAVA, on ne quitte plus ce langage d'une application à une autre. Tous le developpeurs ont la contrainte de respecter la même syntaxe (appel de méthodes), de lire les mêmes spécifications (fichiers "ejb-jar.xml").




Page accedée 1 fois.