JMS Reattach Example

This example demonstrates how ActiveMQ connections can be configured to be resilient to temporary network failures.

In the case of a network failure being detected, either as a result of a failure to read/write to the connection, or the failure of a pong to arrive back from the server in good time after a ping is sent, instead of failing the connection immediately and notifying any user ExceptionListener objects, ActiveMQ can be configured to automatically retry the connection, and reattach to the server when it becomes available again across the network.

When the client reattaches to the server it will be able to resume using its sessions and connections where it left off

This is different to client reconnect as the sessions, consumers etc still exist on the server. With reconnect The client recreates its sessions and consumers as needed.

This example starts a single server, connects to it and performs some JMS operations. We then simulate failure of the network connection by temporarily stopping the network acceptor on the server. (This is done by sending management messages, but that is not central to the purpose of the example).

We then wait a few seconds, then restart the acceptor. The client reattaches and the session resumes as if nothing happened.

The JMS Connection Factory is configured to reattach automatically by specifying the various reconnect related attributes in the activemq-jms.xml file.

For more details on how to configure this and for clustering in general please consult the ActiveMQ user manual.

Example step-by-step

To run the example, simply type mvn verify -Pexample from this directory

  1. Create an initial context to perform the JNDI lookup.
  2.            initialContext = getContext(0);
            
  3. Perform a lookup on the queue
  4.            Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");
            
  5. Perform a lookup on the Connection Factory
  6.            ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
            
  7. We create a JMS connection
  8.            connection = cf.createConnection();
            
  9. We create a JMS session.
  10.            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            
  11. We create a JMS message producer.
  12.           MessageProducer messageProducer = session.createProducer(topic);
           
  13. We create a JMS text message that we are going to send.
  14.            TextMessage message = session.createTextMessage("This is a text message");
            
  15. We send message to the queue
  16.            messageProducer.send(message);
            
  17. We create a JMS Message Consumer to receive the message.
  18.            MessageConsumer messageConsumer = session.createConsumer(queue);
            
  19. We start the connection. In order for delivery to occur on any consumers or subscribers on a connection, the connection must be started
  20.            connection.start();
            
  21. To simulate a temporary problem on the network, we stop the remoting acceptor on the server which will cause all client connections to fail.
  22.            stopAcceptor(initialContext);
            
  23. We wait 10 seconds, before restarting the acceptor. During this period the client will be retrying to connect. When the acceptor is restarted it will be successful in reconnecting.
  24.            
                Thread.sleep(10000);
    
                startAcceptor(initialContext);
               
            
  25. We receive the message after reattachment! Note that no exceptions were received by the client.
  26.            
               TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
               
            
  27. And finally, always remember to close your JMS connections and resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
  28.            finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }