activemq-artemis/examples/jms/jms-bridge
jbertram a102983d7a ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
..
src/main ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
jms-bridge.png ACTIVEMQ6-1 - Initial HornetQ Donation Commit 2014-11-10 10:31:25 -06:00
pom.xml ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
readme.html ACTIVEMQ6-14 Replace JNDI server with client impl 2014-12-05 09:27:52 -06:00

readme.html

<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 &ndash; the <em>Source</em> server. It will be configured with a JMS Topic bound to JNDI under <code>source/topic</code>
        <li>Server #1 &ndash; 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">
         &lt;!-- The JMS Bridge -->
         &lt;bean name="JMSBridge" class="org.apache.activemq.jms.bridge.impl.JMSBridgeImpl">
         ...
         &lt;/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">
      &lt;bean name="SourceJNDI" class="java.util.Hashtable">
         ...
                &lt;entry>
                   &lt;key>java.naming.provider.url&lt;/key>
                   &lt;!-- **************************************** -->
                   &lt;!-- Replace with the *source* server address -->
                   &lt;!-- **************************************** -->
                   &lt;value>jnp://192.168.0.10:1099&lt;/value>
         ...
       &lt;/bean>
       &lt;bean name="TargetJNDI" class="java.util.Hashtable">
         ...
                &lt;ntry>
                   &lt;key>java.naming.provider.url&lt;/key>
                   &lt;!-- **************************************** -->
                   &lt;!-- Replace with the *target* server address -->
                   &lt;!-- **************************************** -->
                   &lt;value>jnp://1192.168.0.11:1099&lt;/value>
                &lt;/entry>
         ...
       &lt;/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</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, the Bridge needs a transaction manager, in this instance we will use the JBoss TM</li>
        <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.ONCE_AND_ONLY_ONCE,
               1,
               -1,
               null,
               null,
               true);
            jmsBridge.setTransactionManager(new TransactionManagerImple());
            ....
        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>