2015-01-05 07:45:36 -05:00
|
|
|
<!--
|
|
|
|
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.
|
|
|
|
-->
|
|
|
|
|
2014-10-31 06:20:28 -04:00
|
|
|
<html>
|
|
|
|
<head>
|
2014-11-19 03:44:57 -05:00
|
|
|
<title>ActiveMQ JMS Clustered Grouping Example</title>
|
2014-10-31 06:20:28 -04:00
|
|
|
<link rel="stylesheet" type="text/css" href="../common/common.css">
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>JMS Clustered Grouping Example</h1>
|
|
|
|
|
|
|
|
<p>This example demonstrates how to ensure strict ordering across a cluster using clustered message grouping</p>
|
|
|
|
<p>We create 3 nodes each with a grouping message handler, one with a Local handler and 2 with a Remote handler.</p>
|
|
|
|
<p>The local handler acts as an arbitrator for the 2 remote handlers, holding the information on routes and communicating
|
|
|
|
the routing info with the remote handlers on the other 2 nodes</p>
|
|
|
|
<p>We then send some messages to each node with the same group id set and ensure the same consumer receives all of them</p>
|
|
|
|
<p>Here's the relevant snippet from the server configuration that has the local handler</p>
|
|
|
|
<pre>
|
|
|
|
<code>
|
|
|
|
<cluster-connections>
|
|
|
|
<cluster-connection name="my-cluster">
|
|
|
|
<address>jms</address>
|
|
|
|
<connector-ref>netty-connector</connector-ref>
|
|
|
|
<retry-interval>500</retry-interval>
|
|
|
|
<use-duplicate-detection>true</use-duplicate-detection>
|
|
|
|
<forward-when-no-consumers>true</forward-when-no-consumers>
|
|
|
|
<max-hops>1</max-hops>
|
|
|
|
<discovery-group-ref discovery-group-name="my-discovery-group"/>
|
|
|
|
</cluster-connection>
|
|
|
|
</cluster-connections>
|
|
|
|
|
|
|
|
<grouping-handler name="my-grouping-handler">
|
|
|
|
<type>LOCAL</type>
|
|
|
|
<address>jms</address>
|
|
|
|
<timeout>5000</timeout>
|
|
|
|
</grouping-handler>
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>Here's the relevant snippet from the server configuration that has the remote handlers</p>
|
|
|
|
<pre>
|
|
|
|
<code>
|
|
|
|
<cluster-connections>
|
|
|
|
<cluster-connection name="my-cluster">
|
|
|
|
<address>jms</address>
|
|
|
|
<retry-interval>500</retry-interval>
|
|
|
|
<use-duplicate-detection>true</use-duplicate-detection>
|
|
|
|
<forward-when-no-consumers>true</forward-when-no-consumers>
|
|
|
|
<max-hops>1</max-hops>
|
|
|
|
<discovery-group-ref discovery-group-name="my-discovery-group"/>
|
|
|
|
</cluster-connection>
|
|
|
|
</cluster-connections>
|
|
|
|
|
|
|
|
<grouping-handler name="my-grouping-handler">
|
|
|
|
<type>REMOTE</type>
|
|
|
|
<address>jms</address>
|
|
|
|
<timeout>5000</timeout>
|
|
|
|
</grouping-handler>
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
<p>For more information on ActiveMQ clustering and grouping see the clustering and grouping
|
2014-10-31 06:20:28 -04:00
|
|
|
section of the user manual.</p>
|
|
|
|
<h2>Example step-by-step</h2>
|
|
|
|
<p><i>To run the example, simply type <code>mvn verify</code> from this directory</i></p>
|
|
|
|
|
|
|
|
<ol>
|
|
|
|
<li> Get an initial context for looking up JNDI from server 0.</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ic0 = getContext(0);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Look-up the JMS Queue object from JNDI</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Queue queue = (Queue)ic0.lookup("/queue/exampleQueue");</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Look-up a JMS Connection Factory object from JNDI on server 0</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory");</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Get an initial context for looking up JNDI from server 1.</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ic1 = getContext(1);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Look-up a JMS Connection Factory object from JNDI on server 1</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ConnectionFactory cf1 = (ConnectionFactory)ic1.lookup("/ConnectionFactory");
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Get an initial context for looking up JNDI from server 2.</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ic2 = getContext(2);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Look-up a JMS Connection Factory object from JNDI on server 2</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ConnectionFactory cf2 = (ConnectionFactory)ic2.lookup("/ConnectionFactory");
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Connection connection0 which is a connection to server 0</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>connection0 = cf0.createConnection();</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Connection connection0 which is a connection to server 1</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>connection1 = cf1.createConnection();</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Connection connection0 which is a connection to server 2</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>connection2 = cf2.createConnection();</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Session on server 0</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Session on server 1</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS Session on server 2</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We start the connections to ensure delivery occurs on them</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
connection0.start();
|
|
|
|
|
|
|
|
connection1.start();
|
|
|
|
|
|
|
|
connection2.start();</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create JMS MessageConsumer objects on server 0</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>MessageConsumer consumer = session0.createConsumer(queue);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We create a JMS MessageProducer object on server 0, 1 and 2</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
MessageProducer producer0 = session0.createProducer(queue);
|
|
|
|
|
|
|
|
MessageProducer producer1 = session1.createProducer(queue);
|
|
|
|
|
|
|
|
MessageProducer producer2 = session2.createProducer(queue);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We send some messages to server 0, 1 and 2 with the same groupid set</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
final int numMessages = 10;
|
|
|
|
|
|
|
|
for (int i = 0; i < numMessages; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = session0.createTextMessage("This is text message " + i);
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
message.setStringProperty(ActiveMQMessage.JMSXGROUPID, "Group-0");
|
2014-10-31 06:20:28 -04:00
|
|
|
|
|
|
|
producer0.send(message);
|
|
|
|
|
|
|
|
System.out.println("Sent messages: " + message.getText() + " to node 0");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < numMessages; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = session1.createTextMessage("This is text message " + (i + 10));
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
message.setStringProperty(ActiveMQMessage.JMSXGROUPID, "Group-0");
|
2014-10-31 06:20:28 -04:00
|
|
|
|
|
|
|
producer1.send(message);
|
|
|
|
|
|
|
|
System.out.println("Sent messages: " + message.getText() + " to node 1");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < numMessages; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = session2.createTextMessage("This is text message " + (i + 20));
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
message.setStringProperty(ActiveMQMessage.JMSXGROUPID, "Group-0");
|
2014-10-31 06:20:28 -04:00
|
|
|
|
|
|
|
producer2.send(message);
|
|
|
|
|
|
|
|
System.out.println("Sent messages: " + message.getText() + " to node 2");
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>We now consume those messages from server 0. We note the messages have all been sent to the same consumer on the same node</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
for (int i = 0; i < numMessages * 3; i++)
|
|
|
|
{
|
|
|
|
TextMessage message0 = (TextMessage)consumer.receive(5000);
|
|
|
|
|
|
|
|
System.out.println("Got message: " + message0.getText() + " from node 0");
|
|
|
|
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
<li>Finally, Be sure to close our resources!</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
if (connection0 != null)
|
|
|
|
{
|
|
|
|
connection0.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connection1 != null)
|
|
|
|
{
|
|
|
|
connection1.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connection2 != null)
|
|
|
|
{
|
|
|
|
connection2.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ic0 != null)
|
|
|
|
{
|
|
|
|
ic0.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ic1 != null)
|
|
|
|
{
|
|
|
|
ic1.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ic2 != null)
|
|
|
|
{
|
|
|
|
ic2.close();
|
|
|
|
}</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
</ol>
|
|
|
|
</body>
|
2015-01-05 07:45:36 -05:00
|
|
|
</html>
|