| = The JMS Bridge |
| :idprefix: |
| :idseparator: - |
| :docinfo: shared |
| |
| A fully functional JMS message bridge is available. |
| |
| 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. |
| |
| [NOTE] |
| ==== |
| 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. |
| ==== |
| |
| 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. |
| |
| 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. |
| |
| The bridge can also be used to bridge messages from other JMS servers as long as they are JMS 1.1 compliant. |
| |
| [NOTE] |
| ==== |
| 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 xref:core-bridges.adoc#core-bridges[core bridge]) 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 _once and only once_ delivery guarantees without using XA. |
| ==== |
| |
| 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. |
| |
| The bridge can be configured with an optional JMS selector, so it will only consume messages matching that JMS selector |
| |
| 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 |
| |
| The JMS Bridge is a simple POJO so can be deployed with most frameworks, simply instantiate the `org.apache.activemq.artemis.api.jms.bridge.impl.JMSBridgeImpl` class and set the appropriate parameters. |
| |
| == JMS Bridge Parameters |
| |
| The main POJO is the `JMSBridge`. |
| It is configurable by the parameters passed to its constructor. |
| |
| * Source Connection Factory Factory |
| + |
| This injects the `SourceCFF` bean (also defined in the beans file). |
| This bean is used to create the _source_ `ConnectionFactory` |
| |
| * Target Connection Factory Factory |
| + |
| This injects the `TargetCFF` bean (also defined in the beans file). |
| This bean is used to create the _target_ `ConnectionFactory` |
| |
| * Source Destination Factory Factory |
| + |
| This injects the `SourceDestinationFactory` bean (also defined in the beans file). |
| This bean is used to create the _source_ `Destination` |
| |
| * Target Destination Factory Factory |
| + |
| This injects the `TargetDestinationFactory` bean (also defined in the beans file). |
| This bean is used to create the _target_ `Destination` |
| |
| * Source User Name |
| + |
| this parameter is the username for creating the _source_ connection |
| |
| * Source Password |
| + |
| this parameter is the parameter for creating the _source_ connection |
| |
| * Target User Name |
| + |
| this parameter is the username for creating the _target_ connection |
| |
| * Target Password |
| + |
| this parameter is the password for creating the _target_ connection |
| |
| * Selector |
| + |
| 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 |
| + |
| The selector expression must follow the https://docs.oracle.com/javaee/7/api/javax/jms/Message.html[JMS selector syntax] |
| |
| * Failure Retry Interval |
| + |
| 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 |
| |
| * Max Retries |
| + |
| 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. |
| `-1` represents 'try forever' |
| |
| * Quality Of Service |
| + |
| This parameter represents the desired quality of service mode |
| + |
| Possible values are: |
| |
| ** `AT_MOST_ONCE` |
| ** `DUPLICATES_OK` |
| ** `ONCE_AND_ONLY_ONCE` |
| |
| + |
| See Quality Of Service section for an explanation of these modes. |
| |
| * Max Batch Size |
| + |
| 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 `>= 1` |
| |
| * Max Batch Time |
| + |
| 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 `MaxBatchSize`. |
| Its value must be `-1` to represent 'wait forever', or `>= 1` to specify an actual time |
| |
| * Subscription Name |
| + |
| 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 |
| |
| * Client ID |
| + |
| 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 |
| |
| * Add MessageID In Header |
| + |
| If `true`, then the original message's message ID will be appended in the message sent to the destination in the header `ACTIVEMQ_BRIDGE_MSG_ID_LIST`. |
| If the message is bridged more than once, each message ID will be appended. |
| This enables a distributed request-response pattern to be used |
| + |
| [NOTE] |
| ==== |
| |
| |
| 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. |
| ==== |
| |
| * MBean Server |
| + |
| To manage the JMS Bridge using JMX, set the MBeanServer where the JMS Bridge MBean must be registered (e.g. the JVM Platform MBeanServer) |
| |
| * ObjectName |
| + |
| If you set the MBeanServer, you also need to set the ObjectName used to register the JMS Bridge MBean (must be unique) |
| |
| 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. |
| |
| == Source and Target Connection Factories |
| |
| 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. |
| |
| 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 `org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory`. |
| |
| == Source and Target Destination Factories |
| |
| Again, similarly, these are used to create or lookup up the destinations. |
| |
| In the configuration example above, we have used the default that looks up the destination using JNDI. |
| |
| A new implementation can be provided by implementing `org.apache.activemq.artemis.jms.bridge.DestinationFactory` interface. |
| |
| == Quality Of Service |
| |
| The quality of service modes used by the bridge are described here in more detail. |
| |
| === AT_MOST_ONCE |
| |
| 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. |
| |
| This mode is available for both durable and non-durable messages. |
| |
| === DUPLICATES_OK |
| |
| 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. |
| |
| This mode is available for both durable and non-durable messages. |
| |
| === ONCE_AND_ONLY_ONCE |
| |
| 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. |
| |
| This mode is only available for durable messages. |
| |
| [NOTE] |
| ==== |
| |
| |
| 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. |
| ==== |
| |
| === Time outs and the JMS bridge |
| |
| 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 `Max Retries` to reconnect every `Failure Retry Interval` milliseconds as specified in the JMS Bridge definition. |
| |
| If you implement your own factories for looking up JMS resources then you will have to bear in mind timeout issues. |
| |
| === Examples |
| |
| Please see xref:examples.adoc#jms-bridge[JMS Bridge Example] 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. |