244 lines
12 KiB
HTML
244 lines
12 KiB
HTML
<!--
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
-->
|
|
|
|
<html>
|
|
<head>
|
|
<title>ActiveMQ JMS Bridge Example</title>
|
|
<link rel="stylesheet" type="text/css" href="../common/common.css" />
|
|
<link rel="stylesheet" type="text/css" href="../common/prettify.css" />
|
|
<script type="text/javascript" src="../common/prettify.js"></script>
|
|
</head>
|
|
<body onload="prettyPrint()">
|
|
<h1>JMS Bridge Example</h1>
|
|
<p>This example shows you how to create a JMS Bridge between two ActiveMQ servers.</p>
|
|
<img src="jms-bridge.png" />
|
|
<p>The example will use two ActiveMQ servers:</p>
|
|
<ul>
|
|
<li>Server #0 – the <em>Source</em> server. It will be configured with a JMS Topic bound to JNDI under <code>source/topic</code>
|
|
<li>Server #1 – the <em>Target</em> server. It will be configured with a JMS Queue bound to JNDI under <code>target/queue</code><br />
|
|
</ul>
|
|
<p>Both ActiveMQ server will run their own JNDI server used by the JMS Bridge and the JMS Client to lookup JMS
|
|
resources (ConnectionFactory and Destination).</p>
|
|
<p>The JMS Bridge will be started in the example code and be configured to bridge messages from the <em>source</em> destination
|
|
(the topic hosted on server #0) and the <em>target</em> destination (the queue hosted on server #1)</p>
|
|
<p>The client will check the bridge works by:</p>
|
|
<ol>
|
|
<li>sending a message to the <em>source</em> topic</li>
|
|
<li>receive a message from the <em>target</em> queue</li>
|
|
<li>check that both messages correspond to the same content.</li>
|
|
</ol>
|
|
<h3>JMS Bridge Configuration</h3>
|
|
<p>The JMS Bridge is a <abbr title="Plain Old Java Object">POJO</abbr> that we configure with both source and target
|
|
JNDI configurations. In the actual example we are programatically creating the Bridge, however the following section
|
|
describes how you would do this if you wanted to deploy with an actual ActiveMQ server via the activemq-beans.xml.
|
|
|
|
<h4>Configuring the Bridge with the JBoss Microcontainer</h4>
|
|
<p>
|
|
in which we inject JNDI configurations
|
|
so that it looks up its source and target JMS resources.
|
|
The JMS Bridge is defined a bean and setup by JBoss Microntainer in the same VM than Server #1, the target server.</p>
|
|
|
|
</p>The JMS Bridge sample configuration can be found in <code>resources/activemq-beans.xml</code>, firstly we define the
|
|
Bridge itself:</p>
|
|
<pre class="prettyprint">
|
|
<!-- The JMS Bridge -->
|
|
<bean name="JMSBridge" class="org.apache.activemq.jms.bridge.impl.JMSBridgeImpl">
|
|
...
|
|
</bean>
|
|
</pre>
|
|
<p>the <code>JMSBridgeImpl</code> constructor is used to inject all the properties required to run the JMS Bridge.</p>
|
|
<p>Its first four arguments defines how the bridge will lookup:</p>
|
|
<ol>
|
|
<li>its <em>source</em> JMS ConnectionFactory</li>
|
|
<li>its <em>source</em> JMS Destination</li>
|
|
<li>its <em>target</em> JMS ConnectionFactory</li>
|
|
<li>its <em>target</em> JMS Destination</li>
|
|
</ol>
|
|
<p>Using other POJOs, the JMS Bridge is configured to retrieve:</p>
|
|
<ul>
|
|
<li>its <em>source</em> JMS ConnectionFactory by looking up <code>/source/ConnectionFactory</code> using
|
|
the <code>SourceJNDI</code> configuration</li>
|
|
<li>its <em>source</em> JMS Destination by looking up <code>/source/topic</code> using
|
|
the <code>SourceJNDI</code> configuration</li>
|
|
<li>its <em>target</em> JMS ConnectionFactory by looking up <code>/target/ConnectionFactory</code> using
|
|
the <code>TargetJNDI</code> configuration</li>
|
|
<li>its <em>target</em> JMS ConnectionFactory by looking up <code>/target/queue</code> using
|
|
the <code>TargetJNDI</code> configuration</li>
|
|
</ul>
|
|
<p>In turn, <code>SourceJNDI</code> and <code>TargetJNDI</code> are POJOs defining how to connect to JNDI server.
|
|
SourceJNDI URL must point to your source server, while LocalJNDI must point to your target server:</p>
|
|
<pre class="prettyprint">
|
|
<bean name="SourceJNDI" class="java.util.Hashtable">
|
|
...
|
|
<entry>
|
|
<key>java.naming.provider.url</key>
|
|
<!-- **************************************** -->
|
|
<!-- Replace with the *source* server address -->
|
|
<!-- **************************************** -->
|
|
<value>jnp://192.168.0.10:1099</value>
|
|
...
|
|
</bean>
|
|
<bean name="TargetJNDI" class="java.util.Hashtable">
|
|
...
|
|
<ntry>
|
|
<key>java.naming.provider.url</key>
|
|
<!-- **************************************** -->
|
|
<!-- Replace with the *target* server address -->
|
|
<!-- **************************************** -->
|
|
<value>jnp://1192.168.0.11:1099</value>
|
|
</entry>
|
|
...
|
|
</bean>
|
|
</pre>
|
|
<h2>Example step-by-step</h2>
|
|
<p>To run the example after having setup both ActiveMQ servers and the JMS bridge:</p>
|
|
<ol>
|
|
<li>To run the example simply run <code>mvn verify -Pexample</code></li>
|
|
</ol>
|
|
<p>Let's look at the Client code (in <code>JMSBridgeExample</code> class):</p>
|
|
<ol>
|
|
<li>First we need to get an initial context so we can look-up the JMS resources</li>
|
|
<pre class="prettyprint">
|
|
InitialContext sourceContext = createContext(sourceServer);
|
|
InitialContext targetContext = createContext(targetServer);
|
|
</pre>
|
|
<li>We then create a JMS Bridge and start it, Note, for certain quality of service modes such as
|
|
ONCE_AND_ONCE_ONLY and AT_LEAST_ONCE a Transaction Manager is required to ensure Messages are delivered
|
|
accordingly. A Transaction Manager can be either loaded via implementation of TransactionManagerLocator intefer
|
|
and loaded via standard a ServiceLoader or by explicitly setting an instance of a Transaction Manager on the
|
|
bridge using setTranscationManager(TransactionManager tm) method. In this example we'll be using the DUPLICATES_OK
|
|
quality of service so there is no need for a Transaction Manager.
|
|
<pre class="prettyprint">
|
|
JMSBridge jmsBridge = new JMSBridgeImpl(
|
|
new JNDIConnectionFactoryFactory(sourceJndiParams, "source/ConnectionFactory"),
|
|
new JNDIConnectionFactoryFactory(targetJndiParams, "target/ConnectionFactory"),
|
|
new JNDIDestinationFactory(sourceJndiParams, "source/topic"),
|
|
new JNDIDestinationFactory(targetJndiParams, "target/queue"),
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
5000,
|
|
10,
|
|
QualityOfServiceMode.DUPLICATES_OK,
|
|
1,
|
|
-1,
|
|
null,
|
|
null,
|
|
true);
|
|
....
|
|
jmsBridge.start();
|
|
</pre>
|
|
<li>We look up the JMS resources from the Source server</li>
|
|
<pre class="prettyprint">
|
|
ConnectionFactory sourceConnectionFactory = (ConnectionFactory)sourceContext.lookup("source/ConnectionFactory");
|
|
Topic sourceTopic = (Topic)sourceContext.lookup("source/topic");
|
|
</pre>
|
|
|
|
<li>We create JMS objects to send a message to the source destination</li>
|
|
<pre class="prettyprint">
|
|
sourceConnection = sourceConnectionFactory.createConnection();
|
|
Session sourceSession = sourceConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
MessageProducer sourceProducer = sourceSession.createProducer(sourceTopic);
|
|
</pre>
|
|
|
|
<li>We send a message to the source destination</li>
|
|
<pre class="prettyprint">
|
|
TextMessage message = sourceSession.createTextMessage("this is a text message sent at " + System.currentTimeMillis());
|
|
sourceProducer.send(message);
|
|
</pre>
|
|
|
|
<li>We close the connection to the source server</li>
|
|
<pre class="prettyprint">
|
|
sourceConnection.close();
|
|
</pre>
|
|
|
|
<p>At this point, the JMS Bridge will consume the message from the source topic and
|
|
sends it to the target queue.
|
|
The client will check the bridge works by consuming a message from the target queue.</p>
|
|
|
|
<li>We look up the JMS resources from the target server</li>
|
|
<pre class="prettyprint">
|
|
ConnectionFactory targetConnectionFactory = (ConnectionFactory)targetContext.lookup("target/ConnectionFactory");
|
|
Queue targetQueue = (Queue)targetContext.lookup("target/queue");
|
|
</pre>
|
|
|
|
<li>We create JMS objects to receive a message from the target destination</li>
|
|
<pre class="prettyprint">
|
|
targetConnection = targetConnectionFactory.createConnection();
|
|
Session targetSession = targetConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
MessageConsumer targetConsumer = targetSession.createConsumer(targetQueue);
|
|
</pre>
|
|
|
|
<li>We start the target connection to start receiving messages
|
|
<pre class="prettyprint">
|
|
targetConnection.start();
|
|
</pre>
|
|
|
|
<li>We receive the message and print it. Its content is the same than the message
|
|
the client sent to the source topic</li>
|
|
<pre class="prettyprint">
|
|
TextMessage messageReceived = (TextMessage)targetConsumer.receive(5000);
|
|
</pre>
|
|
|
|
<li>We display the message ID and its "bridged" message ID</li>
|
|
<pre class="prettyprint">
|
|
System.out.format("Message ID : %s\n", messageReceived.getJMSMessageID());
|
|
System.out.format("Bridged Message ID : %s\n", messageReceived.getStringProperty("HQ_BRIDGE_MSG_ID_LIST"));
|
|
</pre>
|
|
|
|
<p>Note that the message received from the target queue is <em>not the same message</em> sent to the source topic
|
|
(their message IDs are different) but they have the <em>same content</em>.
|
|
|
|
<li>And finally, we stop the Bridge and <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
|
|
|
|
<pre class="prettyprint">
|
|
<code>finally
|
|
{
|
|
if (jmsBridge != null)
|
|
{
|
|
jmsBridge.stop();
|
|
}
|
|
if (initialContext != null)
|
|
{
|
|
initialContext.close();
|
|
}
|
|
if (connection != null)
|
|
{
|
|
connection.close();
|
|
}
|
|
}</code>
|
|
</pre>
|
|
|
|
|
|
|
|
</ol>
|
|
|
|
<h2>More information</h2>
|
|
|
|
<ul>
|
|
<li>User Manual's <a href="../../../docs/user-manual/en/html_single/appserver-integration.html#jms-bridge">JMS Bridge chapter</a></li>
|
|
<li>The <a href="../../javaee/jms-bridge/readme.html">Java EE JMS Bridge example</a> shows how to configure a JMS Bridge
|
|
inside JBoss Application Server to bridge destinations from the same server.</a>
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|