activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r981019 - in /websites/production/activemq/content: cache/main.pageCache jndi-support.html virtual-destinations.html
Date Tue, 23 Feb 2016 14:22:03 GMT
Author: buildbot
Date: Tue Feb 23 14:22:03 2016
New Revision: 981019

Log:
Production update by buildbot for activemq

Modified:
    websites/production/activemq/content/cache/main.pageCache
    websites/production/activemq/content/jndi-support.html
    websites/production/activemq/content/virtual-destinations.html

Modified: websites/production/activemq/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/activemq/content/jndi-support.html
==============================================================================
--- websites/production/activemq/content/jndi-support.html (original)
+++ websites/production/activemq/content/jndi-support.html Tue Feb 23 14:22:03 2016
@@ -36,8 +36,6 @@
       <link href='http://activemq.apache.org/styles/highlighter/styles/shThemeEclipse.css' rel='stylesheet' type='text/css' /> 
       <script src='http://activemq.apache.org/styles/highlighter/scripts/shCore.js' type='text/javascript'></script> 
               <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushJava.js' type='text/javascript'></script> 
-              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushXml.js' type='text/javascript'></script> 
-              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script> 
          
       <script type="text/javascript"> 
         SyntaxHighlighter.defaults['toolbar'] = false; 
@@ -83,28 +81,25 @@
   <tbody>
         <tr>
         <td valign="top" width="100%">
-<div class="wiki-content maincontent"><p>ActiveMQ will work with any JNDI provider capable of storing Java objects.</p>
+<div class="wiki-content maincontent"><p>ActiveMQ will work with any JNDI provider capable of storing Java objects.</p><p>However it is common to require a JNDI initial context to be able to run many JMS example programs, like <a shape="rect" class="external-link" href="http://java.sun.com/products/jms/tutorial/1_3_1-fcs/doc/jms_tutorialTOC.html" rel="nofollow">Sun's JMS tutorial</a></p><p>So we provide a simple JNDI InitialContextFactory which can be used to lookup JMS connection factory objects as well as Destination objects.</p><p>For example if you place this <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties">jndi.properties</a> file on your classpath, you can look inside the InitialContext and lookup ConnectionFactory objects and Destinations etc.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
 
-<p>However it is common to require a JNDI initial context to be able to run many JMS example programs, like <a shape="rect" class="external-link" href="http://java.sun.com/products/jms/tutorial/1_3_1-fcs/doc/jms_tutorialTOC.html" rel="nofollow">Sun's JMS tutorial</a></p>
+# use the following property to configure the default connector
+java.naming.provider.url = vm://localhost
 
