276 lines
11 KiB
Markdown
276 lines
11 KiB
Markdown
# The JMS Bridge
|
|
|
|
Apache ActiveMQ Artemis includes a fully functional JMS message bridge.
|
|
|
|
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 that will play on use cases that will go beyond Apache
|
|
> ActiveMQ Artemis.
|
|
|
|
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 Apache ActiveMQ
|
|
Artemis. 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 non Apache ActiveMQ
|
|
Artemis 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 [core
|
|
> bridge](core-bridges.md)) 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 *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 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 [JMS selector
|
|
syntax](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html)
|
|
|
|
- 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 a 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 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. Apache ActiveMQ Artemis 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 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
|
|
`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 provided by Apache
|
|
ActiveMQ Artemis 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 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.
|
|
|
|
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 [JMS Bridge Example](examples.md#jms-bridge) 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.
|