ActiveMQ implements fully transparent automatic failover of connections from a live node to a backup node which requires no special coding. This is described in a different example and requires server replication.
However, ActiveMQ also supports Application-Layer failover which is useful in the case where replication is not enabled.
With Application-Layer failover, it's up to the application to register a JMS ExceptionListener with ActiveMQ. This listener will then be called by ActiveMQ in the event that connection failure is detected.
User code in the ExceptionListener can then recreate any 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 ActiveMQ failover and HA, and clustering in general, please see the clustering section of the user manual.
To run the example, simply type mvn verify -Pexample
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.
createJMSObjects(1);
connection.setExceptionListener(new ExampleListener());
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());
}
for (int i = 0; i < numMessages; i++)
{
TextMessage message0 = (TextMessage)consumer.receive(5000);
System.out.println("Got message: " + message0.getText());
}
killServer(1);
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();
}
}
}
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());
}
for (int i = 0; i < numMessages; i++)
{
TextMessage message0 = (TextMessage)consumer.receive(5000);
System.out.println("Got message: " + message0.getText());
}
finally
block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
finally
{
closeResources();
}