IBM Support

Using WebSphere MQ automatic client reconnection with the WebSphere MQ classes for JMS

Question & Answer


Question

How can I make use of WebSphere MQ (WMQ) automatic client reconnection, and multi-instance queue managers, within a Java™ SE and Java EE environment?

Answer

WebSphere MQ V7 introduces the concept of "multi-instance queue managers", whereby a single queue manager can be created on two servers - one instance of the queue manager is running on one server (this is known as the Active instance), and one is running in standby on the other server. If the Active queue manager fails, then the Standby instance starts automatically and takes over. Both the Active and Standby queue managers have the same queue manager identifier (QMID).

WebSphere MQ client applications that connect to a multi-instance queue manager can be configured to automatically reconnect to a standby instance of a queue manager by using automatic client reconnection.

In this technote, we will look at how applications using the WebSphere MQ classes for JMS running in Java SE environments can exploit the automatic client reconnection functionality before moving on to discuss how this functionality can be used within Java EE environments, such as WebSphere Application Server.


Automatic client reconnection in Java SE environments
A new Connection Factory property, CLIENTRECONNECTOPTIONS, was added in WebSphere MQ V7.0.1.3 to support automatic client reconnection.

This property uses two additional Connection Factory properties, CONNECTIONNAMELIST and CCDTURL, to determine how to connect to the server where the queue manager is running.

We will look at these properties in turn:
 
  • CONNECTIONNAMELIST
The CONNECTIONNAMELIST property is a comma separated list, where each entry contains information on the hostname and port that are to be used to connect to a queue manager in CLIENT mode. The list has the following format:

hostname(port), hostname(port)

Each entry in the list can correspond to either a stand-alone queue manager, or a multi-instance queue manager.

This property is used in conjunction with the Connection Factory properties QMANAGER and CHANNEL. The QMANAGER property specifies the name of the queue manager to connect to,
and CHANNEL indicates the WebSphere MQ channel that should be used to connect to that queue manager.

The CONNECTIONNAMELIST lists the hostnames of systems where that queue manager has been defined, together with the port number that the WebSphere MQ listener for that queue manager is using.

When an application uses a Connection Factory that has the CONNECTIONNAMELIST property defined to create a CLIENT connection, the WebSphere MQ classes for JMS will work their way down the list, trying to connect to a queue manager with the name specified by the QMANAGER property, over the channel mentioned in the CHANNEL property, using the hostname and port information specified.

If the required queue manager is not accessible using the first hostname and port in the CONNECTIONNAMELIST, the WebSphere MQ classes for JMS will try the next entry in the list, and so on until either a connection can be made, or the end of the list has been reached.

If the end of the CONNECTIONNAMELIST is reached and a connection to the specified queue manager has not been made, the WebSphere MQ classes for JMS will throw an Exception containing the WebSphere MQ Reason Code 2059 (MQRC_QMGR_NOT_AVAILABLE).

If the queue manager that an application is connected to fails, any applications which used a CONNECTIONNAMELIST to connect to that queue manager will receive an Exception indicating that the queue manager is no longer available. They will need to catch that exception, clean up any resources that they were using, and then use the Connection Factory to create a new connection.

This will cause the WebSphere MQ classes for JMS to work their way down the CONNECTIONNAMELIST again, trying each hostname and port number in turn, until they are either able to connect to a queue manager, or reach the end of the list.

 
  • CCDTURL
The CCDTURL property contains a Uniform Resource Locator (URL) that points to a Client Channel Definition Table (CCDT), and is used in conjunction with the Connection Factory property QMANAGER.

This CCDT is a list of Client Channels that can be used to connect to a queue manager that has been defined on a WebSphere MQ system. For information on how CCDTs are used by the WebSphere MQ classes for Java, please refer to the Using a client channel definition table with WebSphere MQ classes for JMS in the Using Java section of the WebSphere MQ V7 Information Center.
 
  • CLIENTRECONNECTOPTIONS
