# JMS User's Guide

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

As required by the J2EE v1.4 specification, application components (servlets, JSP pages and enterprise beans) can use JMS for Java messaging. Furthermore, applications can use Message-driven Beans for asynchronous EJB method invocation, as specified by the EJB 2.1 specification.

Starting with the JOnAS 3.1 version, JOnAS supports the Java Message Service Specification 1.1. Previously in JMS 1.0.2, client programming for Point-to-point and Pub/Sub domains was achieved using similar, but separate, class hierarchies. Now, JMS 1.1 offers a domain-independent approach to programming the client application. Thus, the programming model is simpler and it is now possible to engage queues and topics in the same transaction.

Enterprise Bean providers can use JMS Connection Factory resources via resource references, and JMS Destination resources (JMS Queues and JMS Topics) via resource environment references. Thus, they are able to provide JMS code, inside an EJB method or web component method, for sending or synchronously receiving messages to/from a JMS Queue or Topic.

The EJB container and the Web container can allow for JMS operations within a global transaction, which may include other resources such as databases.

JOnAS integrates a third party JMS implementation (JORAM) which is the default JMS service, and for which a J2EE1.4-compliant Resource Adapter archive file is also provided. Other JMS providers, such as SwiftMQ and WebSphere MQ, may easily be integrated.

Starting with release 4.1, a JMS provider can be integrated within JOnAS by deploying a corresponding resource adapter. This is the preferred method as the JMS service will eventually become deprecated in later JOnAS releases. Also, this method allows deployment of 2.1 MDBs (not possible with the JMS service).

For performing JMS operations, JMS-administered objects will be used by the application components, such as connection factories and destinations. Refer to the JMS Administration section for an explanation of how to create those objects.

## JMS installation and configuration aspects

To use JMS with JOnAS, no additional installation or configuration operations are required. JOnAS contains:

- the Java[TM] Message Service API 1.1, currently integrated with the JOnAS distribution,
- a JMS implementation. Currently, the OpenSource JORAM (http://joram.objectweb.org), is integrated with the JOnAS distribution, thus no installation is necessary.

Additionally, the SwiftMQ product and IBM's WebSphere MQ have been used with JOnAS.

## Writing JMS operations within an application component

To send (or synchronously receive) JMS messages, the component requires access to JMS-administered objects, i.e. Connection Factories for creating connections to JMS resources and Destination objects (Queue or Topic), which are the JMS entities used as destinations within JMS sending operations. Both are made available through JNDI by the JMS provider administration facility.

Refer to the JOnAS example `jms` as a supplement to this present reading. This example jms is described here.

### Accessing the Connection Factory

The EJB specification introduces the concept of Resource Manager Connection Factory References. This concept also appears in the J2EE v1.4 specification. It is used to create connections to a resource manager. To date, three types of Resource Manager Connection Factories are considered:

- DataSource objects (javax.sql.DataSource) represent connection factories for JDBC connection objects.
- JMS Connection factories (`javax.jms.ConnectionFactory`, `javax.jms.QueueConnectionFactory` and `javax.jms.TopicConnectionFactory`) are connection factories for JMS connection objects.
- Java Mail Connection factories (`javax.mail.Session` or `javax.mail.internet.MimePartDataSource`) are connection factories for Java Mail connection objects.

The connection factories of interest here are the second type, which should be used to get JMS Connection Factories.

Note that starting with JMS 1.1, it is recommended that only the `javax.jms.ConnectionFactory` be used (rather than `javax.jms.QueueConnectionFactory` or `javax.jms.TopicConnectionFactory` ). However, the new implementation is fully backwards compatible and existing applications will work as is.

The standard deployment descriptor should contain the following `resource-ref` element:

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

This means that the programmer will have access to a `ConnectionFactory` object using the JNDI name java:comp/env/jms/conFact. The source code for obtaining the factory object is the following:

          ConnectionFactory qcf = (ConnectionFactory)
                     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), `CF` in the example, is defined in the JOnAS-specific deployment descriptor with the following element:

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

### Accessing the Destination Object

Accessing a JMS destination within the code of an application component requires using a Resource Environment Reference, which 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>

The application component's source code should contain:

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

the mapping to the actual JNDI name (e.g. "myQueue") being defined 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 method performing a message sending JMS operations looks like the following:

         void sendMyMessage() {

           ConnectionFactory cf = (ConnectionFactory)
                   ctx.lookup("java:comp/env/jms/conFact");
           Queue queue = (Queue) ctx.lookup("java:comp/env/jms/stockQueue");
           Connection conn = cf.createConnection();
           Session sess = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);

           MessageProducer  mp = sess.createProducer((Destination)queue);
           ObjectMessage msg = sess.createObjectMessage();
           msg.setObject("Hello");
           sender.send(msg);
           sess.close();
           conn.close();
         }