-<p>So we provide a simple JNDI InitialContextFactory which can be used to lookup JMS connection factory objects as well as Destination objects.</p>
-
-<p>For example if you place this <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties">jndi.properties</a> file on your classpath, you can look inside the InitialContext and lookup ConnectionFactory objects and Destinations etc.</p>
-<div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div>
-
-<p>You can edit the jndi.properties file to configure the ActiveMQConnectionFactory's properties such as brokerURL and whether or not there should be an embedded broker etc. See <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.html">how to embed a broker in a connection</a> for more details.</p>
-
-<h3 id="JNDISupport-ActiveMQJNDITutorial">ActiveMQ JNDI Tutorial</h3>
-
-<p>This is a quick one page tutorial on how to setup and use JNDI to create a connection to ActiveMQ. The first thing is ActiveMQ  does not provide a full JNDI server. This means JMS clients need to use properties files to create a jndi IntialContextFactory. If you need an example properties file, you can look the source distribution <a shape="rect" class="external-link" href="http://svn.apache.org/viewvc/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties?view=markup">http://svn.apache.org/viewvc/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties?view=markup</a>. Before we proceed, here are the properties.</p>
-<div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Name </p></th><th colspan="1" rowspan="1" class="confluenceTh"><p> Value </p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p> java.naming.factory.initial </p></td><td colspan="1" rowspan="1" class="confluenceTd"><p> org.apache.activemq.jndi.ActiveMQInitialContextFactory </p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p> java.naming.provider.url </p></td><td colspan="1" rowspan="1" class="confluenceTd"><p> tcp://hostname:61616 </p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p> topic.MyTopic </p></td><td colspan="1" rowspan="1" class="confluenceTd"><p> example.MyTopic </p></td></tr></tbody></table></div>
-
-<p>Make sure to add activemq-&lt;version&gt;.jar and spring-1.x.jar to your classpath. If the libraries are not in the classpath, you will get a "ClassNotFoundException" at runtime. If you get "ClassNotFoundException", try printing out the classpath and check it is present. You can also run activeMQ with "-verbose" option to verify the jar was loaded correctly.</p>
-
-<p><strong>Sample code</strong></p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-// create a new intial context, which loads from jndi.properties file
+# use the following property to specify the JNDI name the connection factory
+# should appear as. 
+#connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry
+
+# register some queues in JNDI using the form
+# queue.[jndiName] = [physicalName]
+queue.MyQueue = example.MyQueue
+
+# register some topics in JNDI using the form
+# topic.[jndiName] = [physicalName]
+topic.MyTopic = example.MyTopic</pre>
+</div></div><p>You can edit the jndi.properties file to configure the ActiveMQConnectionFactory's properties such as brokerURL and whether or not there should be an embedded broker etc. See <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.html">how to embed a broker in a connection</a> for more details.</p><h3 id="JNDISupport-ActiveMQJNDITutorial">ActiveMQ JNDI Tutorial</h3><p>This is a quick one page tutorial on how to setup and use JNDI to create a connection to ActiveMQ. The first thing is ActiveMQ does not provide a full JNDI server. This means JMS clients need to use properties files to create a jndi IntialContextFactory. If you need an example properties file, you can look the source distribution <a shape="rect" class="external-link" href="http://svn.apache.org/viewvc/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties?view=markup">http://svn.apache.org/viewvc/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties?view=markup</
 a>. Before we proceed, here are the properties.</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Name</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>Value</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>java.naming.factory.initial</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>org.apache.activemq.jndi.ActiveMQInitialContextFactory</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>java.naming.provider.url</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>tcp://hostname:61616</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>topic.MyTopic</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>example.MyTopic</p></td></tr></tbody></table></div><p>Make sure to add activemq-&lt;version&gt;.jar and spring-1.x.jar to your classpath. If the libraries are not in the classpath, you will get a "ClassNotFoundException" at run
 time. If you get "ClassNotFoundException", try printing out the classpath and check it is present. You can also run activeMQ with "-verbose" option to verify the jar was loaded correctly.</p><p><strong>Sample code</strong></p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">// create a new intial context, which loads from jndi.properties file
 javax.naming.Context ctx = new javax.naming.InitialContext();
 // lookup the connection factory
 javax.jms.TopicConnectionFactory factory = (javax.jms.TopicConnectionFactory)ctx.lookup("ConnectionFactory");
@@ -117,63 +112,149 @@ javax.jms.TopicSession session = conn.cr
 // create a new subscriber to receive messages
 javax.jms.TopicSubscriber subscriber = session.createSubscriber(mytopic);
 </pre>
-</div></div>
-<p>Notice the name of the topic in the sample is "MyTopic". ActiveMQ will read the jndi.properties files and creates the topics and queues in a lazy fashion. The prefix topic and queue is stripped, so the jndi name begins after the prefix.</p>
-
-<p>Once you have the jndi.properties edited and ready, it needs to be accessible to your application. The easiest way is to add jndi.properties to a jar file. When "new InitialContext()" is called, it will scan the resources and find the file. If you get "javax.naming.NamingException", it usually means the jndi.properties file is not accessible.</p>
-
-<p>You can also try to create a new initial context using either an instance of properties file or a map. For example, the approach recommended by JMS specification will work just fine.</p>
-<div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Example recommended by specification </p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"> <div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-Properties props = new Properties();
+</div></div><p>Notice the name of the topic in the sample is "MyTopic". ActiveMQ will read the jndi.properties files and creates the topics and queues in a lazy fashion. The prefix topic and queue is stripped, so the jndi name begins after the prefix.</p><p>Once you have the jndi.properties edited and ready, it needs to be accessible to your application. The easiest way is to add jndi.properties to a jar file. When "new InitialContext()" is called, it will scan the resources and find the file. If you get "javax.naming.NamingException", it usually means the jndi.properties file is not accessible.</p><p>You can also try to create a new initial context using either an instance of properties file or a map. For example, the approach recommended by JMS specification will work just fine.</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Example recommended by specification</p></th></tr><tr><td colspan="1" rowspan="1" cl
 ass="confluenceTd"><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">Properties props = new Properties();
 props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
 props.setProperty(Context.PROVIDER_URL,"tcp://hostname:61616");
 javax.naming.Context ctx = new InitialContext(props);||
 </pre>
