JMS Multiple Failover using Replication Example

This example demonstrates three servers coupled as a live-backup-backup group for high availability (HA) using replication, and a client connection failing over from live to backup when the live server is crashed and then to the second backup once the new live fails.

For more information on ActiveMQ failover and HA, and clustering in general, please see the clustering section of the user manual.

Example step-by-step

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

In this example, the live server is server 1, and the backup server is server 0

The connection will initially be created to server1, server 1 will crash, and the client will carry on seamlessly on server 0, the backup server.

  1. Get an initial context for looking up JNDI from server #0.
  2.            initialContext = getContext(0);
            
  3. Look up the JMS resources from JNDI on server #0.
  4.            Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
               ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
            
  5. Create a JMS Connection
  6.            connection = connectionFactory.createConnection();
            
  7. Create a client acknowledged Session
  8.            Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            
  9. Start the connection to ensure delivery occurs
  10.            connection.start();
            
  11. Create a JMS MessageProducer
  12.            MessageProducer producer = session.createProducer(queue);
            
  13. Create a JMS MessageConsumer
  14.            MessageConsumer consumer = session.createConsumer(queue);
            
  15. Send some messages to server #0, the live server
  16.            for (int i = 0; i < numMessages; i++)
                {
                    TextMessage message = session.createTextMessage("This is text message " + i);
                    producer.send(message);
                    System.out.println("Sent message: " + message.getText());
                }
            
  17. Receive and acknowledge a third of the sent messages
  18.            TextMessage message0 = null;
                for (int i = 0; i < numMessages / 3; i++)
                {
                   message0 = (TextMessage)consumer.receive(5000);
                   System.out.println("Got message: " + message0.getText());
                }
                message0.acknowledge();
            

    When server #0 crashes, the client automatically detects the failure and automatically fails over from server #0 to server #1 (in your real program you wouldn't need to sleep).

  19. Acknowledging the 2nd third of the sent messages will fail as failover to the backup server has occurred
  20.            try
                 {
                   message0.acknowledge();
                }
                 catch (JMSException e)
                {
                   System.err.println("Got exception while acknowledging message: " + e.getMessage());
                }
            
  21. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered.
  22.            for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++)
                {
                  message0 = (TextMessage)consumer.receive(5000);
                 System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered());
                 }
             message0.acknowledge();
            

    now we Kill server #1 and wait for the server #2 to take over the responsibilities.

  23. Acknowledging the 3rd third of the sent messages will fail as failover to the backup server has occurred
  24.            try
                {
                   message0.acknowledge();
               }
               catch (JMSException e)
              {
                    System.err.println("Got exception while acknowledging message: " + e.getMessage());
                 }
            
  25. Consume again the 3rd third of the messages again. Note that they are not considered as redelivered
  26.             for (int i = (numMessages / 3) * 2; i < numMessages; i++)
                 {
                   message0 = (TextMessage)consumer.receive(5000);
                   System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered());
                }
                 message0.acknowledge();
            
  27. And finally, always remember to close your 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 (connection != null)
                  {
                     connection.close();
                  }
    
                  if (initialContext != null)
                  {
                     initialContext.close();
                  }
               }