Fiches / Articles

Cadre Fonctionnel

Développement d’un session bean utilisant l’API JMS

Cadre Technique

NT / JMS, JonAS (Java Open Application Server), Joram

Identifiant 

JMS_EJB_01

Référent technique 


Version 

1.0

Auteur 

Alexandre Brillant

Date 

04/01

Source

Documentation Joram, http://developer.java.sun.com/

Cibles 

SB_EJB_01, DEV_JMS_01

Dépendance 

INS_EJB_01, INS_JMS_01

Cet exemple délimite l’utilisation de l’API JMS dans jonas. Il reste cependant un exemple standard pour la transmission d’un message via un session bean.


La réception de message ne peut cependant pas se faire de manière asynchrone avec Jonas car cela nécéssite l’utilisation de l’API EJB 2.0 et en particulier le support d’un message-driven bean (MDB).

Ces programmes nécéssitent pour leur exécution les serveurs Jonas et Joram. Reportez-vous à la fiche INS_EJB_01 pour connaître la démarche d’installation.

- Exemple d'interface pour le cycle de vie :


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, RemoteException;
}

- Exemple d’interface des opérations :


package hexadev;

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

/**
 * Interface pour le client distant. Ce bean permet
 * l'émission d'un message avec l'API JMS
 */

public interface Ab extends EJBObject {    

	/**
	 * Exemple de publication d'un message
	 */
	public void publishMessage(String value) throws RemoteException;

}

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


package hexadev;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.jms.Topic;
import javax.jms.*;

/**
 Exemple d'implémentation d'un session bean
 réalisant la transmission d'un Message. 
 Utiliser le programme JMSAdmin pour amorcer
 un Topic et une TopicConnectionFactory
 */
public class AbBean implements SessionBean {

 protected SessionContext sessionContext = null;
 protected org.objectweb.jonas.jms.TopicConnectionFactory factory = null;
 protected Topic topic = null;

 /**
  * Création du Bean 
  */
 public void  ejbCreate() {
	try {
		 
           InitialContext ctx = new InitialContext();
	   Object _obj = ctx.lookup( "java:comp/env/jms/TopicFact" );
	   factory = ( org.objectweb.jonas.jms.TopicConnectionFactory) _obj;
	   _obj = ctx.lookup( "Topic1" );
	   topic = (Topic)_obj;
	} catch( Exception exc ) {
	System.err.println( exc.getMessage() );
	exc.printStackTrace();
	}
 }


 /**
  * 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;
 }
  
 /**	
  * Exemple de publication d'un message
  */ 
  
 public void publishMessage( String value ) {
   try {
   javax.jms.TopicConnection tc =
     (javax.jms.TopicConnection)factory.createTopicConnection();
  tc.start();
	
   javax.jms.TopicSession session =
(javax.jms.TopicSession)tc.createTopicSession( false,
Session.AUTO_ACKNOWLEDGE );
	 
  TextMessage text = session.createTextMessage( value );
	
  // Création d'un agent de transmission du message
	 
  javax.jms.TopicPublisher tp =
(javax.jms.TopicPublisher)session.createPublisher( topic );
	 
  tp.publish( text );
  session.close();
  tc.close();}
    catch( Exception exc ) {
       exc.printStackTrace();
    }
 }
}

Remarque : Dans cet exemple, jms/TopicFact lors de la création du session bean représente un accès vers une factory de connection JMS. Cette dernière est déclarée dans le descripteur jonas-ejb-jar.xml.

Fichier ejb-jar.xml :


<!DOCTYPE ejb-jar SYSTEM "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.Ab</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>

      <resource-ref>

	<res-ref-name>jms/TopicFact</res-ref-name>

	<res-type>javax.jms.TopicConnectionFactory</res-type>

	<res-auth>Container</res-auth>

      </resource-ref>

    </Sessionp>

  </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 "jonas-ejb-jar.dtd">




<jonas-ejb-jar>

  <jonas-session>

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

    <jndi-name>AbHome</jndi-name>

    <jonas-resource>

      <res-ref-name>jms/TopicFact</res-ref-name>

      <jndi-name>TopicFactory1</jndi-name>

    </jonas-resource>

  </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" ),
	    hexadev.AbHome.class);

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

	Ab ab1 = null;

	try {

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

	    	// Utilisation
	    	ab1.publishMessage( "Test1"
);

	    	// Suppression
	    	ab1.remove();

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

- Exemple d’administration JMS :


package hexadev;

import javax.jms.*;
import javax.naming.*;
import fr.dyade.aaa.joram.XATopicConnectionFactory;
import fr.dyade.aaa.joram.Admin;
import org.objectweb.jonas.jms.TopicConnectionFactory;

/**
  Connection au serveur MOM et déclaration 
  de files de messages via le service de désignation
  JNDI( Java Naming Directory Interfaces )
  */
  public class JMSAdmin {
  
 public static void main( String[] args ) throws Exception {
	System.out.println( "Starting JMSAdmin..." );
	// Connexion au serveur MOM joram
	Admin admin = new Admin();
	// Création d'une factory de files de message supportant des
	// transactions par un serveur EJB
	XATopicConnectionFactory topicFactory = admin.createXATopicAgentClient();
	// Création d'une file
	boolean again = true;
	Topic topic = null;

	while( again ) {
	 
	   try {
	     topic = topicFactory.createNewTopic();
	     again = false;
	     break;
	   } catch( Exception exc ) {}
	}

	System.out.println( "Topic created ..." );
	admin.close();

	// Déclaration de la file de messages dans JNDI
	InitialContext context = new InitialContext();
	String internalConnectionFactory = "TopicFactoryRef1";
	context.rebind( internalConnectionFactory, topicFactory );

	// Création d'une factory propre à Jonas utisant la filede messages QueueFactory1
	TopicConnectionFactory jonasFactory = new TopicConnectionFactory( internalConnectionFactory );

	context.rebind( "TopicFactory1", jonasFactory );
	context.rebind( "Topic1", topic );
  
 }
}

Remarque : Ce programme n’a qu’un rôle de référencement sur JNDI d’un  « Topic » et d’une factory

Créer le répertoire classes.



Rem  Check environment variables:

if "%JONAS_ROOT%"=="" Goto SetRoot

@Echo on

Rem set the Environment Variables

set XTRA_CLASSPATH=classes

call %JONAS_ROOT%\bin\nt\config_env.bat

@Echo on

Rem  Compiles the source files

javac -d classes Ab.java AbBean.java
AbHome.java ClientAb.java JMSAdmin.java

 @Echo on

Rem  Generates the interposition classes and compiles them

call %JONAS_ROOT%\bin\nt\GenIC.bat -d
classes ejb-jar.xml

@Echo off

Goto End

:SetRoot
@echo "JONAS_ROOT must be set"
Goto End

:End

Test :

1°) Mettre à jour la variable d’environnement XTRA_CLASSPATH pour contenir le répertoire classes

2°) Exécuter rmiregistry

3°) Exécuter EJBServer

4°) Exécuter le serveur Joram :


start "Server AAA" 
call java -DTransaction=NullTransaction fr.dyade.aaa.agent.AgentServer 0
./s0

5°) Exécuter le programme d’administation :

start java hexadev.JMSAdmin

6°) Exécuter le client de test :

java hexadev.ClientAb