blob: 3f1fb71fb83848657b290d7d68657acc468be4c8 [file] [log] [blame]
<!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.18">
<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">
</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.33.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>Apache ActiveMQ Artemis includes a fully functional JMS message bridge.</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 that will play on use cases that will go beyond Apache ActiveMQ Artemis.</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 Apache ActiveMQ Artemis.
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 non Apache ActiveMQ Artemis 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 Apache ActiveMQ Artemis 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>&gt;= 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>&gt;= 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&#8217;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.
Apache ActiveMQ Artemis doesn&#8217;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 provided by Apache ActiveMQ Artemis 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 provided by Apache ActiveMQ Artemis 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 Apache ActiveMQ Artemis 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 Apache ActiveMQ Artemis brokers.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>