This property is used to enable automatic client reconnection within the WebSphere MQ classes for JMS. The possible values for this property are:
  • DISABLED - Automatic client reconnection is disabled.
  • QMGR - When this value is enabled, the WebSphere MQ classes for JMS will attempt to reconnect to a queue manager with the same identifier (QMID) as the queue manager that it was connected to previously, using either:
  • the channel specified in the CHANNEL property together with the list of hostname and port numbers specified in the CONNECTIONNAMELIST
  • the Client Channel Definition Table specified in the CCDTURL.
  • ANY - If the queue manager that the application was connected to fails, the WebSphere MQ classes for JMS will automatically try to reconnect to a queue manager using either the CONNECTIONNAMELIST and CHANNEL properties for the Connection Factory, or a Client Channel Definition Table if the Connection Factory has been configured with a CCDTURL property.


This means that an application using the WebSphere MQ classes for JMS needs to be using a JMS Connection Factory that has the following properties set in order to automatically reconnect to a multi-instance queue manager:
  • CHANNEL = my_server_connection_channel
  • CLIENTRECONNECTOPTIONS = QMGR
  • CONNECTIONNAMELIST = hostname1(port1), hostname2(port2)
  • QMANAGER = my_queue_manager

where:
  • my_queue_manager is the name of the multi-instance queue manager.
  • my_server_connection_channel is the name of a server connection channel defined on the queue manager.
  • hostname1 is the hostname machine where the of the Active queue manager is running.
  • port1 is the port number for the WebSphere MQ listener for the Active queue manager.
  • hostname2 is the hostname of the system where the standby queue manager is located.
  • port2 is the port number that the WebSphere MQ listener for the standby queue manager is using.


Automatic client reconnection in Java EE environments
The WebSphere MQ Resource Adapter, which can be deployed into Java EE environments, and the WebSphere Application Server WebSphere MQ messaging provider use the WebSphere MQ classes for JMS to communicate with WebSphere MQ queue managers.

In this section, we will look at how both the WebSphere MQ Resource Adapter and the WebSphere Application Server WebSphere MQ messaging provider provide support for automatic client reconnection.

Before we get into the detail, here is a table that summarizes all of the information that can be found in this section:

 
CONNECTION
NAMELIST
CCDTURL
CLIENT
RECONNECT
OPTIONS
Alternative
Approach To
Automatic Client
Reconnection
Activation Specifications
Supported
with restrictions
Supported
with restrictions
Not supported
Java EE environment and
Activation
Specifications
provide their own
reconnection
mechanism
WebSphere
Application
Server
Listener Ports
Supported
with restrictions
Supported
with restrictions
Not supported
WebSphere
Application Server
provides its own
reconnection
mechanism
Enterprise JavaBeans
and
Web-based
Applications
Supported
with restrictions
Supported
with restrictions
Not supported
Application needs
to implement
its own
reconnection logic
Applications
running inside
Client
Containers
Supported
Supported
Supported
N/A
 
  • Activation Specifications
Message-driven bean applications that are installed in a Java EE environment, such as WebSphere Application Server, can use Activation Specifications to process messages on a WebSphere MQ system.

Activation Specifications are used to detect messages arriving on a WebSphere MQ system, and then deliver them to message-driven beans for processing. This section deals with how the Activation Specification monitors the WebSphere MQ system.

Message-driven beans can also make additional connections to WebSphere MQ systems from inside their onMessage() method. Details about how these connections can use automatic client reconnection can be found in the Enterprise JavaBeans and Web-based applications section below.
 
  • CONNECTIONNAMELIST
The CONNECTIONNAMELIST property is supported with restrictions with Activation Specifications.


When the Activation Specification starts up, it will try to connect to the queue manager specified in the QMANAGER property, over the channel mentioned in the CHANNEL property, using the hostname and port information from the first entry in the CONNECTIONNAMELIST. If the Activation Specification is not able to connect to the queue manager using the first entry in the list, it moves on to the second entry, and so on, until either a connection to the queue manager has been made, or the end of the list has been reached.

