JMS Colocated Failover Shared Store Example

This example demonstrates how you can colocate live and backup servers in the same VM. We do this by creating an HA Policy that is colocated. colocated means that backup servers can be created and maintained by live servers on behalf of other requesting live servers. In this example we create a colocated shared store server.

This example starts 2 live servers each with a backup server that backs up the other live server.

The first live server will be killed and the backup in the second will become live

The following shows how to configure the live servers to request and allow backups to be deployed

     <ha-policy>
         <shared-store>
             <colocated>
                 <backup-port-offset>100</backup-port-offset>
                 <backup-request-retries>-1</backup-request-retries>
                 <backup-request-retry-interval>2000</backup-request-retry-interval>
                 <max-backups>1</max-backups>
                 <request-backup>true</request-backup>
                 <master/>
                 <slave/>
             </colocated>
         </shared-store>
     </ha-policy>
     
     

notice that we have used a template to set some sensible defaults but overridden the backup strategy so back ups are full servers

Example step-by-step

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

  1. Get an initial context for looking up JNDI for both servers
  2.            
        initialContext1 = getContext(1);
        initialContext = getContext(0);
       
            
  3. Look up the JMS resources from JNDI
  4.            
        Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
        ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
        ConnectionFactory connectionFactory1 = (ConnectionFactory)initialContext1.lookup("/ConnectionFactory");
               
            
  5. Create a JMS Connections
  6.            
        connection = connectionFactory.createConnection();
        connection1 = connectionFactory1.createConnection();
               
            
  7. Create a *non-transacted* JMS Session with client acknowledgement
  8.            
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        Session session1 = connection1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
               
            
  9. Create a JMS MessageProducer
  10.            
        MessageProducer producer = session.createProducer(queue);
        MessageProducer producer1 = session1.createProducer(queue);
               
            
  11. Send some messages to both servers
  12.           
        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());
          message = session1.createTextMessage("This is another text message " + i);
          producer1.send(message);
          System.out.println("Sent message: " + message.getText());
        }
              
            
  13. Crash server #0, the live server
  14.           
        killServer(0);
              
            
  15. start the connection ready to receive messages
  16.            
        connection1.start();
               
            
  17. create a consumer
  18.            
        MessageConsumer consumer = session1.createConsumer(queue);
                
            
  19. Receive and acknowledge all of the sent messages, the backup server that is colocated with server 1 will have become live and is now handling messages for server 0.
  20.            
        TextMessage message0 = null;
        for (int i = 0; i < numMessages; i++)
        {
           message0 = (TextMessage)consumer.receive(5000);
           System.out.println("Got message: " + message0.getText());
        }
        message0.acknowledge();
               
            
  21. Receive and acknowledge the rest of the sent messages from server 1.
  22.            
       for (int i = 0; i < numMessages; i++)
       {
       message0 = (TextMessage)consumer1.receive(5000);
       System.out.println("Got message: " + message0.getText());
       }
       message0.acknowledge();
               
            
  23. And finally (no pun intended), always remember to close your JMS resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
  24.            
        finally
        {
           if (connection != null)
           {
           connection.close();
           }
    
           if (initialContext != null)
           {
           initialContext.close();
           }
           if (connection1 != null)
           {
           connection1.close();
           }
    
           if (initialContext1 != null)
           {
           initialContext1.close();
           }
        }