-</div></div> </td></tr></tbody></table></div>
-
-<p>If ActiveMQ is embedded within an EJB container, you will need to look at the containers documentation for the correct jndi values.</p>
-
-<h3 id="JNDISupport-Dynamicallycreatingdestinations">Dynamically creating destinations</h3>
-
-<p>For the easiest possible configuration with JNDI based programs, there are 2 dynamic contexts as follows</p>
-<ul><li>dynamicQueues</li><li>dynamicTopics</li></ul>
-
-
-<p>which allows you to lookup queues and topics using JNDI without any configuration.</p>
-
-<p>e.g. if you use the following name to lookup into JNDI</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-dynamicQueues/FOO.BAR
+</div></div></td></tr></tbody></table></div><p>If ActiveMQ is embedded within an EJB container, you will need to look at the containers documentation for the correct jndi values.</p><h3 id="JNDISupport-Dynamicallycreatingdestinations">Dynamically creating destinations</h3><p>For the easiest possible configuration with JNDI based programs, there are 2 dynamic contexts as follows</p><ul><li>dynamicQueues</li><li>dynamicTopics</li></ul><p>which allows you to lookup queues and topics using JNDI without any configuration.</p><p>e.g. if you use the following name to lookup into JNDI</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">dynamicQueues/FOO.BAR
 </pre>
-</div></div>
-<p>you will get back an ActiveMQQueue of the name "FOO.BAR".</p>
-
-<p>This can be very handy if you can easily reconfigure the JNDI name to use to lookup something in JNDI, but don't want to have to double configure a jndi.properties to matchup.</p>
-
-<h3 id="JNDISupport-Workingwithembeddedbrokers">Working with embedded brokers</h3>
-
-<p>It is often useful to use an embedded broker in the same JVM as the JMS client. For this see <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.html">How do I embed a Broker inside a Connection</a>.</p>
-
-<p>If you want to use an embedded broker with your JNDI provider you can just use the <a shape="rect" href="vm-transport-reference.html">VM Transport</a> to connect to the broker in your URL. e.g. to create a purely in JVM broker use this URI</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-vm://locahost
+</div></div><p>you will get back an ActiveMQQueue of the name "FOO.BAR".</p><p>This can be very handy if you can easily reconfigure the JNDI name to use to lookup something in JNDI, but don't want to have to double configure a jndi.properties to matchup.</p><h3 id="JNDISupport-Workingwithembeddedbrokers">Working with embedded brokers</h3><p>It is often useful to use an embedded broker in the same JVM as the JMS client. For this see <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.html">How do I embed a Broker inside a Connection</a>.</p><p>If you want to use an embedded broker with your JNDI provider you can just use the <a shape="rect" href="vm-transport-reference.html">VM Transport</a> to connect to the broker in your URL. e.g. to create a purely in JVM broker use this URI</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">vm://locahost
 </pre>