If the Activation Specification has been unable to connect to the specified queue manager using any of the entries in the CONNECTIONNAMELIST, it will stop and will require a manual restart in order to try to reconnect again (unless startup reconnection has been switched on - please refer to APAR IZ76343 for more details on how to enable this).

Once the Activation Specification is running, it will get messages from the WebSphere MQ system and deliver them to a message-driven bean for processing.

If the queue manager fails while a message is being processed, the Java EE environment will detect the failure and then try to reconnect the Activation Specification. The Activation Specification uses the information in the CONNECTIONNAMELIST property as before, when it preforms the reconnection attempts.

If the Activation Specification tries all of the entries in the CONNECTIONNAMELIST and is still unable to connect to the queue manager, then it will wait for the period of time specified by the WebSphere MQ Resource Adapter property reconnectionRetryInterval before trying again.

The WebSphere MQ Resource Adapter property reconnectionRetryCount defines the number of consecutive reconnection attempts that will be made before an Activation Specification is stopped and will require a manual restart.

Once the Activation Specification has reconnected to a WebSphere MQ system, the Java EE environment will perform any transactional cleanup that is required, and then resume delivering messages to message-driven beans for processing.

In order for the transactional cleanup to work correctly, the Java EE environment must be able to access the logs for the queue manager that failed.

If the Activation Specifications are being used with transactional message-driven beans that participate in XA transactions, and are connecting to a multi-instance queue manager, then the CONNECTIONNAMELIST must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the transactional message-driven beans are being used with stand-alone queue managers, then the CONNECTIONNAMELIST property must contain a single entry, to ensure that the Activation Specification always reconnects to the same queue manager running on the same system following a failure.
 
  • CCDTURL
The use of the CCDTURL property with Activation Specifications is supported with restrictions.

When the Activation Specification starts up, it will try to connect to the queue manager specified in the QMANAGER property using the first entry in the CCDT. If the Activation Specification is not able to connect to the queue manager using the first entry in the table, it moves on to the second entry, and so on, until either a connection to the queue manager has been made, or the end of the table has been reached.

If the Activation Specification has been unable to connect to the specified queue manager using any of the entries in the CCDT, it will stop and will require a manual restart in order to try to reconnect again (unless startup reconnection has been switched on - please refer to APAR IZ76343 for more details on how to enable this).

Once the Activation Specification is running, it will get messages from the WebSphere MQ system and deliver them to a message-driven bean for processing.

If the queue manager fails while a message is being processed, the Java EE environment will detect the failure and then try to reconnect the Activation Specification. The Activation Specification uses the information in the CCDT when it performs the reconnection attempts.

If the Activation Specification tries all of the entries in the CCDT and is still unable to connect to the queue manager, then it will wait for the period of time specified by the WebSphere MQ Resource Adapter property reconnectionRetryInterval before trying again.

The WebSphere MQ Resource Adapter property reconnectionRetryCount defines the number of consecutive reconnection attempts that will be made before an Activation Specification is stopped and will require a manual restart.

Once the Activation Specification has reconnected to a WebSphere MQ system, the Java EE environment will perform any transactional cleanup that is required, and then resume delivering messages to message-driven beans for processing.

In order for the transactional cleanup to work correctly, the Java EE environment must be able to access the logs for the queue manager that failed.

If the Activation Specifications are being used with transactional message-driven beans that participate in XA transactions, and are connecting to a multi-instance queue manager, then the CCDT must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the transactional message-driven beans are being used with stand-alone queue managers, then the CCDT being used by the Activation Specification must contain a single entry, to ensure that it always reconnects to the same queue manager running on the same system following a failure.

CCDTs used with Activation Specifications must use the default AFFINITY value of PREFERRED to ensure connections are made to the same active queue manager.

 
  • CLIENTRECONNECTOPTIONS
