| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <meta name="generator" content="Asciidoctor 2.0.23"> |
| <link rel="icon" type="image/png" href="images/favicon.png"> |
| <title>The JMS Bridge</title> |
| <link rel="stylesheet" href="css/asciidoctor.css"> |
| <link rel="stylesheet" href="css/font-awesome.css"> |
| <script> |
| document.addEventListener("DOMContentLoaded", function() { |
| const pathSegments = window.location.pathname.split('/'); |
| if (window.location.hostname == "artemis.apache.org" && pathSegments[pathSegments.length - 2] != "latest") { |
| var message = document.createElement("div"); |
| message.style.margin = "20px"; |
| message.style.textAlign = "center"; |
| message.style.backgroundColor = "#FFFFE0"; |
| message.textContent = "Please be aware that this documentation is out of date. "; |
| |
| var link = document.createElement("a"); |
| link.href = "../../latest"; |
| link.textContent = "Here is the latest documentation."; |
| message.appendChild(link); |
| |
| document.body.insertBefore(message, document.body.firstChild); |
| } |
| }); |
| </script> |
| </head> |
| <body class="book toc2 toc-left"> |
| <div id="header"> |
| <h1>The JMS Bridge</h1> |
| <div id="toc" class="toc2"> |
| <div id="toctitle"><a href="index.html">User Manual for 2.55.0</a></div> |
| <ul class="sectlevel1"> |
| <li><a href="#jms-bridge-parameters">1. JMS Bridge Parameters</a></li> |
| <li><a href="#source-and-target-connection-factories">2. Source and Target Connection Factories</a></li> |
| <li><a href="#source-and-target-destination-factories">3. Source and Target Destination Factories</a></li> |
| <li><a href="#quality-of-service">4. Quality Of Service</a> |
| <ul class="sectlevel2"> |
| <li><a href="#at_most_once">4.1. AT_MOST_ONCE</a></li> |
| <li><a href="#duplicates_ok">4.2. DUPLICATES_OK</a></li> |
| <li><a href="#once_and_only_once">4.3. ONCE_AND_ONLY_ONCE</a></li> |
| <li><a href="#time-outs-and-the-jms-bridge">4.4. Time outs and the JMS bridge</a></li> |
| <li><a href="#examples">4.5. Examples</a></li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div id="content"> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>A fully functional JMS message bridge is available.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function of the bridge is to consume messages from a source queue or topic, and send them to a target queue or topic, typically on a different server.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>The JMS Bridge is not intended as a replacement for transformation and more expert systems such as Camel. |
| The JMS Bridge may be useful for fast transfers as this chapter covers, but keep in mind that more complex scenarios requiring transformations will require you to use a more advanced transformation system.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The source and target servers do not have to be in the same cluster which makes bridging suitable for reliably sending messages from one cluster to another, for instance across a WAN, and where the connection may be unreliable.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A bridge can be deployed as a standalone application or as a web application managed by the embedded Jetty instance bootstrapped with the broker. |
| The source and the target can be located in the same virtual machine or another one.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The bridge can also be used to bridge messages from other JMS servers as long as they are JMS 1.1 compliant.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Do not confuse a JMS bridge with a core bridge. |
| A JMS bridge can be used to bridge any two JMS 1.1 compliant JMS providers and uses the JMS API. |
| A <a href="core-bridges.html#core-bridges">core bridge</a>) is used to bridge any two broker instances and uses the Core API. |
| Always use a core bridge if you can in preference to a JMS bridge. |
| The core bridge will typically provide better performance than a JMS bridge. |
| Also the core bridge can provide <em>once and only once</em> delivery guarantees without using XA.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The bridge has built-in resilience to failure so if the source or target server connection is lost, e.g. due to network failure, the bridge will retry connecting to the source and/or target until they come back online. |
| When it comes back online it will resume operation as normal.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The bridge can be configured with an optional JMS selector, so it will only consume messages matching that JMS selector</p> |
| </div> |
| <div class="paragraph"> |
| <p>It can be configured to consume from a queue or a topic. |
| When it consumes from a topic it can be configured to consume using a non durable or durable subscription</p> |
| </div> |
| <div class="paragraph"> |
| <p>The JMS Bridge is a simple POJO so can be deployed with most frameworks, simply instantiate the <code>org.apache.activemq.artemis.api.jms.bridge.impl.JMSBridgeImpl</code> class and set the appropriate parameters.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="jms-bridge-parameters"><a class="anchor" href="#jms-bridge-parameters"></a><a class="link" href="#jms-bridge-parameters">1. JMS Bridge Parameters</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The main POJO is the <code>JMSBridge</code>. |
| It is configurable by the parameters passed to its constructor.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Source Connection Factory Factory</p> |
| <div class="paragraph"> |
| <p>This injects the <code>SourceCFF</code> bean (also defined in the beans file). |
| This bean is used to create the <em>source</em> <code>ConnectionFactory</code></p> |
| </div> |
| </li> |
| <li> |
| <p>Target Connection Factory Factory</p> |
| <div class="paragraph"> |
| <p>This injects the <code>TargetCFF</code> bean (also defined in the beans file). |
| This bean is used to create the <em>target</em> <code>ConnectionFactory</code></p> |
| </div> |
| </li> |
| <li> |
| <p>Source Destination Factory Factory</p> |
| <div class="paragraph"> |
| <p>This injects the <code>SourceDestinationFactory</code> bean (also defined in the beans file). |
| This bean is used to create the <em>source</em> <code>Destination</code></p> |
| </div> |
| </li> |
| <li> |
| <p>Target Destination Factory Factory</p> |
| <div class="paragraph"> |
| <p>This injects the <code>TargetDestinationFactory</code> bean (also defined in the beans file). |
| This bean is used to create the <em>target</em> <code>Destination</code></p> |
| </div> |
| </li> |
| <li> |
| <p>Source User Name</p> |
| <div class="paragraph"> |
| <p>this parameter is the username for creating the <em>source</em> connection</p> |
| </div> |
| </li> |
| <li> |
| <p>Source Password</p> |
| <div class="paragraph"> |
| <p>this parameter is the parameter for creating the <em>source</em> connection</p> |
| </div> |
| </li> |
| <li> |
| <p>Target User Name</p> |
| <div class="paragraph"> |
| <p>this parameter is the username for creating the <em>target</em> connection</p> |
| </div> |
| </li> |
| <li> |
| <p>Target Password</p> |
| <div class="paragraph"> |
| <p>this parameter is the password for creating the <em>target</em> connection</p> |
| </div> |
| </li> |
| <li> |
| <p>Selector</p> |
| <div class="paragraph"> |
| <p>This represents a JMS selector expression used for consuming messages from the source destination. |
| Only messages that match the selector expression will be bridged from the source to the target destination</p> |
| </div> |
| <div class="paragraph"> |
| <p>The selector expression must follow the <a href="https://docs.oracle.com/javaee/7/api/javax/jms/Message.html">JMS selector syntax</a></p> |
| </div> |
| </li> |
| <li> |
| <p>Failure Retry Interval</p> |
| <div class="paragraph"> |
| <p>This represents the amount of time in ms to wait between trying to recreate connections to the source or target servers when the bridge has detected they have failed</p> |
| </div> |
| </li> |
| <li> |
| <p>Max Retries</p> |
| <div class="paragraph"> |
| <p>This represents the number of times to attempt to recreate connections to the source or target servers when the bridge has detected they have failed. |
| The bridge will give up after trying this number of times. |
| <code>-1</code> represents 'try forever'</p> |
| </div> |
| </li> |
| <li> |
| <p>Quality Of Service</p> |
| <div class="paragraph"> |
| <p>This parameter represents the desired quality of service mode</p> |
| </div> |
| <div class="paragraph"> |
| <p>Possible values are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>AT_MOST_ONCE</code></p> |
| </li> |
| <li> |
| <p><code>DUPLICATES_OK</code></p> |
| </li> |
| <li> |
| <p><code>ONCE_AND_ONLY_ONCE</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>See Quality Of Service section for an explanation of these modes.</p> |
| </div> |
| </li> |
| <li> |
| <p>Max Batch Size</p> |
| <div class="paragraph"> |
| <p>This represents the maximum number of messages to consume from the source destination before sending them in a batch to the target destination. |
| Its value must <code>>= 1</code></p> |
| </div> |
| </li> |
| <li> |
| <p>Max Batch Time</p> |
| <div class="paragraph"> |
| <p>This represents the maximum number of milliseconds to wait before sending a batch to target, even if the number of messages consumed has not reached <code>MaxBatchSize</code>. |
| Its value must be <code>-1</code> to represent 'wait forever', or <code>>= 1</code> to specify an actual time</p> |
| </div> |
| </li> |
| <li> |
| <p>Subscription Name</p> |
| <div class="paragraph"> |
| <p>If the source destination represents a topic, and you want to consume from the topic using a durable subscription then this parameter represents the durable subscription name</p> |
| </div> |
| </li> |
| <li> |
| <p>Client ID</p> |
| <div class="paragraph"> |
| <p>If the source destination represents a topic, and you want to consume from the topic using a durable subscription then this attribute represents the JMS client ID to use when creating/looking up the durable subscription</p> |
| </div> |
| </li> |
| <li> |
| <p>Add MessageID In Header</p> |
| <div class="paragraph"> |
| <p>If <code>true</code>, then the original message’s message ID will be appended in the message sent to the destination in the header <code>ACTIVEMQ_BRIDGE_MSG_ID_LIST</code>. |
| If the message is bridged more than once, each message ID will be appended. |
| This enables a distributed request-response pattern to be used</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>when you receive the message you can send back a response using the correlation id of the first message id, so when the original sender gets it back it will be able to correlate it.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </li> |
| <li> |
| <p>MBean Server</p> |
| <div class="paragraph"> |
| <p>To manage the JMS Bridge using JMX, set the MBeanServer where the JMS Bridge MBean must be registered (e.g. the JVM Platform MBeanServer)</p> |
| </div> |
| </li> |
| <li> |
| <p>ObjectName</p> |
| <div class="paragraph"> |
| <p>If you set the MBeanServer, you also need to set the ObjectName used to register the JMS Bridge MBean (must be unique)</p> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The "transactionManager" property points to a JTA transaction manager implementation and should be set if you need to use the 'ONCE_AND_ONCE_ONLY' Quality of Service. |
| The broker doesn’t ship with such an implementation, but if you are running within an Application Server you can inject the Transaction Manager that is shipped.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="source-and-target-connection-factories"><a class="anchor" href="#source-and-target-connection-factories"></a><a class="link" href="#source-and-target-connection-factories">2. Source and Target Connection Factories</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The source and target connection factory factories are used to create the connection factory used to create the connection for the source or target server.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The configuration example above uses the default implementation that looks up the connection factory using JNDI. |
| For other Application Servers or JMS providers a new implementation may have to be provided. |
| This can easily be done by implementing the interface <code>org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory</code>.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="source-and-target-destination-factories"><a class="anchor" href="#source-and-target-destination-factories"></a><a class="link" href="#source-and-target-destination-factories">3. Source and Target Destination Factories</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Again, similarly, these are used to create or lookup up the destinations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the configuration example above, we have used the default that looks up the destination using JNDI.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A new implementation can be provided by implementing <code>org.apache.activemq.artemis.jms.bridge.DestinationFactory</code> interface.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="quality-of-service"><a class="anchor" href="#quality-of-service"></a><a class="link" href="#quality-of-service">4. Quality Of Service</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The quality of service modes used by the bridge are described here in more detail.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="at_most_once"><a class="anchor" href="#at_most_once"></a><a class="link" href="#at_most_once">4.1. AT_MOST_ONCE</a></h3> |
| <div class="paragraph"> |
| <p>With this QoS mode messages will reach the destination from the source at most once. |
| The messages are consumed from the source and acknowledged before sending to the destination. |
| Therefore, there is a possibility that if failure occurs between removing them from the source and them arriving at the destination, they could be lost. |
| Hence, delivery will occur at most once.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This mode is available for both durable and non-durable messages.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="duplicates_ok"><a class="anchor" href="#duplicates_ok"></a><a class="link" href="#duplicates_ok">4.2. DUPLICATES_OK</a></h3> |
| <div class="paragraph"> |
| <p>With this QoS mode, the messages are consumed from the source and then acknowledged after they have been successfully sent to the destination. |
| Therefore there is a possibility that if failure occurs after sending to the destination but before acknowledging them, they could be sent again when the system recovers. |
| i.e. the destination might receive duplicates after a failure.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This mode is available for both durable and non-durable messages.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="once_and_only_once"><a class="anchor" href="#once_and_only_once"></a><a class="link" href="#once_and_only_once">4.3. ONCE_AND_ONLY_ONCE</a></h3> |
| <div class="paragraph"> |
| <p>This QoS mode ensures messages will reach the destination from the source once and only once. |
| (Sometimes this mode is known as "exactly once"). |
| If both the source and the destination are on the same server instance, then this can be achieved by sending and acknowledging the messages in the same local transaction. |
| If the source and destination are on different servers this is achieved by enlisting the sending and consuming sessions in a JTA transaction. |
| The JTA transaction is controlled by a JTA Transaction Manager, which will need to be set via the settransactionManager method on the Bridge.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This mode is only available for durable messages.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>For a specific application it may possible to provide once and only once semantics without using the ONCE_AND_ONLY_ONCE QoS level. |
| This can be done by using the DUPLICATES_OK mode and then checking for duplicates at the destination and discarding them. |
| Some JMS servers provide automatic duplicate message detection functionality, or this may be possible to implement on the application level by maintaining a cache of received message ids on disk and comparing received messages to them. |
| The cache would only be valid for a certain period of time so this approach is not as watertight as using ONCE_AND_ONLY_ONCE but may be a good choice depending on your specific application.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="time-outs-and-the-jms-bridge"><a class="anchor" href="#time-outs-and-the-jms-bridge"></a><a class="link" href="#time-outs-and-the-jms-bridge">4.4. Time outs and the JMS bridge</a></h3> |
| <div class="paragraph"> |
| <p>There is a possibility that the target or source server will not be available at some point in time. |
| If this occurs then the bridge will try <code>Max Retries</code> to reconnect every <code>Failure Retry Interval</code> milliseconds as specified in the JMS Bridge definition.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you implement your own factories for looking up JMS resources then you will have to bear in mind timeout issues.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="examples"><a class="anchor" href="#examples"></a><a class="link" href="#examples">4.5. Examples</a></h3> |
| <div class="paragraph"> |
| <p>Please see <a href="examples.html#jms-bridge">JMS Bridge Example</a> which shows how to programmatically instantiate and configure a JMS Bridge to send messages to the source destination and consume them from the target destination between two standalone brokers.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </body> |
| </html> |