26.3. 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.

26.3.1. 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.

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.

26.3.2. 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.