JBoss Messaging JMS Automatic (Transparent) Failover (HA) Example


This example demonstrates two servers coupled as a live-backup pair for high availability (HA), and a client connection transparently failing over from live to backup when the live server is crashed.

JBoss Messaging implements seamless, transparent failover of client connections between live and backup servers. This is implemented by the replication of state between live and backup nodes. When replication is configured and a live node crashes, the client connections can carry on as if nothing happened and carry on sending and consuming messages.

With JBoss Messaging there is no need to code any special client side failover logic in order to benefit from failover and HA. There is no need to refactor your messaging applications to work in an HA environment.

JBoss Messaging also supports manual failover which is covered in a separate example.

For more information on JBoss Messaging 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 ant 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 1.
  2.            initialContext = getContext(1);
            
  3. Look-up the JMS Queue object from JNDI on server 1.
  4.            Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
            
  5. Look-up a JMS Connection Factory object from JNDI on server 1
  6.            ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
            
  7. We create a JMS Connection
  8.           connection = connectionFactory.createConnection();
            
  9. We create a JMS Session
  10.            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            
  11. We start the connection to ensure delivery occurs on them
  12.            
       connection.start();
               
            
  13. We create a JMS MessageConsumer
  14.            
       MessageConsumer consumer = session.createConsumer(queue);
               
            
  15. We create a JMS MessageProducer
  16.            
       MessageProducer producer = session.createProducer(queue);
            
  17. We send some messages to server 1, the live server. As we do operations on the live server they are transparently replicated to server 0 the backup server, behind the scenes.
  18.            
    	      final int numMessages = 10;
    
             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());
             }
               
            
  19. We now cause server 1, the live server, to crash, and wait a little while to make sure it has really crashed. When server 1 crashes, the client automatically detects the failure and automatically fails over from server 1 to server 0. (In your real program you wouldn't need to sleep).
  20.            
    	      killServer(1); // This causes the live server to crash
             
             Thread.sleep(2000); // Just wait a little while to make sure the live server has really crashed.
               
            
  21. We consume the messages sent before the crash of the live server. We are now transparently reconnected to server 0 - the backup server. Note that all this reconnection has been done without the client being aware it has been reconnected!
  22.            
             for (int i = 0; i < numMessages; i++)
             {
                TextMessage message0 = (TextMessage)consumer.receive(5000);
    
                System.out.println("Got message: " + message0.getText());
             }
               
            
  23. We now send some more messages.
  24.            
             for (int i = numMessages; i < numMessages * 2; i++)
             {
                TextMessage message = session.createTextMessage("This is text message " + i);
    
                producer.send(message);
    
                System.out.println("Sent message: " + message.getText());
             }
               
            
  25. And consume them.
  26.            
             for (int i = 0; i < numMessages; i++)
             {
                TextMessage message0 = (TextMessage)consumer.receive(5000);
    
                System.out.println("Got message: " + message0.getText());
             }
               
            
  27. And finally (no pun intended), 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();
          }
    	}