JBoss Messaging Application-Layer Failover Example


JBoss Messaging implements fully transparent automatic failover of connections from a live to backup node, this requires no special coding for failover, and is described in a different example. Automatic failover requires server replication.

However, JBoss Messaging also supports Application-Layer failover, useful in the case that replication is not enabled on the server side.

With Application-Layer failover, it's up to the application to register a JMS ExceptionListener with JBoss Messaging which will be called by JBoss Messaging in the event that connection failure is detected.

The code in the ExceptionListener then recreates the JMS Connection, Session, etc on another node and the application can continue.

Application-Layer failover is an alternative approach to High Availabilty (HA).

Application-Layer failover differs from automatic failover in that some client side coding is required in order to implement this. Also, with Application-Layer failover, since the old Session object dies and a new is created, any uncommitted work in the old Session will be lost, and any unacknowledged messages might be redelivered.

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, which will failover onto server 0.

The connection will initially be created to server1, server 1 will crash, and the client will carry on on server 0, the new server. With Application-Layer failover the node that is failed over onto, does not need to be specially configured as a backup server, it can be any node.


  1. We create our JMS Connection, Session, MessageProducer and MessageConsumer on server 1
  2.            createJMSObjects(1);
            
  3. We set a JMS ExceptionListener on the connection. On failure this will be called and the connection, session, etc. will be manually recreated on the backup node.
  4.            connection.setExceptionListener(new ExampleListener());
            
  5. We send some messages to server 1, the live server.
  6.            
             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());
             }
               
            
  7. We consume those messages on server 1.
  8.           
              for (int i = 0; i < numMessages; i++)
             {
                TextMessage message0 = (TextMessage)consumer.receive(5000);
    
                System.out.println("Got message: " + message0.getText());
             }
              
            
  9. We now cause server 1, the live server to crash. After a little while the connection's ExceptionListener will register the failure and reconnection will occur.
  10.            killServer(1);
            
  11. The connection's ExceptionListener gets called, and we lookup the JMS objects and recreate the connection, session, etc on the other node 0.
  12.            
       private class ExampleListener implements ExceptionListener
       {
          public void onException(JMSException exception)
          {
             try
             {
                // Close the old resources
    
                closeResources();
    
                // Create new JMS objects on the backup server
    
                createJMSObjects(0);
    
                failoverLatch.countDown();
             }
             catch (Exception e)
             {
                System.err.println("Failed to handle failover");
    
                e.printStackTrace();
             }
          }
       }   
               
            
  13. We are now connected to the other node. We now send some more messages.
  14.            
       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());
             }
               
            
  15. And consume them.
  16.            
       for (int i = 0; i < numMessages; i++)
             {
                TextMessage message0 = (TextMessage)consumer.receive(5000);
    
                System.out.println("Got message: " + message0.getText());
             }
               
            
  17. 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
  18.            
    	finally
    	{
    	   closeResources();
    	}