Activation Specifications provide their own "automatic reconnection" functionality, which allows them to automatically reconnect to a WebSphere MQ system if the queue manager they were connected to fails.

Because of this, the automatic client reconnection functionality provided by the WebSphere MQ classes for JMS is not supported. The CLIENTRECONNECTOPTIONS property should be set to DISABLED for all Activation Specifications that are used in the Java EE environment.

 
  • WebSphere Application Server Listener Ports
Message-driven bean applications that are installed in WebSphere Application Server can also use Listener Ports to process messages on a WebSphere MQ system.

Listener Ports are used to detect messages arriving on a WebSphere MQ system, and then deliver them to message-driven beans for processing. This section deals with how the Listener Port monitors the WebSphere MQ system.

Message-driven beans can also make additional connections to WebSphere MQ systems from inside their onMessage() method. Details about how these connections can use automatic client reconnection can be found in the Enterprise JavaBeans and Web-based applications section below.
 
  • CONNECTIONNAMELIST
The CONNECTIONNAMELIST property is supported with restrictions when used with WebSphere Application Server Listener Ports.


Listener Ports make use of JMS Connection Pools when connecting to WebSphere MQ, and so are subject to the implications of using Connection Pools mentioned below.

When the Listener Port starts up, it will request a connection from the JMS Connection Pool associated with the Connection Factory it has been configured to use.

If there is a free connection in the Connection Pool, then this connection is returned to the application.

If there are no free connections, and the maximum number of connections have not yet been created from this Connection Factory, then the CONNECTIONNAMELIST will be used to try and create a new connection to WebSphere MQ.

If all of the WebSphere MQ systems in the CONNECTIONNAMELIST are not accessible, the Listener Port will stop, wait for the period of time specified by the Message Listener Service Custom Property RECOVERY.RETRY.INTERVAL and then try to reconnect again. This reconnection attempt will check if there are any free connections in the Connection Pool, just in case one was returned in between the connection attempts, and if there isn't, it will use the CONNECTIONNAMELIST as before.

Once the Listener Port has reconnected to a WebSphere MQ system, the Java EE environment will perform any transactional cleanup that is required, and then resume delivering messages to message-driven beans for processing.

In order for the transactional cleanup to work correctly, the Java EE environment must be able to access the logs for the queue manager that failed.

If the Listener Ports are being used with transactional message-driven beans that participate in XA transactions, and are connecting to a multi-instance queue manager, then the CONNECTIONNAMELIST must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the transactional message-driven beans are being used with stand-alone queue managers, then the CONNECTIONNAMELIST property must contain a single entry, to ensure that the Listener Port always reconnects to the same queue manager running on the same system following a failure.
 
  • CCDTURL
The use of the CCDTURL property with Listener Ports is supported with restrictions.


When the Listener Port starts up, it will try to connect to the queue manager specified in the QMANAGER property using the first entry in the CCDT. If the Listener Port is not able to connect to the queue manager using the first entry in the table, it moves on to the second entry, and so on, until either a connection to the queue manager has been made, or the end of the table has been reached.

If the Listener Port is unable to connect to the specified queue manager using any of the entries in the CCDT, it will stop, wait for the period of time specified by the Message Listener Service Custom Property RECOVERY.RETRY.INTERVAL and then try to reconnect again. This reconnection attempt will work its way through all of the entries in the CCDT has before.

Once the Listener Port is running, it will get messages from the WebSphere MQ system and deliver them to a message-driven bean for processing.

If the queue manager fails while a message is being processed, the Java EE environment will detect the failure and then try to reconnect the Listener Port. The Listener Port uses the information in the CCDT when it performs the reconnection attempts.

If the Activation Specification tries all of the entries in the CCDT and is still unable to connect to the queue manager, then it will wait for the period of time specified by the RECOVERY.RETRY.INTERVAL property before trying again.

