Chapter 27. Configuring Jakarta Messaging Bridges

JBoss EAP messaging includes a Jakarta Messaging bridge, which takes messages from a source destination and send them to a target destination, usually on a different server.

A Jakarta Messaging bridge supports destination mapping in which each link consists of a source and a target defined below:

  • The source defines the destination from which the Jakarta Messaging bridge receives messages. The source consists of a connection factory for creating connections to a Jakarta Messaging provider and a message source destination in that provider.
  • The target defines the destination to which the Jakarta Messaging bridge sends messages received from the source. The target consists of a connection factory for creating connections to a Jakarta Messaging provider and a message target destination in that provider.

If the source destination is a topic, the Jakarta Messaging bridge creates a subscription for it. If the client-id and subscription-name attributes are configured for the Jakarta Messaging bridge, the subscription is durable. This means that no messages are missed if the Jakarta Messaging bridge is stopped and then restarted.

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.

Note

Do not confuse a Jakarta Messaging bridge with a core bridge. A Jakarta Messaging bridge can be used to bridge any two Jakarta Messaging-1.1-compliant providers and uses the Jakarta Messaging API. A Configuring core bridges is used to bridge any two JBoss EAP messaging instances and uses the core API. Whenever possible, use a core bridge instead of a Jakarta Messaging bridge.

Example configuration of a JBoss EAP Jakarta Messaging bridge

<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">
  <server name="default">
  ...
  </server>
  <jms-bridge name="my-jms-bridge" module="org.apache.activemq.artemis" max-batch-time="100" max-batch-size="10" max-retries="1" failure-retry-interval="500" quality-of-service="AT_MOST_ONCE">
    <source destination="jms/queue/InQueue" connection-factory="ConnectionFactory">
      <source-context/>
    </source>
    <target destination="jms/queue/OutQueue" connection-factory="jms/RemoteConnectionFactory">
      <target-context>
        <property name="java.naming.factory.initial" value="org.wildfly.naming.client.WildFlyInitialContextFactory"/>
        <property name="java.naming.provider.url" value="http-remoting://192.168.40.1:8080"/>
      </target-context>
    </target>
  </jms-bridge>
  ...
</subsystem>

In the above example configuration, the Jakarta Messaging bridge uses the connection-factory attribute for creating the following two connections:

  • Source-context, which defines the original destination of the received messages.
  • Target-context, which defines the target destination that receives the messages.

You can use the default implementation provided by Apache ActiveMQ Artemis or Red Hat AMQ that searches the connection factory by using Java Naming and Directory Interface (JNDI). For other application servers or Jakarta Messaging providers, you can provide a new implementation by implementing the interface org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory.

Adding a Jakarta Messaging Bridge Using the Management CLI

A Jakarta Messaging bridge can be added using the following management CLI command. Note that the source and target destinations must already be defined in the configuration. See the table in the appendix for a full list of configurable attributes.

