1
votes

We are using an application that contains a jboss @Service mbean which encapsulates a javax.jms.Connection object.

During startup of the mbean the connection is created by initializing a remote InitialContext, looking up the ConnectionFactory from that context, and creating a connection from that factory:

@Service
public class JMSPublisher extends etcc.... {
   private Connection connection;
   protected void startService() {
      Context ctx = getRemoteInitialContext();
      ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup("ConnectionFactory");
      connection = connectionFactory.createConnection();
   }
}

My question is: how long can we be supposed to maintain that connection ? In practise we see that the connection throws a JMSException when we try to create a session on it after an undefined amount of time.

The documentation of Connection tells us that an object represents a socket, so timeouts due to inactivity could be normal. But how can we deal with it without creating new connections for each and every message ?

1

1 Answers

3
votes

Your best bet is to have JMSPublisher implement javax.jms.Exception listener. Implement a connect() method which safely acquires a connection on:

  1. startService
  2. onException

A couple of extra points:

  • For code compression, simply acquire the JMS connection factory via resource injection. The connection factory reference will be resolved before startService is called and will also act as an implicit depends, making the JMS connection factory a dependency for your service.

  • Have JMSPublisher extend org.jboss.system.ServiceMBeanSupport and implement a token MBean interface (JMSPublisherMBean) that extends org.jboss.system.ServiceMBean. This will ensure that the dependencies are honoured on service start (and stop).

Resource Injected JMS Connection Factory

@Resource(mappedName="ConnectionFactory") 
private javax.jms.ConnectionFactory connectionFactory;
private volatile javax.jms.Connection connection;

Modified startService()

public void startService() {
   connect();
}

Connection Exception Handler

public void onException(JMSException je) {
   connect();
}

*Safe Connection Initializer (adding conn.start()) *

private void synchronized connect() {
    log.info("Initializing Connection....");
    try {
        if(connection!=null) {
           try { connection.stop(); } catch (Exception e) {}
           try { connection.close(); } catch (Exception e) {}
        }
        connection = connectionFactory.createConnection();
        connection.setExceptionListener(this);
        connection.start();
    } catch (Exception e) {
        log.error("Failed to intialize JMS connection", e);
    }
}

This will not automatically take care of other JMS resources allocated through the lost connection, but if other components are using the connection held by this component, you can publish JMX Notifications from JMSPublisher indicating that the connection has been lost and clean up/re-acquire on the notification receipt.