The Message Listener Service Custom Property MAX.RECOVERY.RETRIES defines the number of consecutive reconnection attempts that will be made before a Listener Port is stopped and will require a manual restart.

Once the Listener Port has reconnected to a WebSphere MQ system, the Java EE environment will perform any transactional cleanup that is required, and then resume delivering messages to message-driven beans for processing.

In order for the transactional cleanup to work correctly, the Java EE environment must be able to access the logs for the queue manager that failed.

If the Listener Port are being used with transactional message-driven beans that participate in XA transactions, and are connecting to a multi-instance queue manager, then the CCDT must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the transactional message-driven beans are being used with stand-alone queue managers, then the CCDT being used by the Listener Port must contain a single entry, to ensure that it always reconnects to the same queue manager running on the same system following a failure.

CCDTs used with Listener Ports must use the default AFFINITY value of PREFERRED to ensure connections are made to the same active queue manager.
 
  • CLIENTRECONNECTOPTIONS
Listener Ports provide their own "automatic reconnection" functionality, which allows them to automatically reconnect to a WebSphere MQ system if the queue manager they were connected to fails.

Because of this, the automatic client reconnection functionality provided by the WebSphere MQ classes for JMS is not supported. The CLIENTRECONNECTOPTIONS property should be set to DISABLED on the connection factories used by all Listener Ports.
 
  • Enterprise JavaBeans and Web-based applications
Enterprise JavaBeans applications and applications that run within the Web Container, such as Servlets, use a JMS Connection Factory to create a connection to a WebSphere MQ queue manager.
 
  • CONNECTIONNAMELIST
The use of the CONNECTIONNAMELIST property by Enterprise JavaBeans and applications that run within the Web Container is supported with restrictions.

If the Java EE environment provides a Connection Pool for JMS Connections, then please refer to the section below for details on how this affects the behaviour of the CONNECTIONNAMELIST property.

If the Java EE environment does not provide a JMS Connection Pool. then the application will use the CONNECTIONNAMELIST property in the same way as Java SE applications.

In situations where the applications participate in XA transactions, and are connecting to a multi-instance queue manager, then the CONNECTIONNAMELIST must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the applications are being used with stand-alone queue managers, then the CONNECTIONNAMELIST property must contain a single entry, to ensure that the application always reconnects to the same queue manager running on the same system following a failure.
 
  • CCDTURL
The use of the CCDTURL property by Enterprise JavaBeans and applications that run within the Web Container is supported with restrictions.

If the Java EE environment provides a Connection Pool for JMS Connections, then please refer to the section below for details on how this affects the behaviour of the CCDTURL property.

If the Java EE environment does not provide a JMS Connection Pool. then the application will use the CCDTURL property in the same way as Java SE applications.

In situations where the applications participate in XA transactions, and are connecting to a multi-instance queue manager, then the CCDTURL must contain 2 entries:
  • An entry for the Active queue manager instance.
  • An entry for the Standby queue manager instance.

This means that the Java EE environment can access the queue manager logs if it needs to perform transaction recovery, regardless of which queue manager it reconnects to following a failure.

If the applications are being used with stand-alone queue managers, then the CCDTURL property must contain a single entry, to ensure that the application always reconnects to the same queue manager running on the same system following a failure.
 
  • CLIENTRECONNECTOPTIONS
The automatic client reconnection functionality provided by the WebSphere MQ classes for JMS is not supported for either Enterprise JavaBeans applications, or applications running within the Web Container.

This is due to the various transactional implications that can arise if the WebSphere MQ classes for JMS automatically reconnect to another WebSphere MQ queue manager without the transaction manager for the Java EE environment realizing.

For JMS Connection Factories that are used by Enterprise JavaBeans or applications that run in the Web Container, the CLIENTRECONNECTOPTIONS property should be set to DISABLED.

