# EJB/JMS User's Guide

1. JMS installation and configuration aspects
2. Writing JMS operations within an enterprise bean
3. Some programming rules and restrictions
4. JMS administration
5. Running an EJB performing JMS operations
6. A JMS EJB example

Asynchronous EJB method invocation is provided by the Message-driven Beans, as specified in the EJB 2.0 specification. Moreover, it is possible for any EJB component (session, entity, Message-driven) to send or synchronously receive JMS messages, and this within the scope of a global transaction managed by the EJB Server. The bean programmer has the possibility to use resources (by the way of resource references) that may be JDBC (a DataSource) or JMS (a ConnectionFactory) connection factories. Thus, the bean programmer is able to provide JMS code inside of an EJB method, in order to send a message toward a JMS Queue or Topic. The EJB Container is able to take into account these JMS operations within a global EJB transaction which may include other resources such as databases.

Details about JMS should be found in the Java Message Service Specification 1.0.2.

In the JOnAS JMS integration, JOnAS makes use of a third party JMS implementation: currently the Joram opensource is integrated and delivered with JOnAS, the SwiftMQ product may also be used, other JMS provider implementations may easily be integrated. The JMS administered objects used by the EJB components, such as the connection factories and the destinations, may be created previously to the EJB execution, by the way of the proprietary JMS implementation administration facilities. However, JOnAS provides "wrappers" upon such JMS administration APIs, allowing simple administration operations to be achieved automatically by the EJB server itself. This avoids the deployer to cope with proprietary administration APIs or tools. See JMS Administration.

## JMS installation and configuration aspects

To use JMS with the JOnAS you do not need to perform any installation or configuration operation, JOnAS contains:

- the Java[TM] Message Service API 1.0.2a, currently integrated with the JOnAS distribution,
- a JMS implementation, currently the OpenSource Joram (http://www.objectweb.org/joram), it is integrated with the JOnAS distribution, so you do not have to install it.

You may of course decide to use another JMS implementation. Currently the SwiftMQ product has been tested.

## Writing JMS operations within an enterprise bean

In order to send (or synchronously receive) JMS messages, the bean programmer should have access to JMS administered objects, i.e. Connection Factories to create connections to JMS resources, and Destination objects (Queue or Topic) which are the JMS entities used as destination within JMS sending operations. Both are made available through JNDI by the JMS provider administration facility.

### Accessing the Connection Factory

The EJB 1.1 specification introduces the concept of "Resource Manager Connection Factory References", which are objects used to create connections to a resource manager within an EJB component. Up to now, two kinds of Resource Manager Connection Factories are considered in the EJB specification

- the DataSource objects (javax.sql.DataSource) represent connection factories for JDBC connection objects,
- the JMS Connection factories (javax.jms.QueueConnectionFactory and javax.jms.TopicConnectionFactory) are connection factories for JMS connection objects.

The second ones should be used by an EJB to get JMS Connection Factories. The standard deployment descriptor should contain the following element :

          <resource-ref>
          <res-ref-name>jms/conFact</res-ref-name>
          <res-type>javax.jms.QueueConnectionFactory</res-type>
          <res-auth>Container</res-auth>
          </resource-ref>

This means that the bean programmer will have access to a QueueConnectionFactory object using the JNDI name java:comp/env/jms/conFact. To obtain the factory object the EJB should contain the code :

          QueueConnectionFactory qcf = (QueueConnectionFactory)
                     ctx.lookup("java:comp/env/jms/conFact");

The mapping to the actual JNDI name of the connection factory (as assigned by the JMS provider administration tool), `QCF` in the example, will be done in the JOnAS specific deployment descriptor with the following element:

          <jonas-resource>
          <res-ref-name>jms/conFact</res-ref-name>
          <jndi-name>QCF</jndi-name>
          </jonas-resource>

### Accessing the Destination Object

Accessing a JMS destination within the code of an EJB component will require to use a resource environment reference, as defined in the EJB specification 2.0. A resource environment reference is represented in the standard deployment descriptor as follows:

          <resource-env-ref>
          <resource-env-ref-name>jms/stockQueue</resource-env-ref-name>
          <resource-env-ref-type>javax.jms.Queue<resource-env-ref-type>
          </resource-env-ref>

And the EJB code should contain

          Queue q = (Queue) ctx.lookup("java:comp/env/jms/stockQueue");

the mapping to the actual JNDI name (e.g. "myQueue") being done in the JOnAS specific deployment descriptor in the following way:

          <jonas-resource-env>
          <resource-env-ref-name>jms/stockQueue</resource-env-ref-name>
          <jndi-name>myQueue<jndi-name>
          </jonas-resource-env>

### Writing JMS Operations

A typical EJB method performing some JMS operations will look like the following (for sending a message):

         void sendMyMessage() {

           QueueConnectionFactory qcf = (QueueConnectionFactory)
                   ctx.lookup("java:comp/env/jms/conFact");
           Queue queue = (Queue) ctx.lookup("java:comp/env/jms/stockQueue");
           QueueConnection qc = qcf.createQueueConnection();
           QueueSession qs = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
           QueueSender sender = qs.createSender(queue);
           ObjectMessage msg = qs.createObjectMessage();
           msg.setObject("Hello");
           sender.send(msg);
           qs.close();
           qc.close();
         }

It is also possible for an EJB component to synchronously receive a message (asynchronous message reception is not possible in session or entity beans, it should be done through message-driven beans). An EJB method performing synchronous message reception on a queue is illustrated below:

        public String recMsg() {
            QueueConnectionFactory qcf = (QueueConnectionFactory)
                   ctx.lookup("java:comp/env/jms/conFact");
            Queue queue = (Queue) ctx.lookup("java:comp/env/jms/stockQueue");
            QueueConnection qc = qcf.createQueueConnection();
            QueueSession qs = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
            QueueReceiver qr = qs.createReceiver(queue);
            qc.start();
            ObjectMessage msg = (ObjectMessage) qr.receive();
            String msgtxt =  (String) msg.getObject();
            qs.close();
            qc.close();
            return msgtxt;
        }

A method that performs JMS operations should always contain the session create and close statements, as follows:

         public void doSomethingWithJMS (...) {
           ...
           session = connection.create<Queue|Topic>Session(...);
           ... // JMS operations
           session.close();
         }

Of course, the contained JMS operations will be part of the transaction, if there is one, when the EJB server executes the method.

Be careful to never send and receive a given message in the same transaction, since the JMS sending operations are actually performed at commit time only !

The examples above illustrate point to point messaging, you may of course develop EJB components using the publish/subscribe JMS API, i.e. use the Topic instead of the Queue destination type. This allows you to broadcast a message to several message consumers at a time. The example below illustrates a typical EJB method for publishing a message on a JMS topic.

        public void sendMsg(java.lang.String s) {
            TopicConnectionFactory tcf = (TopicConnectionFactory)
                           ictx.lookup("java:comp/env/jms/conFactSender");
            Topic topic = (Topic) ictx.lookup("java:comp/env/jms/topiclistener");
            TopicConnection tc = tcf.createTopicConnection();
            TopicSession session = tc.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
            TopicPublisher tp =  session.createPublisher(topic);
            ObjectMessage message = session.createObjectMessage();
            message.setObject(s);
            tp.publish(message);
            session.close();
            tc.close();
        }

### Transactions and JMS sessions within an EJB component

JMS session creation within an EJB component will result in different behaviors depending if the session is created at execution time within or outside a transaction ! In fact, the parameters of the `create<Queue|Topic>Session(boolean transacted, int acknowledgeMode)` method are never taken into account within an EJB.

- If the session creation occurs outside of a transaction, the parameters will be considered as being `transacted = false` and `acknowledgeMode = AUTO_ACKNOWLEDGE`. Which means that each operation of the session is immediately executed (the session is not transacted, it could not be since the use of commit and rollback JMS session methods is not allowed within an EJB).
- If the session creation occurs inside a transaction, the parameters have no meaning, the session may be considered as transacted, the commit and rollback operations being handled by the EJB server at the level of the associated XA resource.

## Some programming rules and restrictions

This section presents some programming restrictions and rules for using JMS operations within EJB components.

### Authentification

If your JMS implementation performs user authentification you may use the following methods on Connection Factories:

- `createQueueConnection(String userName, String password)` on `QueueConnectionFactory`
- `createTopicConnection(String userName, String password)` on `TopicConnectionFactory`

### Connection Management

Depending on your JMS implementation and on your application, you may choose to keep your JMS connections opened for the life of your bean instance, or for the duration of your method call. These two programming modes are illustrated below (this example illustrates a stateful session bean):

    public class EjbCompBean implements SessionBean {
        ...
        QueueConnectionFactory qcf = null;
        Queue queue = null;

        public void ejbCreate() {
           ....
           ictx = new InitialContext();
           qcf = (QueueConnectionFactory)
              ictx.lookup("java:comp/env/jms/conFactSender");
           queue = (Queue) ictx.lookup("java:comp/env/jms/queue1");
        }

        public void doSomethingWithJMS (...) {
           ...
           QueueConnection qc = qcf.createQueueConnection();
           QueueSession session = qc.createQueueSession(...);
           ... // JMS operations
           session.close();
           qc.close();
         }

        ...
    }

If you would like to keep the connection opened during the life of your bean instance , the following programming style could be preferred, which avoids many connection opening and closing operations:

    public class EjbCompBean implements SessionBean {
        ...
        QueueConnectionFactory qcf = null;
        Queue queue = null;
        QueueConnection qc = null;

        public void ejbCreate() {
           ....
           ictx = new InitialContext();
           qcf = (QueueConnectionFactory)
              ictx.lookup("java:comp/env/jms/conFactSender");
           queue = (Queue) ictx.lookup("queue1");
           qc = qcf.createQueueConnection();
        }

        public void doSomethingWithJMS (...) {
           ...
           QueueSession session = qc.createQueueSession(...);
           ... // JMS operations
           session.close();
        }

        public void ejbRemove() {
           qc.close();
        }

        ...
    }

Be careful that maintaining JMS objects in the bean state, is not always possible depending on the type of the bean:

- In case of a stateless session bean, the bean state is not maintained across method calls, thus always initialize and define your JMS objects in each method performing JMS operations !
- In case of an entity bean, an instance may be passivated, and only the persistent part of the bean state is maintained, thus it is recommended to initialize and define the JMS objects in each method performing JMS operations. If you define these objects in the bean state, you may initialize them in the `ejbActivate` method (if you create the connection in the `ejbActivate` method, do not forget to close it in the `ejbPassivate` method).
- In case of a stateful session bean, the example above, you may define JMS objects in the bean state. Stateful session bean instances may be passivated (not in the current version of JOnAS). As connection factories and destinations are serializable objects, you may initialize them in ejbCreate and that's all. However be careful that for a connection, you will certainly need to close it in `ejbPassivate` (and set the state variable to `null`), and to re-create it in `ejbActivate`.

### Starting Transactions after JMS Connection or Session creation

In case of bean-managed transaction, it is currently not possible to start a transaction after the creation of a JMS session and to have the JMS operations involved in the transaction. In the following code example, the JMS operations will not occur within the `ut` transaction:

    public class EjbCompBean implements SessionBean {
        ...

        public void doSomethingWithJMS (...) {
           ...
           QueueConnection qc = qcf.createQueueConnection();
           QueueSession session = qc.createQueueSession(...);
           ut = ejbContext.getUserTransaction();
           ut.begin();
           ... // JMS operations
           ut.commit();
           session.close();
           qc.close();
         }

        ...
    }

For having the session operations involved in the transaction, you should have the session creation and close inside the transaction boundaries, and may choose to have the connection creation and close operations either both outside the transaction boundaries or both inside the transaction boundaries, as follows:

    public class EjbCompBean implements SessionBean {
        ...

        public void doSomethingWithJMS (...) {
           ...
           QueueConnection qc = qcf.createQueueConnection();
           ut = ejbContext.getUserTransaction();
           ut.begin();
           QueueSession session = qc.createQueueSession(...);
           ... // JMS operations
           session.close();
           ut.commit();
           qc.close();
         }

        ...
    }

or

    public class EjbCompBean implements SessionBean {
        ...

        public void doSomethingWithJMS (...) {
           ...
           ut = ejbContext.getUserTransaction();
           ut.begin();
           QueueConnection qc = qcf.createQueueConnection();
           QueueSession session = qc.createQueueSession(...);
           ... // JMS operations
           session.close();
           qc.close();
           ut.commit();
         }

        ...
    }

Programming EJB components with bean-managed transactions may induce complex code, that is why we recommend to use container-managed transactions, which will avoid you to face such problems as described above.

## JMS administration

JMS applications need some JMS administered objects: connection factories and destinations. These JMS administered objects are to be created via the proprietary administration interface (not standardized) of the JMS provider. For simple administration cases, and for JOnAS integrated JMS implementations (as Joram or SwiftMQ), you may avoid this administration phase by telling JOnAS to do it for you. This is what is described in the JOnAS simple JMS administration section.

### JOnAS simple JMS administration

In the default configuration, JOnAS automatically creates four connection factories and two destination objects. The only thing to do for using JMS in the default configuration is to require the use of the JMS service in the jonas.properties file:

        jonas.services           security,jtm,dbm,jms,ejb

The four connection factories automatically created are described in the table below:

JNDI name | JMS type | Usage
QCF | QueueConnectionFactory | To be used by an EJB component to create a QueueConnection.
TCF | TopicConnectionFactory | To be used by an EJB component to create a TopicConnection.
JQCF | QueueConnectionFactory | To be used by a Java component (an EJB client for instance) to create a QueueConnection.
JTCF | TopicConnectionFactory | To be used by a Java component (an EJB client for instance) to create a TopicConnection.

The QCF and TCF connection factories are managed connection factories. The EJB components should use only managed connection factories in order to allow JOnAS to manage the JMS resources created via these connection factories (the JMS sessions).
On the contrary, JQCF and JTCF are non-managed connection factories. They are to be used by Java component implementing a JMS client behavior, but running outside the application server.

The two destination objects automatically created are described in the table below:

JNDI name | JMS type | Usage
sampleQueue | Queue | Can be equally used by an EJB component or a Java component.
sampleTopic | Topic | Can be equally used by an EJB component or a Java component.

You cannot ask JOnAS to create additional connection factories when using the default configuration. However, you may ask JOnAS to create the destination objects you want at the EJB server launching time, by specifying it in the jonas.properties file. You have to specify the JNDI names of the Topic (resp. Queue) destination objects to be created in a jonas.service.jms.topics (resp. jonas.service.jms.queues) property as follows:

        jonas.service.jms.topics    t1,t2    // JOnAS server creates 2 topic destinations (t1,t2)
        jonas.service.jms.queues    myQueue  // JOnAS server creates 1 queue destination (myQueue)

It is recommended to EJB programmers to use resource references and resource environment references to access the connection factories and destination objects created by JOnAS, as already presented in Writing JMS operations within an enterprise bean section.

## Running an EJB performing JMS operations

In order to have an Enterprise bean performing some JMS operations, the following steps should be followed:

- A registry should be running.
- The Message-Oriented Middleware (the JMS provider implementation) should be started. See the section Launching the Message-Oriented Middleware.
- The JMS administered objects that will be used by the Enterprise beans should be created and registered in JNDI. This is done by the proprietary administration facilities of the JMS provider or through the JOnAS simplified facilities (JMS Administration).
- Deploy the EJB components on the EJB server by launching the EJB server.

    EJBServer

Note that when using the default configuration, the first three steps are automatically executed when launching the EJB server (the registry and the MOM are running in the server's JVM and the default administered objects are automatically created as presented in the JOnAS simple JMS administration section).
- Run the EJB client application.
- Stop the application. When using JMS, it is very important that the EJB server be stopped by using the JonasAdmin -s command, and not directly by killing it.

### Launching the Message-Oriented Middleware

If the JOnAS property jonas.services contains the jms service, then the JOnAS JMS service will be launched, and will eventually try to launch a JMS implementation (e.g. the Joram MOM or the SwiftMQ MOM).

For launching the MOM, three possibilities may be considered:

1. Launching the MOM automatically in the EJB server JVM
This can only be done using the default values for the configuration options, i.e. keeping the JOnAS property jonas.service.jms.collocated value `true` in the jonas.properties file (see the jonas.properties file provided in $JONAS_ROOT/config directory).

        jonas.service.jms.collocated true

In that case, the MOM will be launched automatically at EJB server launching time (command `EJBServer`).
2. Launching the MOM in a separate JVM on the same host
The Joram MOM may be launched with its default options by the command:

`JmsServer`

For other MOMs, you may use the proprietary command.

In that case, the JOnAS property jonas.service.jms.collocated must be set to `false` in the jonas.properties file.

        jonas.service.jms.collocated false

3. Launching the MOM on another host
You may launch the MOM on a separate host. In this case, you must specify to the EJB server that the MOM is running on another host through the JOnAS property jonas.service.jms.url in the jonas.properties file. In case of Joram, its value should be the Joram URL `joram://host:port` where `host` is the host name, and `port` the default Joram port number, i.e. 16010 (In case of SwiftMQ, the value of the URL is something like `smqp://host:4001/timeout=10000`).

        jonas.service.jms.collocated false
        jonas.service.jms.url        joram://host2:16010

4. Launching the MOM on another port number (case of Joram)
If you intend to change the default Joram port number, this requests a Joram specific configuration operation (modifying the `a3servers.xml` configuration file located in the directory where Joram is explicitly launched. A default `a3servers.xml` file and the `a3config.dtd` file (used by the `JmsServer` command) are respectively provided in $JONAS_ROOT/config and $JONAS_ROOT/xml directories; this `a3servers.xml` file specifies that the MOM runs on the localhost using the Joram default port number.
In order to launch the MOM on another port number you must change the args attribute of the service class="fr.dyade.aaa.mom.ConnectionFactory" element in the `a3servers.xml` file and to update the jonas.service.jms.url property in jonas.properties file.
The default a3servers.xml file is the one located in $JONAS_ROOT/config if you need to change the location of this file you must pass the system property `-Dfr.dyade.aaa.agent.A3CONF_DIR="your directory for a3.xml`"
To change other MOM configuration (distribution, multi-servers, ...), see the Joram documentation on http://www.objectweb.org/joram.

Note: the MOM may be directly launched by the proprietary command. In the case of Joram, the command is:

`java -DTransaction=NullTransaction fr.dyade.aaa.agent.AgentServer 0 ./s0`

This corresponds to the default options used by the `JmsServer` command.

The JMS messages are not persistent when launching the MOM with this command. If your messages need to be persistent, you should replace the `-DTransaction=NullTransaction` option by the `-DTransaction=ATransaction` option. See the Joram documentation for more details about this command.

## A JMS EJB example

This example shows an EJB application that combines an enterprise bean sending a JMS message and an enterprise bean writing a Database (an Entity Bean) within the same global transaction. It is composed of the following elements:

- A Session Bean, EjbComp, with a method for sending a message toward a JMS topic.
- An Entity Bean, Account, it is the one used in the sample eb with container-managed persistence, which writes its data into a relational database table, and which is supposed to represent a sent message (i.e. each time the EjbComp bean will send a message, an entity bean instance will be created).
- An EJB client, EjbCompClient, which calls the sendMsg method of the EjbComp bean, and creates an Account entity bean, both within the same transaction. In case of transaction commit, the JMS message is actually sent, and the record corresponding to the entity bean in the database is created. In case of rollback, the message is not sent and nothing is created in the database.
- A pure JMS client MsgReceptor, outside the EJB server, the role of which is to receive the messages sent by the Enterprise bean on the topic.

### The Session Bean performing JMS operations

The bean should contain some code to initialize the references to JMS administered objects that it will use. This code can be introduced in the `ejbCreate` method, in order to avoid repeating it in each method performing some JMS operations.

    public class EjbCompBean implements SessionBean {
        ...
        TopicConnectionFactory qcf = null;
        topic queue = null;

        public void ejbCreate() {
           ....
           ictx = new InitialContext();
           qcf = (TopicConnectionFactory)
              ictx.lookup("java:comp/env/jms/conFactSender");
           topic = (Topic) ictx.lookup("java:comp/env/jms/topiclistener");
        }
        ...
    }

This code has been voluntary cleared from all the elements which are not necessary for understanding the JMS logic aspects of the example, e.g. the exception management ...

The JMS administered objects `TopicConnectionFactory` and `Topic` have been made available to the bean by a resource reference for the first one, and by a resource environment reference for the second one.
The standard deployment descriptor should contain the following element:

          <resource-ref>
            <res-ref-name>jms/conFactSender</res-ref-name>
            <res-type>javax.jms.TopicConnectionFactory</res-type>
            <res-auth>Container</res-auth>
          </resource-ref>

          <resource-env-ref>
            <resource-env-ref-name>jms/topiclistener</resource-env-ref-name>
            <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
          </resource-env-ref>

The JOnAS specific deployment descriptor should contain the following element:

          <jonas-resource>
            <res-ref-name>jms/conFactSender</res-ref-name>
            <jndi-name>TCF</jndi-name>
          </jonas-resource>

          <jonas-resource-env>
            <resource-env-ref-name>jms/topiclistener</resource-env-ref-name>
            <jndi-name>sampleTopic</jndi-name>
          </jonas-resource-env>

Note that the EjbComp SessionBean will use the administered objects automatically created by JOnAS in the default JMS configuration.

The administered objects being accessible it is now possible to perform within a method some JMS operations. This is what is done in the `sendMsg` method:

    public class EjbCompBean implements SessionBean {
        ...
        public void sendMsg(java.lang.String s) {
            // create TopicConnection, TopicSession and TopicSender
            TopicConnection tc = null;
            TopicSession session = null;
            TopicPublisher tp = null;
            try {
                tc = tcf.createTopicConnection();
                session = tc.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
                tp = session.createPublisher(topic);
            }
            catch (Exception e) {e.printStackTrace();}

            // send the message to the topic
            try {
                ObjectMessage message;
                message = session.createObjectMessage();
                message.setObject(s);
                tp.publish(message);
                session.close();
                tc.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ...
    }

This method sends a message containing its String argument.

### The Entity Bean

The example use the simple entity bean Account for writing data into a database. See the sample eb

### The Client Application

The client application calls the sendMsg method of the EjbComp bean, and creates an AccountImpl entity bean, both within the same transaction.

    public class EjbCompClient {
        ...
        public static void main(String[] arg) {
        ...
        utx = (UserTransaction) initialContext.lookup("javax.transaction.UserTransaction");
        ...
        home1 = (EjbCompHome) initialContext.lookup("EjbCompHome");
        home2 = (AccountHome) initialContext.lookup("AccountImplHome");
        ...
        EjbComp aJmsBean = home1.create();
        Account aDataBean = null;
        ...
        utx.begin();
        aJmsBean.sendMsg("Hello commit"); // sending a JMS message
        aDataBean = home2.create(222, "JMS Sample OK", 0);
        utx.commit();

        utx.begin();
        aJmsBean.sendMsg("Hello rollback"); // sending a JMS message
        aDataBean = home2.create(223, "JMS Sample KO", 0);
        utx.rollback();
        ...
        }
    }

The result of this client execution will be that

- the `"Hello commit"` message will be sent and the `[222, 'JMS Sample OK', 0]` record will be created in the database (corresponding to the entity bean `109` creation)
- the `"Hello rollback"` message will never be sent and the `[223, 'JMS Sample KO', 0]` record will not be created in the database (as the entity bean `110` creation will be canceled).

### A pure JMS client for receiving the messages

In this example, the messages sent by the EJB component are received by a simple JMS client, running outside the EJB server, but listening for messages sent on the JMS topic "sampleTopic". It uses the TopicConnectionFactory automatically created by JOnAS named "JTCF"

    public class MsgReceptor {

        static Context ictx = null;
        static TopicConnectionFactory tcf = null;
        static Topic topic = null;

        public static void main(String[] arg) {

            ictx = new InitialContext();
            tcf = (TopicConnectionFactory) ictx.lookup("JTCF");
            topic = (Topic) ictx.lookup("sampleTopic");
            ...
            TopicConnection tc = tcf.createTopicConnection();
            TopicSession session =
                   tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
            TopicSubscriber ts = session.createSubscriber(topic);

            MyListenerSimple listener = new MyListenerSimple();
                ts.setMessageListener(listener);
            tc.start();

            System.in.read(); // waiting for messages

            session.close();
            qc.close();
            ...
        }
    }

    public MyListenerSimple implements javax.jms.MessageListener {
       MyListenerSimple() {}

       public void onMessage(javax.jms.Message msg) {
          try {
          if(msg==null)
            System.out.println("Message: message null ");
          else {
            if(msg instanceof ObjectMessage) {
                String m = (String) ((ObjectMessage)msg).getObject();
                System.out.println ("JMS client: received message ======> " + m);
            } else if(msg instanceof TextMessage) {
                String m = ((TextMessage)msg).getText();
                System.out.println ("JMS client: received message ======> " + m);
            }
          }catch(Exception exc) {
              System.out.println("Exception caught :" + exc);
              exc.printStackTrace();
          }
       }
    }

### The JMS Administration

We use the the JOnAS simplified facilities for administration by using the default values for the properties in the jonas.properties file. We only has to specify the use of the jms service:

        jonas.services               security,jtm,dbm,jms,ejb

The JMS Server is collocated to the JOnAS server and a topic named `sampleTopic` is created when launching the JOnAS server with the `EJBServer` command.