It is also possible for an application component to synchronously receive a message. An EJB method performing synchronous message reception on a queue is illustrated in the following:

        public String recMsg() {
            ConnectionFactory cf = (ConnectionFactory)
                   ctx.lookup("java:comp/env/jms/conFact");
            Queue queue = (Queue) ctx.lookup("java:comp/env/jms/stockQueue");
            Connection conn = cf.createConnection();
            Session sess = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer mc = sess.createConsumer((Destination)queue);
            conn.start();
            ObjectMessage msg = (ObjectMessage) mc.receive();
            String msgtxt =  (String) msg.getObject();
            sess.close();
            conn.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.createSession(...);
           ... // JMS operations
           session.close();
         }

The contained JMS operations will be a part of the transaction, if there is one, when the JOnAS server executes the method.

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

The previous examples illustrate point-to-point messaging. However, application components can also be developed using the publish/subscribe JMS API, i.e. using the `Topic` instead of the `Queue` destination type. This offers the capability of broadcasting a message to several message consumers at the same time. The following example illustrates a typical method for publishing a message on a JMS topic and demonstrates how interfaces have been simplified since JMS 1.1.

        public void sendMsg(java.lang.String s) {
            ConnectionFactory cf = (ConnectionFactory)
                           ictx.lookup("java:comp/env/jms/conFactSender");
            Topic topic = (Topic) ictx.lookup("java:comp/env/jms/topiclistener");
            Connection conn = cf.createConnection();
            Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer mc = session.createConsumer((Destination)topic);
            ObjectMessage message = session.createObjectMessage();
            message.setObject(s);
            mc.send(message);
            session.close();
            conn.close();
        }

### Transactions and JMS sessions within an application component

JMS session creation within an application component will result in different behaviors, depending on whether the session is created at execution time within or outside a transaction. In fact, the parameters of the `createSession(boolean transacted, int acknowledgeMode)` method are never taken into account.

- If the session creation occurs outside a transaction, the parameters is considered as being `transacted = false` and `acknowledgeMode = AUTO_ACKNOWLEDGE`. This means that each operation of the session is immediately executed.
- If the session creation occurs inside a transaction, the parameters have no meaning, the session may be considered as transacted, and the commit and rollback operations are handled by the JOnAS server at the level of the associated XA resource.

### Authentication

If your JMS implementation performs user authentication, the following methods can be used on Connection Factories:

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

## Some programming rules and restrictions when using JMS within EJB

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

### Connection Management

Depending on the JMS implementation and the application, it may be desirable to keep the JMS connections open for the life of the bean instance or for the duration of the method call. These two programming modes are illustrated in the following example (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 (...) {
           ...
           Connection conn = qcf.createConnection();
           Session session = conn.createSession(...);
           ... // JMS operations
           session.close();
           conn.close();
         }

        ...
    }

To keep the connection open during the life of a bean instance, the programming style shown in the following example is preferred, since it avoids many connection opening and closing operations:

    public class EjbCompBean implements SessionBean {
        ...
        ConnectionFactory qcf = null;
        Queue queue = null;
        Connection conn = null;

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

        public void doSomethingWithJMS (...) {
           ...
           Session session = conn.createSession(...);
           ... // JMS operations
           session.close();
        }

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

        ...
    }

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

- For a stateless session bean, the bean state is not maintained across method calls. Therefore, the JMS objects should always be initialized and defined in each method that performs JMS operations.
- For an entity bean, an instance may be passivated, and only the persistent part of the bean state is maintained. Therefore, it is recommended that the JMS objects be initialized and defined in each method performing JMS operations. If these objects are defined in the bean state, they can be initialized in the `ejbActivate` method (if the connection is created in the `ejbActivate` method, be sure to close it in the `ejbPassivate` method).
- For a stateful session bean (as shown in the previous example), JMS objects can be defined in the bean state. Stateful session bean instances can be passivated (not in the current version of JOnAS). Since connection factories and destinations are serializable objects, they can be initialized only in ejbCreate. However, be aware that a connection must be closed in `ejbPassivate` (with the state variable set to `null`) and recreated in `ejbActivate`.

Note that, due to a known problem with the Sun JDK 1.3 on Linux, the close of the connection can block. The problem is fixed with JDK 1.4.