Applications that wish to automatically reconnect to a new queue manager if the queue manager they are using fails need to implement their own reconnection logic. Some information on how to do this is provided below.
 
  • Applications running inside Client Containers
Some Java EE environments, such as WebSphere Application Server, provide a Client Container which can be used to run Java SE applications.

Applications running inside of these environments will use a JMS Connection Factory to connect to a WebSphere MQ queue manager.
 
  • CONNECTIONNAMELIST
The use of the CONNECTIONNAMELIST property by applications that run within a Client Container is fully supported.

If the Java EE environment provides a Connection Pool for JMS Connections, then please refer to the section below for details on how this affects the behaviour of the CONNECTIONNAMELIST property.

If the Java EE environment does not provide a JMS Connection Pool. then the application will use the CONNECTIONNAMELIST property in the same way as Java SE applications.
 
  • CCDTURL
The use of the CCDTURL property by applications that run within a Client Container is fully supported.

If the Java EE environment provides a Connection Pool for JMS Connections, then please refer to the section below for details on how this affects the behaviour of the CCDTURL property.

If the Java EE environment does not provide a JMS Connection Pool. then the application will use the CCDTURL property in the same way as Java SE applications.
 
  • CLIENTRECONNECTOPTIONS
The use of the CLIENTRECONNECTOPTIONS property is fully supported for applications that run within a Client Container.



Implications of using CONNECTIONNAMELIST or CCDT in Java EE environments that provide a Connection Pool
Some Java EE environments, such as WebSphere Application Server, provide a JMS Connection Pool. Applications that create a connection using a Connection Factory that has been defined in the Java EE environment will either get an existing free connection from the Connection Pool for this Connection Factory, or a new connection if there is not a suitable one in the Connection Pool.

This can have implications if the Connection Factory has been configured with either the CONNECTIONNAMELIST or CCDTURL property defined.

The first time the Connection Factory is used to create a connection, the Java EE environment will use either the CONNECTIONNAMELIST or the CCDTURL to create a new connection to the WebSphere MQ system. When this connection is finished with, it will be returned to the Connection Pool where it is available for reuse.

Now, if something else creates a Connection from the Connection Factory, the Java EE environment will return the connection from the Connection Pool rather than using the CONNECTIONNAMELIST or the CCDTURL properties to create a new connection.

If a connection is being used when a queue manager instance fails, then the connection is discarded. However, the contents of the Connection Pool may not be, which means that the Pool can potentially still contain connections to a queue manager that is no longer running.

In this situation, the next time a request is made to create a connection from the Connection Factory, a connection to the failed queue manager will be returned. Any attempts to use this Connection will fail, as the queue manager is no longer running, causing the connection to be discarded.

Only when the Connection Pool is empty will the Java EE environment use the CONNECTIONNAMELIST or CCDTURL properties to create a new connection to WebSphere MQ.


Due to the way the CONNECTIONNAMELIST and CCDTs are used to create JMS Connections, it is also possible to have a Connection Pool that contains connections to different WebSphere MQ systems.

For example, suppose a Connection Factory has been configured with the CONNECTIONNAMELIST property set to the following value:
  • CONNECTIONNAMELIST = hostname1(port1), hostname2(port2)

Now, suppose that the first time an application tries to create a Connection to a stand-alone queue manager from this Connection Factory, the queue manager running on the system hostname1(port1) is not accessible. This means that the application ends up with a Connection to the queue manager running on hostname2(port2).

Another application now comes along and creates a JMS Connection from the same Connection Factory. The queue manager on hostname1(port1) is now available, so a new JMS Connection is created to this WebSphere MQ system and is returned to the application.

When both applications have finished, they close their JMS Connections, which causes them to be returned to the Connection Pool.

This means that the Connection Pool for our Connection Factory now contains two JMS Connections:
  • One connection to the queue manager running on hostname1(port1).
  • One connection to the queue manager running on hostname2(port2).

This can lead to issues relating to transaction recovery. If the Java EE system needs to roll back a transaction, it needs to be able to connect to a queue manager that has access to the transaction logs


Implementing reconnection logic in a Java EE application
Enterprise JavaBeans and Web-based applications that want to automatically reconnect if a queue manager fails need to implement their own reconnection logic. Here are some design patterns that can be used by these types of applications:


1. Allow the application to fail


public class SimpleServlet extends HttpServlet {

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
    throws ServletException, IOException {

    try {
      // get connection factory/ queue
      InitialContext ic = new InitialContext();
      ConnectionFactory cf =
                (ConnectionFactory)ic.lookup("java:comp/env/jms/WMQCF");
      Queue q = (Queue) ic.lookup("java:comp/env/jms/WMQQueue");

      // send a message
      Connection c = cf.createConnection();
      Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
      MessageProducer p = s.createProducer(q);
      Message m = s.createTextMessage();
      p.send(m);

      // done, release the connection
      c.close();
    }
      catch (JMSException je) {
    // process exception
    }
  }
}



Here, it is assumed that the Connection Factory that this Servlet is using has the CONNECTIONNAMELIST property defined.

When the Servlet first executes, a new connection will be created using the CONNECTIONNAMELIST (assuming that no pooled connections are available from other applications connecting to the same queue manager).

When the connection is released following a close() call, this connection will be returned to the pool and reused the next time the Servlet executes - without referring to the CONNECTIONNAMELIST - until a connection failure occurs, at which point a CONNECTION_ERROR_OCCURRED event will be generated, which prompts the pool to destroy the failed connection.

When the application next executes, no pooled connection will be available and the CONNECTIONNAMELIST is used to connect to the first available queue manager. If queue manager failover has taken place (for example, the failure was not a transitory network failure) then the Servlet will connect to the backup instance once it is available.

This approach requires no application changes, but does require an administrative reconfiguration of the Connection Factory definition to include the CONNECTIONNAMELIST property.

However, it does require the invoker to be able to handle a failure appropriately (note that this is also required for failures such as MQRC_Q_FULL that are not related to connection failure).

If other resources, such as databases, are involved in the application, it may be appropriate to indicate that the application server should rollback the transaction.

2. Handle reconnection within the application

If the invoker is unable to process a failure from the Servlet, then reconnection must be handled within the application. This requires the application to cache the Connection Factory it looked up from JNDI and handle a JMSException, such as:

JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').

by requesting a new Connection.


public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

  // get connection factory/ queue
  InitialContext ic = new InitialContext();
  ConnectionFactory cf = (ConnectionFactory)
               ic.lookup("java:comp/env/jms/WMQCF");
  Destination destination = (Destination) ic.lookup("java:comp/env/jms/WMQQueue");

  setupResources();
 
  // loop sending messages
  while (!sendComplete) {
    try {
      // create the next message to send
      msg.setText("message sent at "+new Date());
      // and send it
      producer.send(msg);
    }
    catch (JMSException je) {
        // drive reconnection
        setupResources();
    }
  }



Here, setupResources() creates the JMS objects and includes a sleep/retry loop to handle non-instantaneous reconnection (in practice this method would prevent many reconnect attempts; exit conditions have been omitted for clarity)