/subsystem=messaging-activemq/jms-bridge=my-jms-bridge:add(quality-of-service=AT_MOST_ONCE,module=org.apache.activemq.artemis,failure-retry-interval=500,max-retries=1,max-batch-size=10,max-batch-time=100,source-connection-factory=ConnectionFactory,source-destination=jms/queue/InQueue,source-context={},target-connection-factory=jms/RemoteConnectionFactory,target-destination=jms/queue/OutQueue,target-context={java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory,java.naming.provider.url=http-remoting://192.168.40.1:8080})

You can review the configuration of a Jakarta Messaging bridge using the read-resource command in the management CLI as in the following example.

/subsystem=messaging-activemq/jms-bridge=my-jms-bridge:read-resource

Add configuration to a Jakarta Messaging bridge by using the write-attribute, as done in this example:

/subsystem=messaging-activemq/jms-bridge=my-jms-bridge:write-attribute(name=ATTRIBUTE,value=VALUE)

Adding a Jakarta Messaging Bridge Using the Management Console

You can also use the management console to add a Jakarta Messaging bridge by following these steps.

  1. Open the management console in a browser and navigate to ConfigurationSubsystemsMessaging (ActiveMQ)JMS Bridge.
  2. Click the Add (+) button and provide the required information when prompted.
  3. Click Add when finished.

27.1. Quality of Service

In JBoss EAP, quality-of-service is a configurable attribute that determines how messages are consumed and acknowledged. The valid values for quality-of-service and their descriptions are below. See the table in the appendix for a full list of Jakarta Messaging bridge attributes.

AT_MOST_ONCE

Messages will reach the destination from the source at the most one time. The messages are consumed from the source and acknowledged before sending to the destination. Therefore, there is a possibility that messages could be lost if a failure occurs between their removal from the source and their arrival at the destination. This mode is the default value.

This mode is available for both durable and non-durable messages.

DUPLICATES_OK

Messages are consumed from the source and then acknowledged after they have been successfully sent to the destination. Therefore, there is a possibility that messages could be sent again if a failure occurs after the initial message was sent but before it is acknowledged.

This mode is available for both durable and non-durable messages.

ONCE_AND_ONLY_ONCE

Messages will reach the destination from the source once and only once. If both the source and the destination are on the same server instance, 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 Jakarta Transactions. The transaction is controlled by a Transaction Manager which will need to be set using the setTransactionManager() method on the bridge.

This mode is only available for durable messages.

Warning

When shutting down a server that has a deployed Jakarta Messaging bridge with the quality-of-service attribute set to ONCE_AND_ONLY_ONCE, be sure to shut the server down with the Jakarta Messaging bridge first to avoid unexpected errors.

It may possible to provide once and only once semantics by using the DUPLICATES_OK mode instead of ONCE_AND_ONLY_ONCE and then checking for duplicates at the destination and discarding them. See Configuring Duplicate Message Detection for more information. However, the cache would only be valid for a certain period of time. This approach therefore is not as watertight as using ONCE_AND_ONLY_ONCE, but it may be a good choice depending on your specific application needs.

27.2. Timeouts and the Jakarta Messaging Bridge

There is a possibility that the target or source server will not be available at some point in time. If this occurs, the bridge will try to reconnect a number of times equal to the value of max-retries. The wait between attempts is set by failure-retry-interval.

Warning

Because each Jakarta Messaging bridge has its own max-retries parameter, you should use a connection factory that does not set the reconnect-attempts parameter, or sets it to 0. This will avoid a potential collision that may result in longer reconnection times. Also note that any connection factory referenced by a Jakarta Messaging bridge with the quality-of-service set to ONCE_AND_ONLY_ONCE needs to have the factory-type set to XA_GENERIC, XA_TOPIC, or XA_QUEUE.

27.3. Resolving the RemoteConnectionFactory exception

When configuring a Jakarta Messaging message bridge, you might get the RemoteConnectionFactory exception. To resolve this exception, perform one or all of the following steps:

  • Add the URL prefix java:/jboss/exported, if needed, based on your client connection from within a Java 2 Platform Enterprise Edition (J2EE) component, a non-J2EE component or remote component.
  • Use two Java Naming and Directory Interface names for your connection factory as shown below:

    <jms-connection-factories>
     <connection-factory name="RemoteConnectionFactory">
      <connectors>
        <connector-ref connector-name="netty"/>
      </connectors>
      <entries>
        <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/> <entry name="jms/RemoteConnectionFactory"/>
      </entries>
     </connection-factory>
    </jms-connection-factories>
  • Use the following code snippet in the spring bean configuration file:

    <jee:jndi-lookup id="jmsConnectionFactory" jndi-name="java:/ConnectionFactory" expected-type="javax.jms.ConnectionFactory" lookup-on-startup="false" />
    Note

    The value of the lookup-on-startup and jndi-name attributes might change according to the application.