-</div></div>
-<p>If you want to customize the broker use something like this</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-vm:broker:(tcp://localhost:61616)
+</div></div><p>If you want to customize the broker use something like this</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">vm:broker:(tcp://localhost:61616)
 </pre>
-</div></div>
-<p>More options are available in the <a shape="rect" href="vm-transport-reference.html">VM Transport Reference</a></p>
-
-<h3 id="JNDISupport-ExampleJavacode">Example Java code</h3>
-
-<p>Once you have configured JNDI on the classpath you can run any normal JMS application such as the following <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/java/org/apache/activemq/demo/SimpleProducer.java">example</a>. Notice that the Java code just uses pure JMS APIs and is not in any way ActiveMQ specific</p>
-<div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div></div>
+</div></div><p>More options are available in the <a shape="rect" href="vm-transport-reference.html">VM Transport Reference</a></p><h3 id="JNDISupport-ExampleJavacode">Example Java code</h3><p>Once you have configured JNDI on the classpath you can run any normal JMS application such as the following <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/java/org/apache/activemq/demo/SimpleProducer.java">example</a>. Notice that the Java code just uses pure JMS APIs and is not in any way ActiveMQ specific</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">/**
+ * 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.
+ */
+/**
+ * The SimpleQueueSender class consists only of a main method,
+ * which sends several messages to a queue.
+ *
+ * Run this program in conjunction with SimpleQueueReceiver.
+ * Specify a queue name on the command line when you run the
+ * program.  By default, the program sends one message.  Specify
+ * a number after the queue name to send that number of messages.
+ */
+package org.apache.activemq.demo;
+// START SNIPPET: demo
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * A simple polymorphic JMS producer which can work with Queues or Topics which
+ * uses JNDI to lookup the JMS connection factory and destination
+ * 
+ * 
+ */
+public final class SimpleProducer {
+    private static final Logger LOG = LoggerFactory.getLogger(SimpleProducer.class);
+    private SimpleProducer() {
+    }
+    /**
+     * @param args the destination name to send to and optionally, the number of
+     *                messages to send
+     */
+    public static void main(String[] args) {
+        Context jndiContext = null;
+        ConnectionFactory connectionFactory = null;
+        Connection connection = null;
+        Session session = null;
+        Destination destination = null;
+        MessageProducer producer = null;
+        String destinationName = null;
+        final int numMsgs;
+        if ((args.length &lt; 1) || (args.length &gt; 2)) {
+            LOG.info("Usage: java SimpleProducer &lt;destination-name&gt; [&lt;number-of-messages&gt;]");
+            System.exit(1);
+        }
+        destinationName = args[0];
+        LOG.info("Destination name is " + destinationName);
+        if (args.length == 2) {
+            numMsgs = (new Integer(args[1])).intValue();
+        } else {
+            numMsgs = 1;
+        }
+        /*
+         * Create a JNDI API InitialContext object
+         */
+        try {
+            jndiContext = new InitialContext();
+        } catch (NamingException e) {
+            LOG.info("Could not create JNDI API context: " + e.toString());
+            System.exit(1);
+        }
+        /*
+         * Look up connection factory and destination.
+         */
+        try {
+            connectionFactory = (ConnectionFactory)jndiContext.lookup("ConnectionFactory");
+            destination = (Destination)jndiContext.lookup(destinationName);
+        } catch (NamingException e) {
+            LOG.info("JNDI API lookup failed: " + e);
+            System.exit(1);
+        }
+        /*
+         * Create connection. Create session from connection; false means
+         * session is not transacted. Create sender and text message. Send
+         * messages, varying text slightly. Send end-of-messages message.
+         * Finally, close connection.
+         */
+        try {
+            connection = connectionFactory.createConnection();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            producer = session.createProducer(destination);
+            TextMessage message = session.createTextMessage();
+            for (int i = 0; i &lt; numMsgs; i++) {
+                message.setText("This is message " + (i + 1));
+                LOG.info("Sending message: " + message.getText());
+                producer.send(message);
+            }
+            /*
+             * Send a non-text control message indicating end of messages.
+             */
+            producer.send(session.createMessage());
+        } catch (JMSException e) {
+            LOG.info("Exception occurred: " + e);
+        } finally {
+            if (connection != null) {
+                try {
+                    connection.close();
+                } catch (JMSException e) {
+                }
+            }
+        }
+    }
+}
+// END SNIPPET: demo
+</pre>
+</div></div></div>
         </td>
         <td valign="top">
           <div class="navigation">

Modified: websites/production/activemq/content/virtual-destinations.html
==============================================================================
--- websites/production/activemq/content/virtual-destinations.html (original)
+++ websites/production/activemq/content/virtual-destinations.html Tue Feb 23 14:22:03 2016
@@ -35,9 +35,7 @@
           <link href='http://activemq.apache.org/styles/highlighter/styles/shCore.css' rel='stylesheet' type='text/css' /> 
       <link href='http://activemq.apache.org/styles/highlighter/styles/shThemeEclipse.css' rel='stylesheet' type='text/css' /> 
       <script src='http://activemq.apache.org/styles/highlighter/scripts/shCore.js' type='text/javascript'></script> 
-              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushJava.js' type='text/javascript'></script> 
               <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushXml.js' type='text/javascript'></script> 
-              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script> 
          
       <script type="text/javascript"> 
         SyntaxHighlighter.defaults['toolbar'] = false; 
@@ -83,13 +81,47 @@
   <tbody>
         <tr>
         <td valign="top" width="100%">
-<div class="wiki-content maincontent"><p><em>Virtual Destinations</em> allow us to create logical destinations that clients can use to produce and consume from but which map onto one or more <em>physical destinations</em>. It allows us to provide more flexible loosely coupled messaging configurations.</p><h2 id="VirtualDestinations-VirtualTopics">Virtual Topics</h2><p>The idea behind <em>publish subscribe</em> is a great one. Allow producers to be decoupled from consumers so that they do not even know how many consumers are interested in the messages they publish. The JMS specification defines support for durable topics however they have limitations as we will describe...</p><h3 id="VirtualDestinations-ThelimitationsofJMSdurabletopics">The limitations of JMS durable topics</h3><p>A JMS durable subscriber MessageConsumer is created with a unique JMS clientID and durable subscriber name. To be JMS compliant only one JMS connection can be active at any point in time for one JMS clientI
 D, and only one consumer can be active for a clientID and subscriber name. i.e., only <strong>one</strong> thread can be actively consuming from a given logical topic subscriber. This means we cannot implement</p><ul><li>load balancing of messages.</li><li>fast failover of the subscriber if that one process running that one consumer thread dies.</li></ul><p>Now <em>queue</em> semantics in JMS offer the ability to load balance work across a number of consumers in a reliable way - allowing many threads, processes and machines to be used to process messages. Then we have sophisticated sticky load balancing techniques like <a shape="rect" href="message-groups.html">Message Groups</a> to load balance and parallelise work while maintaining ordering.</p><p>Another added benefit of having physical queues for each logical topic subscriber is we can them monitor the queue depths via <a shape="rect" href="jmx.html">JMX</a> to monitor system performance together with being able to browse these 
 physical queues.</p><h3 id="VirtualDestinations-VirtualTopicstotherescue">Virtual Topics to the rescue</h3><p>The idea behind virtual topics is that producers send to a topic in the usual JMS way. Consumers can continue to use the Topic semantics in the JMS specification. However if the topic is virtual, consumer can consume from a physical queue for a logical topic subscription, allowing many consumers to be running on many machines &amp; threads to load balance the load.</p><p>E.g., let's say we have a topic called <strong>VirtualTopic.Orders</strong>. (Where the prefix VirtualTopic. indicates its a virtual topic). And we logically want to send orders to systems A and B. Now with regular durable topics we'd create a JMS consumer for clientID_A and "A" along with clientID_B and "B".</p><p>With virtual topics we can just go right ahead and consume to queue <strong>Consumer.A.VirtualTopic.Orders</strong> to be a consumer for system A or consume to <strong>Consumer.B.VirtualTopic.Orde
 rs</strong> to be a consumer for system B.</p><p>We can now have a pool of consumers for each system which then compete for messages for systems A or B such that all the messages for system A are processed exactly once and similarly for system B.</p><h3 id="VirtualDestinations-Customizingtheout-of-the-boxdefaults">Customizing the out-of-the-box defaults</h3><p>The out-of-the-box defaults are described above. Namely that the only virtual topics available must be within the <strong>VirtualTopic.&gt;</strong> namespace and that the consumer queues are named <strong>Consumer.*.VirtualTopic.&gt;</strong>.</p><p>You can configure this to use whatever naming convention you wish. The following <a shape="rect" class="external-link" href="https://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/resources/org/apache/activemq/broker/virtual/global-virtual-topics.xml">example</a> shows how to make all topics virtual topics. The example below is using the name <stron
 g>&gt;</strong> to indicate 'match all topics'. You could use this wildcard to apply different virtual topic policies in different hierarchies.</p><div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div>Note that making a topic virtual does add a small CPU overhead when sending messages to the topic but it is fairly small.<div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh">Option</th><th colspan="1" rowspan="1" class="confluenceTh">Default</th><th colspan="1" rowspan="1" class="confluenceTh">Description</th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">selectorAware</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">only messages that match one of the existing subscribers are actually dispatched. Using this option prevents the build up of unmatched messages when se
 lectors are used by exclusive consumers</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">local</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, don't fan out messages that were received over a network</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">concurrentSend</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, use an executor to fanout such that sends occur in parallel. This allows the journal to batch writes which will reduce disk io (5.12)</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">transactedSend</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, use a transaction for fanout sends such that there is a single disk sync. A local broker transaction will be created if there is no client transaction (5.13)</td></tr></tbody>
 </table></div><p>&#160;</p><h2 id="VirtualDestinations-CompositeDestinations">Composite Destinations</h2><p>Composite Destinations allow for one-to-many relationships on individual destinations; the main use case is for <em>composite queues</em>. For example when a message is sent to queue A you may want to forward it also to queues B and C and topic D. Composite destinations are then a mapping from a virtual destination to a collection of other physical destinations. In this case the mapping is broker side and the client is unaware of the mapping between the destinations. This is different from client side <a shape="rect" href="composite-destinations.html">Composite Destinations</a> where the client uses a URL notation to specify the actual physical destinations that a message must be sent to.</p><p>The following <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/resources/org/apache/activemq/broker/virt
 ual/composite-queue.xml">example</a> shows how to set up a <strong>&lt;compositeQueue/&gt;</strong> element in the XML configuration so that when a message is sent to <code>MY.QUEUE</code> then it is really forwarded to the physical queue <code>FOO</code> and the topic <code>BAR</code>.</p><div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div>By default, subscribers cannot consume messages directly from a composite queue or topic - it is a logical construct only. Given the configuration above, subscribers can only consume messages from <code>FOO</code> and <code>BAR</code>; but not <code>MY.QUEUE</code>.<p>This behaviour can be altered to implement use cases such as watching a queue by sending the same messages to a notification topic (wire tapping), by setting the optionally set <code>forwardOnly</code> attribute to false.</p><div class="code panel pdl" style="border-width: 1px;"><div class="cod
 eContent panelContent pdl">
+<div class="wiki-content maincontent"><p><em>Virtual Destinations</em> allow us to create logical destinations that clients can use to produce and consume from but which map onto one or more <em>physical destinations</em>. It allows us to provide more flexible loosely coupled messaging configurations.</p><h2 id="VirtualDestinations-VirtualTopics">Virtual Topics</h2><p>The idea behind <em>publish subscribe</em> is a great one. Allow producers to be decoupled from consumers so that they do not even know how many consumers are interested in the messages they publish. The JMS specification defines support for durable topics however they have limitations as we will describe...</p><h3 id="VirtualDestinations-ThelimitationsofJMSdurabletopics">The limitations of JMS durable topics</h3><p>A JMS durable subscriber MessageConsumer is created with a unique JMS clientID and durable subscriber name. To be JMS compliant only one JMS connection can be active at any point in time for one JMS clientI
 D, and only one consumer can be active for a clientID and subscriber name. i.e., only <strong>one</strong> thread can be actively consuming from a given logical topic subscriber. This means we cannot implement</p><ul><li>load balancing of messages.</li><li>fast failover of the subscriber if that one process running that one consumer thread dies.</li></ul><p>Now <em>queue</em> semantics in JMS offer the ability to load balance work across a number of consumers in a reliable way - allowing many threads, processes and machines to be used to process messages. Then we have sophisticated sticky load balancing techniques like <a shape="rect" href="message-groups.html">Message Groups</a> to load balance and parallelise work while maintaining ordering.</p><p>Another added benefit of having physical queues for each logical topic subscriber is we can them monitor the queue depths via <a shape="rect" href="jmx.html">JMX</a> to monitor system performance together with being able to browse these 
 physical queues.</p><h3 id="VirtualDestinations-VirtualTopicstotherescue">Virtual Topics to the rescue</h3><p>The idea behind virtual topics is that producers send to a topic in the usual JMS way. Consumers can continue to use the Topic semantics in the JMS specification. However if the topic is virtual, consumer can consume from a physical queue for a logical topic subscription, allowing many consumers to be running on many machines &amp; threads to load balance the load.</p><p>E.g., let's say we have a topic called <strong>VirtualTopic.Orders</strong>. (Where the prefix VirtualTopic. indicates its a virtual topic). And we logically want to send orders to systems A and B. Now with regular durable topics we'd create a JMS consumer for clientID_A and "A" along with clientID_B and "B".</p><p>With virtual topics we can just go right ahead and consume to queue <strong>Consumer.A.VirtualTopic.Orders</strong> to be a consumer for system A or consume to <strong>Consumer.B.VirtualTopic.Orde
 rs</strong> to be a consumer for system B.</p><p>We can now have a pool of consumers for each system which then compete for messages for systems A or B such that all the messages for system A are processed exactly once and similarly for system B.</p><h3 id="VirtualDestinations-Customizingtheout-of-the-boxdefaults">Customizing the out-of-the-box defaults</h3><p>The out-of-the-box defaults are described above. Namely that the only virtual topics available must be within the <strong>VirtualTopic.&gt;</strong> namespace and that the consumer queues are named <strong>Consumer.*.VirtualTopic.&gt;</strong>.</p><p>You can configure this to use whatever naming convention you wish. The following <a shape="rect" class="external-link" href="https://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/resources/org/apache/activemq/broker/virtual/global-virtual-topics.xml">example</a> shows how to make all topics virtual topics. The example below is using the name <stron
 g>&gt;</strong> to indicate 'match all topics'. You could use this wildcard to apply different virtual topic policies in different hierarchies.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationInterceptors&gt;
+  &lt;virtualDestinationInterceptor&gt;
+	&lt;virtualDestinations&gt;
+	  &lt;virtualTopic name="&gt;" prefix="VirtualTopicConsumers.*." selectorAware="false"/&gt;
+	&lt;/virtualDestinations&gt;
+  &lt;/virtualDestinationInterceptor&gt;
+&lt;/destinationInterceptors&gt;</pre>
+</div></div><p>Note that making a topic virtual does add a small CPU overhead when sending messages to the topic but it is fairly small.</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh">Option</th><th colspan="1" rowspan="1" class="confluenceTh">Default</th><th colspan="1" rowspan="1" class="confluenceTh">Description</th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">selectorAware</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">only messages that match one of the existing subscribers are actually dispatched. Using this option prevents the build up of unmatched messages when selectors are used by exclusive consumers</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">local</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, don't fan out messages that were receiv
 ed over a network</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">concurrentSend</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, use an executor to fanout such that sends occur in parallel. This allows the journal to batch writes which will reduce disk io (5.12)</td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd">transactedSend</td><td colspan="1" rowspan="1" class="confluenceTd">false</td><td colspan="1" rowspan="1" class="confluenceTd">when true, use a transaction for fanout sends such that there is a single disk sync. A local broker transaction will be created if there is no client transaction (5.13)</td></tr></tbody></table></div><p>&#160;</p><h2 id="VirtualDestinations-CompositeDestinations">Composite Destinations</h2><p>Composite Destinations allow for one-to-many relationships on individual destinations; the main use case is for <em>composite queues</em>. For example when a mess
 age is sent to queue A you may want to forward it also to queues B and C and topic D. Composite destinations are then a mapping from a virtual destination to a collection of other physical destinations. In this case the mapping is broker side and the client is unaware of the mapping between the destinations. This is different from client side <a shape="rect" href="composite-destinations.html">Composite Destinations</a> where the client uses a URL notation to specify the actual physical destinations that a message must be sent to.</p><p>The following <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/resources/org/apache/activemq/broker/virtual/composite-queue.xml">example</a> shows how to set up a <strong>&lt;compositeQueue/&gt;</strong> element in the XML configuration so that when a message is sent to <code>MY.QUEUE</code> then it is really forwarded to the physical queue <code>FOO</code> and the topic 
 <code>BAR</code>.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationInterceptors&gt;
+  &lt;virtualDestinationInterceptor&gt;
+	&lt;virtualDestinations&gt;
+	  &lt;compositeQueue name="MY.QUEUE"&gt;
+		&lt;forwardTo&gt;
+		  &lt;queue physicalName="FOO" /&gt;
+		  &lt;topic physicalName="BAR" /&gt;
+		&lt;/forwardTo&gt;
+	  &lt;/compositeQueue&gt;
+	&lt;/virtualDestinations&gt;
+  &lt;/virtualDestinationInterceptor&gt;
+&lt;/destinationInterceptors&gt;</pre>
+</div></div><p>By default, subscribers cannot consume messages directly from a composite queue or topic - it is a logical construct only. Given the configuration above, subscribers can only consume messages from <code>FOO</code> and <code>BAR</code>; but not <code>MY.QUEUE</code>.</p><p>This behaviour can be altered to implement use cases such as watching a queue by sending the same messages to a notification topic (wire tapping), by setting the optionally set <code>forwardOnly</code> attribute to false.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;compositeQueue name="IncomingOrders" forwardOnly="false"&gt;
     &lt;forwardTo&gt;
         &lt;topic physicalName="Notifications" /&gt;
     &lt;/forwardTo&gt;
 &lt;/compositeQueue&gt;</pre>
-</div></div><p>Messages sent to <code>IncomingOrders</code> will all be copied and forwarded to <code>Notifications</code>, before being placed on the physical <code>IncomingOrders</code> queue for consumption by subscribers.</p><p>Where the <code>forwardOnly</code> attribute is not defined or is set to <code>true</code>, there is no logical difference between a <code>compositeQueue</code> and a <code>compositeTopic</code> - they can be used interchangeably. It is only when a composite destination is made physical through the use of <code>forwardOnly</code> that the choice of <code>compositeTopic</code>/<code>compositeQueue</code> has an impact on behavior.</p><h3 id="VirtualDestinations-Usingfiltereddestinations">Using filtered destinations</h3><p>From Apache ActiveMQ <strong>4.2</strong> onwards you can now use selectors to define virtual destinations.</p><p>You may wish to create a virtual destination which forwards messages to multiple destinations but applying a selector first 
 to decide if the message really does have to go to a particular destination.</p><p>The following example shows how a message sent to the virtual destination <strong>MY.QUEUE</strong> will be forwarded to <strong>FOO</strong> and <strong>BAR</strong> if the selectors match</p><div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div><h2 id="VirtualDestinations-AvoidingDuplicateMessageinaNetworkofBrokers">Avoiding Duplicate Message in a Network of Brokers</h2><p>You have to make sure that the messages sent to the <strong>Consumer.*.VirtualTopic.&gt;</strong> destination are not forwarded when you're using both queue-based and non-queue based subscribers to the virtual topic (that is, if you have normal topic subscribers to the virtual topic). If you use Virtual Topics in a network of brokers, it is likely you will get duplicate messages if you use the default network configuration. This is because a ne
 twork node will not only forward message sent to the virtual topic, but also the associated physical queues. To fix this, you should disable forwarding messages on the associated physical queues.</p><p>Here is an example of how to do that:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Messages sent to <code>IncomingOrders</code> will all be copied and forwarded to <code>Notifications</code>, before being placed on the physical <code>IncomingOrders</code> queue for consumption by subscribers.</p><p>Where the <code>forwardOnly</code> attribute is not defined or is set to <code>true</code>, there is no logical difference between a <code>compositeQueue</code> and a <code>compositeTopic</code> - they can be used interchangeably. It is only when a composite destination is made physical through the use of <code>forwardOnly</code> that the choice of <code>compositeTopic</code>/<code>compositeQueue</code> has an impact on behavior.</p><h3 id="VirtualDestinations-Usingfiltereddestinations">Using filtered destinations</h3><p>From Apache ActiveMQ <strong>4.2</strong> onwards you can now use selectors to define virtual destinations.</p><p>You may wish to create a virtual destination which forwards messages to multiple destinations but applying a selector first 
 to decide if the message really does have to go to a particular destination.</p><p>The following example shows how a message sent to the virtual destination <strong>MY.QUEUE</strong> will be forwarded to <strong>FOO</strong> and <strong>BAR</strong> if the selectors match</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationInterceptors&gt;
+  &lt;virtualDestinationInterceptor&gt;
+	&lt;virtualDestinations&gt;
+	  &lt;compositeQueue name="MY.QUEUE"&gt;
+		&lt;forwardTo&gt;
+		  &lt;filteredDestination selector="odd = 'yes'" queue="FOO"/&gt;
+		  &lt;filteredDestination selector="i = 5" topic="BAR"/&gt;
+		&lt;/forwardTo&gt;
+	  &lt;/compositeQueue&gt;
+	&lt;/virtualDestinations&gt;
+  &lt;/virtualDestinationInterceptor&gt;
+&lt;/destinationInterceptors&gt;</pre>
+</div></div><h2 id="VirtualDestinations-AvoidingDuplicateMessageinaNetworkofBrokers">Avoiding Duplicate Message in a Network of Brokers</h2><p>You have to make sure that the messages sent to the <strong>Consumer.*.VirtualTopic.&gt;</strong> destination are not forwarded when you're using both queue-based and non-queue based subscribers to the virtual topic (that is, if you have normal topic subscribers to the virtual topic). If you use Virtual Topics in a network of brokers, it is likely you will get duplicate messages if you use the default network configuration. This is because a network node will not only forward message sent to the virtual topic, but also the associated physical queues. To fix this, you should disable forwarding messages on the associated physical queues.</p><p>Here is an example of how to do that:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">    &lt;networkConnectors&gt;
       &lt;networkConnector uri="static://(tcp://localhost:61617)"&gt;
       	&lt;excludedDestinations&gt;




Mime
View raw message