private void setupResources() {

    boolean connected = false;
    while (!connected) {
      try {
        connection = cf.createConnection(); // cf cached from JNDI lookup
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        msg = session.createTextMessage();
        producer = session.createProducer(destination); // destination cached from JNDI lookup
        // no exception? then we connected ok
        connected = true;
      }
      catch (JMSException je) {
        // sleep and then have another attempt
        try {Thread.sleep(30*1000);} catch (InterruptedException ie) {}
      }
    }



If the application manages reconnection, it is important that it releases any connections that are held to other resources (whether other WebSphere MQ queue managers or other backend services such as databases). These must then be re-established once reconnection to a new WebSphere MQ queue manager instance is complete. If this is not done then application server resources are held unnecessarily for the duration of the reconnection attempt, and may have been timed out by the time they are reused.

3. Use of the WorkManager

For long-lived applications (e.g. batch processing) where execution time is greater than a few tens of seconds, the WebSphere Application Server WorkManager may be used. A code fragment example for WebSphere Application Server is included.


public class BatchSenderServlet extends HttpServlet  {
 
  private WorkManager workManager = null;
  private MessageSender sender; // background sender WorkImpl
 
  public void init() throws ServletException {
    InitialContext ctx = new InitialContext();
    workManager = (WorkManager)ctx.lookup(java:comp/env/wm/default);
    sender = new MessageSender(5000);
    workManager.startWork(sender);
  }

  public void destroy() {
    sender.halt();
  }

  public void doGet(HttpServletRequest req, HttpServletResponse res)
                               throws ServletException, IOException {
    res.setContentType("text/plain");
    PrintWriter out = res.getWriter();
    if (sender.isRunning()) {
      out.println(sender.getStatus());
    }
}



where web.xml contains


 <resource-ref>
      <description>WorkManager</description>
      <res-ref-name>wm/default</res-ref-name>
      <res-type>com.ibm.websphere.asynchbeans.WorkManager</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
   </resource-ref>



and the batch send is now implemented via the Work interface


import com.ibm.websphere.asynchbeans.Work;

public class MessageSender implements Work {

  public MessageSender(int messages) {numberOfMessages = messages;}

  public void run() {
    // get connection factory/ queue
    InitialContext ic = new InitialContext();
    ConnectionFactory cf = (ConnectionFactory)
               ic.lookup("java:comp/env/jms/WMQCF");
    Destination destination = (Destination) ic.lookup("jms/WMQQueue");

    setupResources();
 
    // loop sending messages
    while (!sendComplete) {
      try {
        // create the next message to send
        msg.setText("message sent at "+new Date());
        // and send it
        producer.send(msg);
        // are we finished?
        if (sendCount == numberOfMessages) {sendComplete = true);
      }
      catch (JMSException je) {
          // drive reconnection
          setupResources();
      }
  }

  public boolean isRunning() {return !sendComplete;}

  public void release() {sendComplete = true;}
}



If the batch processing takes a long time to execute (e.g. large messages, slow network, extensive database access etc., especially when coupled with slow failover) then the server will start to output hung thread warnings, similar to the one shown below:

WSVR0605W: Thread "WorkManager.DefaultWorkManager : 0" (00000035) has been active for 694061 milliseconds and may be hung. There is/are 1 thread(s) in total in the server that may be hung.

These may be minimized by reducing the batch size, or increasing the hung thread timeout. However, it is generally preferable to implement this processing in an EJB (for batch send) or message-driven bean (for consume or consume/reply) processing.



Application-managed reconnection does not provide a general solution to handling runtime errors, and the application must still handle errors that are not related to connection failure, for example attempting to put a message to a queue that is full (2053 MQRC_Q_FULL), or attempting to connect to a queue manager using invalid security credentials (2035 MQRC_NOT_AUTHORIZED). It must also handle 2059 MQRC_Q_MGR_NOT_AVAILABLE errors when no instances are immediately available when failover is in progress. This may be achieved by the application reporting the JMSExceptions as they occur instead of silently attempting to reconnect.

[{"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Product":{"code":"SSFKSJ","label":"WebSphere MQ"},"Component":"Java","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"},{"code":"PF033","label":"Windows"}],"Version":"9.1;9.0;8.0;7.5;7.1;7.0","Edition":"All Editions","Line of Business":{"code":"LOB45","label":"Automation"}},{"Product":{"code":"SSYHRD","label":"IBM MQ"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":" ","Platform":[{"code":"","label":""}],"Version":"","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Product Synonym

MQ WMQ MQSeries

Document Information

Modified date:
13 March 2020

UID

swg21508357