| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| <html> |
| <head> |
| <title>ActiveMQ Artemis Application-Layer Failover Example</title> |
| <link rel="stylesheet" type="text/css" href="../../../common/common.css" /> |
| <link rel="stylesheet" type="text/css" href="../../../common/prettify.css" /> |
| <script type="text/javascript" src="../../../common/prettify.js"></script> |
| </head> |
| <body onload="prettyPrint()"> |
| <h1>Application-Layer Failover Example</h1> |
| |
| <pre>To run the example, simply type <b>mvn verify</b> from this directory. This example will always spawn and stop multiple servers.</pre> |
| |
| <p>ActiveMQ Artemis implements fully transparent <b>automatic</b> 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.</p> |
| <p>However, ActiveMQ Artemis also supports <b>Application-Layer</b> failover which is useful in the case where replication is not enabled.</p> |
| <p>With Application-Layer failover, it's up to the application to register a JMS ExceptionListener with ActiveMQ Artemis. |
| This listener will then be called by ActiveMQ Artemis in the event that connection failure is detected.</p> |
| <p>User code in the ExceptionListener can then recreate any JMS Connection, Session, etc on another node and the application |
| can continue.</p> |
| <p>Application-Layer failover is an alternative approach to High Availability (HA).</p> |
| <p>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.</p> |
| <p>For more information on ActiveMQ Artemis failover and HA, and clustering in general, please see the clustering |
| section of the user manual.</p> |
| |
| <h2>Example step-by-step</h2> |
| <p>In this example, the live server is server 1, which will failover onto server 0.</p> |
| <p>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.</p> |
| |
| <ol> |
| <li> We create our JMS Connection, Session, MessageProducer and MessageConsumer on server 1</li> |
| <pre class="prettyprint"> |
| <code>createJMSObjects(1);</code> |
| </pre> |
| |
| <li>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.</li> |
| <pre class="prettyprint"> |
| <code>connection.setExceptionListener(new ExampleListener());</code> |
| </pre> |
| |
| <li>We send some messages to server 1, the live server.</li> |
| <pre class="prettyprint"> |
| <code> |
| 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()); |
| } |
| </code> |
| </pre> |
| |
| <li>We consume those messages on server 1.</li> |
| <pre class="prettyprint"> |
| <code> |
| for (int i = 0; i < numMessages; i++) |
| { |
| TextMessage message0 = (TextMessage)consumer.receive(5000); |
| |
| System.out.println("Got message: " + message0.getText()); |
| } |
| </code> |
| </pre> |
| |
| <li>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.</li> |
| <pre class="prettyprint"> |
| <code>killServer(1);</code> |
| </pre> |
| |
| <li>The connection's ExceptionListener gets called, and we lookup the JMS objects and |
| recreate the connection, session, etc on the other node 0.</li> |
| <pre class="prettyprint"> |
| <code> |
| 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(); |
| } |
| } |
| } |
| </code> |
| </pre> |
| |
| <li>We are now connected to the other node. We now send some more messages.</li> |
| <pre class="prettyprint"> |
| <code> |
| 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()); |
| } |
| </code> |
| </pre> |
| |
| <li>And consume them.</li> |
| <pre class="prettyprint"> |
| <code> |
| for (int i = 0; i < numMessages; i++) |
| { |
| TextMessage message0 = (TextMessage)consumer.receive(5000); |
| |
| System.out.println("Got message: " + message0.getText()); |
| } |
| </code> |
| </pre> |
| |
| |
| <li>And finally (no pun intended), <b>always</b> remember to close your resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li> |
| |
| <pre class="prettyprint"> |
| <code> |
| finally |
| { |
| closeResources(); |
| } |
| </code> |
| </pre> |
| |
| </ol> |
| </body> |
| </html> |