### Starting Transactions after JMS Connection or Session creation

Currently, it is not possible to start a bean-managed transaction after the creation of a JMS session and 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 (...) {
           ...
           Connection conn = cf.createConnection();
           Session session = conn.createSession(...);
           ut = ejbContext.getUserTransaction();
           ut.begin();
           ... // JMS operations
           ut.commit();
           session.close();
           conn.close();
         }

        ...
    }

To have the session operations involved in the transaction, the session creation and close should be inside the transaction boundaries, and the connection creation and close operations can either be both outside the transaction boundaries or both inside the transaction boundaries, as follows:

    public class EjbCompBean implements SessionBean {
        ...

        public void doSomethingWithJMS (...) {
           ...
           Connection conn = qcf.createConnection();
           ut = ejbContext.getUserTransaction();
           ut.begin();
           Session session = conn.createSession(...);
           ... // JMS operations
           session.close();
           ut.commit();
           conn.close();
         }

        ...
    }

or

    public class EjbCompBean implements SessionBean {
        ...

        public void doSomethingWithJMS (...) {
           ...
           ut = ejbContext.getUserTransaction();
           ut.begin();
           Connection conn = cf.createConnection();
           Session session = conn.createSession(...);
           ... // JMS operations
           session.close();
           conn.close();
           ut.commit();
         }

        ...
    }

Programming EJB components with bean-managed transactions can result in complex code. Using container-managed transactions can help avoid problems such as those previously described.

## JMS administration

Applications using messaging require some JMS-administered objects: connection factories and destinations. These objects are created via the proprietary administration interface (not standardized) of the JMS provider. For simple cases, it is possible to have either the jms service or the JMS resource adapter perform administration operations during startup.

As provided, the default JMS service and JORAM adapter configurations automatically create six connection factories and two destination objects.

The six connection factories automatically created are described in the following table:

JNDI name | JMS type | Usage
CF | ConnectionFactory | To be used by an application component to create a Connection.
QCF | QueueConnectionFactory | To be used by an application component to create a QueueConnection.
TCF | TopicConnectionFactory | To be used by an application component to create a TopicConnection.
JCF | ConnectionFactory | To be used by any other Java component (for instance a client) to create a Connection.
JQCF | QueueConnectionFactory | To be used by any other Java component (for instance a client) to create a QueueConnection.
JTCF | TopicConnectionFactory | To be used by any other Java component (for instance a client) to create a TopicConnection.

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

The two destinations automatically created are described in the following table:

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.

### JMS service administration

For using the JMS service in the default configuration, it is only necessary to require the use of the JMS service in the jonas.properties file:

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

JOnAS will not create additional connection factories when using the default configuration. However, JOnAS can create requested destination objects at server launching time, if specified in the jonas.properties file. To do this, specify the JNDI names of the Topic and Queue destination objects to be created in a jonas.service.jms.topics and jonas.service.jms.queues property respectively, 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 that programmers use resource references and resource environment references to access the connection factories and destination objects created by JOnAS, as already presented in the "Writing JMS operations within an application component" section.

### JMS resource adapter configuration

Starting with JOnAS release 4.1, it is recommended that a JMS resource adapter be deployed instead of using the jms service. Refer to the JMS Resource Adapters configuration guide for an explanation.

## Running an EJB performing JMS operations

All that is necessary to have an Enterprise Bean perform JMS operations is:

    jonas start

The Message-Oriented Middleware (the JMS provider implementation) is automatically started (or at least accessed) and the JMS-administered objects that will be used by the Enterprise Beans are automatically created and registered in JNDI.

Then, the EJB can be deployed as usual with:

    jonas admin -a XX.jar

### Accessing the Message-Oriented Middleware...

#### as a service...

If the JOnAS property jonas.services contains the jms service, 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, consider the following possibilities:

1. Launching the MOM automatically in the JOnAS JVM
   This is 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/conf` directory).

           jonas.service.jms.collocated true

   In this case, the MOM will be launched automatically at server launching time (command `jonas start`). Note for using the JORAM MOM from a distant host: To use the JMS resources from a distant host, the hostname property value in the default `a3servers.xml` configuration file must be changed from localhost to the actual host name. See case 4 (Launching the MOM on another port number) for details on the JORAM configuration.
2. Launching the MOM in a separate JVM on the same host
   The JORAM MOM can be launched with its default options using the command:
   `JmsServer`

   For other MOMs, use the proprietary command.

   In this 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
   The MOM can be launched on a separate host. In this case, the JOnAS server must be notified that the MOM is running on another host via the JOnAS property jonas.service.jms.url in the jonas.properties file. For 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 (For SwiftMQ, the value of the URL is similar to `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 (for JORAM)
   To change the default JORAM port number requires 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 is provided in the $JONAS_ROOT/conf directory; this `a3servers.xml` file specifies that the MOM runs on the localhost using the JORAM default port number.
   To launch the MOM on another port number, change the args attribute of the service class="fr.dyade.aaa.mom.ConnectionFactory" element in the `a3servers.xml` file and update the jonas.service.jms.url property in the jonas.properties file.
   The default a3servers.xml file is located in $JONAS_ROOT/conf. To change the location of this file, the system property `-Dfr.dyade.aaa.agent.A3CONF_DIR="your directory for a3.xml`" must be passed.
5. Specifying JORAM's persistence mode
   When automatically starting JORAM, or when starting JORAM with the `JmsServer` command, the default mode is non-persistent. Meaning that in the event of a crash, the non-delivered and non-acknowledged messages are lost.
   In order to start a persistent JORAM server, guaranteeing message delivery even in case of failures, the Transaction system property should be set to `fr.dyade.aaa.util.NTransaction`.

   Note: the MOM may be directly launched by the proprietary command. The command for JORAM is:
   `java -DTransaction=fr.dyade.aaa.util.NullTransaction fr.dyade.aaa.agent.AgentServer 0 ./s0`

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

   The server is not persistent when launched with this command. If persistence is required, the `-DTransaction=fr.dyade.aaa.util.NullTransaction` option should be replaced with the `-DTransaction=fr.dyade.aaa.util.NTransaction` option.

   To change other MOM configurations (distribution, multi-servers, ...), refer to the JORAM documentation on http://joram.objectweb.org.

#### ... or as a J2EE1.4 adapter

Starting with JOnAS release 4.1, a JMS server can be accessed through a resource adapter which may be deployed.

For deploying such a resource adapter, place the corresponding archive file (`*.rar`) in the JOnAS's `rars/autoload` directory, or declare it at the end of the `jonas.properties` file, or deploy it manually through the jonasAdmin tool.

Configuring and deploying such adapters is explained in the Configuring JMS Resource Adapters section.

## 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 to a JMS topic.
- An Entity Bean, Account (the one used in the sample eb with container-managed persistence), which writes its data into a relational database table and is intended to represent a sent message (i.e. each time the EjbComp bean sends 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. For a transaction commit, the JMS message is actually sent and the record corresponding to the entity bean in the database is created. For a rollback, the message is not sent and nothing is created in the database.
- A pure JMS client MsgReceptor, outside the JOnAS 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 code for initializing the references to JMS administered objects that it will use. To avoid repeating this code in each method performing JMS operations, it can be introduced in the `ejbCreate` method.

    public class EjbCompBean implements SessionBean {
        ...
        ConnectionFactory cf = null;
        Topic topic = null;

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

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

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

          <resource-ref>
            <res-ref-name>jms/conFactSender</res-ref-name>
            <res-type>javax.jms.ConnectionFactory</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.

Because the administered objects are now accessible, it is possible to perform JMS operations within a method. The following occurs in the `sendMsg` method:

    public class EjbCompBean implements SessionBean {
        ...
        public void sendMsg(java.lang.String s) {
            // create Connection, Session and MessageProducer
            Connection conn = null;
            Session session = null;
            MessageProducer mp = null;
            try {
                conn = cf.createConnection();
                session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
                mp = session.createProducer((Destination)topic);
            }
            catch (Exception e) {e.printStackTrace();}

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

This method sends a message containing its String argument.

### The Entity Bean

The example uses the simple entity bean Account for writing data into a database. Refer to 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 (since the entity bean `110` creation will be canceled).

### A pure JMS client for receiving messages

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

    public class MsgReceptor {

        static Context ictx = null;
        static ConnectionFactory cf = null;
        static Topic topic = null;

        public static void main(String[] arg) {

            ictx = new InitialContext();
            cf = (ConnectionFactory) ictx.lookup("JCF");
            topic = (Topic) ictx.lookup("sampleTopic");
            ...
            Connection conn = cf.createConnection();
            Session session =
                   conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer mc = session.createConsumer((Destination)topic);

            MyListenerSimple listener = new MyListenerSimple();
                mc.setMessageListener(listener);
            conn.start();

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

            session.close();
            conn.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();
          }
       }
    }