My goal is to setup a bridge which will forward messages between two queues residing on a different physical servers over the TCP connection. I plan to use two HornetQ services running as part of the latest JBoss (EAP 6.1.0). The "jms-bridge" example from standalone HornetQ distribution has a sample configuration (standalone-example.xml) for JBoss to setup a bridge on a single JBoss instance with HornetQ service. We will have to modify it to support two servers over the network.
In my configuration I have two systems set up, let's name them "laptop1" and "remoteHost", each of them has JBoss with HornetQ service installed. Below are the changes to the configuration from "jms-bridge" example:
- Define new HornetQ connector and acceptor. Note that HornetQ has "netty-connector" defined for JBoss configuration, but seems it does not support "host" and "port" parameters, and rely on mandatory "socket-binding" attribute (see jboss-as-messaging_1_3.xsd from JBoss distribution for more details). That's why I had to redefine both connector and acceptor. For simplicity the acceptor has "0.0.0.0" for host to allow connections from everywhere. Also note that on second server the ports should be listed as opposite - 5457 for acceptor and 5456 for connector.
- Disable the HornetQ security, also for simplicity reasons. The proper approach will be to specify "user" and "password" as parameters for connector above.
- Define two queues: "source" and "target". If desired, for the purposes of this example would be enough to have only one "source" query on local server and one "target" on remote.
- Define a new connection factory to use in bridge.
- Modify bridge definition added after "hornetq-system" tag in settings.xml.
<connector name="netty-bridge">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
<param key="host" value="remoteHost" />
<param key="port" value="5457" />
</connector>
<acceptor name="netty-bridge">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="host" value="0.0.0.0" />
<param key="port" value="5456" />
</acceptor>
<hornetq-server>
<security-enabled>false</security-enabled>
...
<jms-queue name="sourceQueue">
<entry name="queue/sourceQueue"/>
<entry name="java:jboss/exported/jms/queues/sourceQueue"/>
</jms-queue>
<jms-queue name="targetQueue">
<entry name="java:/queue/targetQueue"/>
<entry name="java:jboss/exported/jms/queues/targetQueue"/>
</jms-queue>
<connection-factory name="RemoteConnectionFactoryBridge">
<connectors>
<connector-ref connector-name="netty-bridge"/>
</connectors>
<entries>
<entry name="RemoteConnectionFactoryBridge"/>
<entry name="java:jboss/exported/jms/RemoteConnectionFactoryBridge"/>
</entries>
</connection-factory>
<jms-bridge name="myBridge">
<source>
<connection-factory name="ConnectionFactory" />
<destination name="queue/sourceQueue" />
</source>
<target>
<connection-factory name="RemoteConnectionFactoryBridge" />
<destination name="queue/targetQueue" />
</target>
<quality-of-service>AT_MOST_ONCE</quality-of-service>
<failure-retry-interval>1000</failure-retry-interval>
<max-retries>7890</max-retries>
<max-batch-size>1</max-batch-size>
<max-batch-time>1000</max-batch-time>
</jms-bridge>
18:54:55,621 INFO [org.hornetq.core.server] (MSC service thread 1-1) HQ221024: Started Netty Acceptor version 3.6.2.Final-c0d783c 0.0.0.0:5456 for CORE protocolTo test the configuration, send a sample message to a "sourceQueue" using for example Teiid messageSender from one of my previous articles:
...
18:54:57,953 DEBUG [org.hornetq.core.client] (ServerService Thread Pool -- 61) Remote destination: rokan01-VM3762.ca.com/10.130.248.122:5457
...
18:54:58,723 INFO [org.jboss.messaging] (ServerService Thread Pool -- 61) JBAS011610: Started JMS Bridge myBridge
Now login to JBoss Management Console on your remoteHost (http://remoteHost:9990/console/App.html#jms-metrics) and make sure the messages are gets delivered over the bridge to remote host "targetQueue":call Times.messageSender('queue/sourceQueue', 'My Message1');
There might be a moment when you have only a "connector" side of the bridge up and running. The bridge will automatically reattempt to instantiate the connection every second (configurable by "failure-retry-interval" setting in bridge definition above), until the "acceptor" side of the bridge will be available.