http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/interoperability.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/interoperability.xml b/docs/user-manual/en/interoperability.xml deleted file mode 100644 index f3f3bdd..0000000 --- a/docs/user-manual/en/interoperability.xml +++ /dev/null @@ -1,305 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="interoperability"> - <title>Interoperability</title> - <section id="stomp"> - <title>Stomp</title> - <para><ulink url="http://stomp.github.com/">Stomp</ulink> is a text-orientated wire protocol that allows - Stomp clients to communicate with Stomp Brokers. ActiveMQ now supports Stomp 1.0, 1.1 and 1.2.</para> - <para>Stomp clients are available for - several languages and platforms making it a good choice for interoperability.</para> - <section id="stomp.native"> - <title>Native Stomp support</title> - <para>ActiveMQ provides native support for Stomp. To be able to send and receive Stomp messages, - you must configure a <literal>NettyAcceptor</literal> with a <literal>protocols</literal> - parameter set to have <literal>stomp</literal>:</para> -<programlisting> -<acceptor name="stomp-acceptor"> - <factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> - <param key="protocols" value="STOMP"/> - <param key="port" value="61613"/> -</acceptor></programlisting> - <para>With this configuration, ActiveMQ will accept Stomp connections on - the port <literal>61613</literal> (which is the default port of the Stomp brokers).</para> - <para>See the <literal>stomp</literal> example which shows how to configure a ActiveMQ server with Stomp.</para> - <section> - <title>Limitations</title> - <para>Message acknowledgements are not transactional. The ACK frame can not be part of a transaction - (it will be ignored if its <literal>transaction</literal> header is set).</para> - </section> - <section> - <title>Stomp 1.1/1.2 Notes</title> - <section> - <title>Virtual Hosting</title> - <para>ActiveMQ currently doesn't support virtual hosting, which means the 'host' header - in CONNECT fram will be ignored.</para> - </section> - <section> - <title>Heart-beating</title> - <para>ActiveMQ specifies a minimum value for both client and server heart-beat intervals. - The minimum interval for both client and server heartbeats is 500 milliseconds. That means if - a client sends a CONNECT frame with heartbeat values lower than 500, the server will defaults - the value to 500 milliseconds regardless the values of the 'heart-beat' header in the frame.</para> - </section> - </section> - </section> - - <section> - <title>Mapping Stomp destinations to ActiveMQ addresses and queues</title> - <para>Stomp clients deals with <emphasis>destinations</emphasis> when sending messages and subscribing. - Destination names are simply strings which are mapped to some form of destination on the - server - how the server translates these is left to the server implementation.</para> - <para>In ActiveMQ, these destinations are mapped to <emphasis>addresses</emphasis> and <emphasis>queues</emphasis>. - When a Stomp client sends a message (using a <literal>SEND</literal> frame), the specified destination is mapped - to an address. - When a Stomp client subscribes (or unsubscribes) for a destination (using a <literal>SUBSCRIBE</literal> - or <literal>UNSUBSCRIBE</literal> frame), the destination is mapped to a ActiveMQ queue.</para> - </section> - <section> - <title>STOMP and connection-ttl</title> - <para>Well behaved STOMP clients will always send a DISCONNECT frame before closing their connections. In this case the server - will clear up any server side resources such as sessions and consumers synchronously. However if STOMP clients exit without - sending a DISCONNECT frame or if they crash the server will have no way of knowing immediately whether the client is still alive - or not. STOMP connections therefore default to a connection-ttl value of 1 minute (see chapter on <link linkend="connection-ttl" - >connection-ttl</link> for more information. This value can be overridden using connection-ttl-override. - </para> - <para>If you need a specific connection-ttl for your stomp connections without affecting the connection-ttl-override setting, you - can configure your stomp acceptor with the "connection-ttl" property, which is used to set the ttl for connections that are - created from that acceptor. For example: - </para> -<programlisting> -<acceptor name="stomp-acceptor"> - <factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> - <param key="protocols" value="STOMP"/> - <param key="port" value="61613"/> - <param key="connection-ttl" value="20000"/> -</acceptor></programlisting> - <para>The above configuration will make sure that any stomp connection that is created from that acceptor will have its - connection-ttl set to 20 seconds.</para> - - <note><para>Please note that the STOMP protocol version 1.0 does not contain any heartbeat frame. It is therefore the user's - responsibility to make sure data is sent within connection-ttl or the server will assume the client is dead and clean up server - side resources. With <literal>Stomp 1.1</literal> users can use heart-beats to maintain the life cycle of stomp - connections.</para></note> - </section> - - <section> - <title>Stomp and JMS interoperability</title> - <section> - <title>Using JMS destinations</title> - <para>As explained in <xref linkend="jms-core-mapping" />, JMS destinations are also mapped to ActiveMQ addresses and queues. - If you want to use Stomp to send messages to JMS destinations, the Stomp destinations must follow the same convention:</para> - <itemizedlist> - <listitem> - <para>send or subscribe to a JMS <emphasis>Queue</emphasis> by prepending the queue name by <literal>jms.queue.</literal>.</para> - <para>For example, to send a message to the <literal>orders</literal> JMS Queue, the Stomp client must send the frame:</para> - <programlisting> -SEND -destination:jms.queue.orders - -hello queue orders -^@</programlisting> - </listitem> - <listitem> - <para>send or subscribe to a JMS <emphasis>Topic</emphasis> by prepending the topic name by <literal>jms.topic.</literal>.</para> - <para>For example to subscribe to the <literal>stocks</literal> JMS Topic, the Stomp client must send the frame:</para> - <programlisting> -SUBSCRIBE -destination:jms.topic.stocks - -^@</programlisting> - </listitem> - </itemizedlist> - </section> - - <section> - <title>Sending and consuming Stomp message from JMS or ActiveMQ Core API</title> - <para>Stomp is mainly a text-orientated protocol. To make it simpler to interoperate with JMS and ActiveMQ Core API, - our Stomp implementation checks for presence of the <literal>content-length</literal> header to decide how to map a Stomp message - to a JMS Message or a Core message. - </para> - <para>If the Stomp message does <emphasis>not</emphasis> have a <literal>content-length</literal> header, it will be mapped to a JMS <emphasis>TextMessage</emphasis> - or a Core message with a <emphasis>single nullable SimpleString in the body buffer</emphasis>.</para> - <para>Alternatively, if the Stomp message <emphasis>has</emphasis> a <literal>content-length</literal> header, - it will be mapped to a JMS <emphasis>BytesMessage</emphasis> - or a Core message with a <emphasis>byte[] in the body buffer</emphasis>.</para> - <para>The same logic applies when mapping a JMS message or a Core message to Stomp. A Stomp client can check the presence - of the <literal>content-length</literal> header to determine the type of the message body (String or bytes).</para> - </section> - <section> - <title>Message IDs for Stomp messages</title> - <para>When receiving Stomp messages via a JMS consumer or a QueueBrowser, the messages have - no properties like JMSMessageID by default. However this may bring some inconvenience to - clients who wants an ID for their purpose. ActiveMQ Stomp provides a parameter to enable - message ID on each incoming Stomp message. If you want each Stomp message to have a unique ID, - just set the <literal>stomp-enable-message-id</literal> to true. For example:</para> -<programlisting> -<acceptor name="stomp-acceptor"> - <factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> - <param key="protocols" value="STOMP"/> - <param key="port" value="61613"/> - <param key="stomp-enable-message-id" value="true"/> -</acceptor></programlisting> - <para>When the server starts with the above setting, each stomp message sent through this - acceptor will have an extra property added. The property key is <literal> - hq-message-id</literal> and the value is a String representation of a long type internal - message id prefixed with "<literal>STOMP</literal>", like: -<programlisting> -hq-message-id : STOMP12345</programlisting> - If <literal>stomp-enable-message-id</literal> is not specified in the configuration, default - is <literal>false</literal>. </para> - </section> - <section> - <title>Handling of Large Messages with Stomp</title> - <para>Stomp clients may send very large bodys of frames which can exceed the size of ActiveMQ - server's internal buffer, causing unexpected errors. To prevent this situation from happening, - ActiveMQ provides a stomp configuration attribute <literal>stomp-min-large-message-size</literal>. - This attribute can be configured inside a stomp acceptor, as a parameter. For example: </para> -<programlisting> - <acceptor name="stomp-acceptor"> - <factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> - <param key="protocols" value="STOMP"/> - <param key="port" value="61613"/> - <param key="stomp-min-large-message-size" value="10240"/> -</acceptor></programlisting> - <para>The type of this attribute is integer. When this attributed is configured, ActiveMQ server - will check the size of the body of each Stomp frame arrived from connections established with - this acceptor. If the size of the body is equal or greater than the value of - <literal>stomp-min-large-message</literal>, the message will be persisted as a large message. - When a large message is delievered to a stomp consumer, the HorentQ server will automatically - handle the conversion from a large message to a normal message, before sending it to the client.</para> - <para>If a large message is compressed, the server will uncompressed it before sending it to - stomp clients. The default value of <literal>stomp-min-large-message-size</literal> is the same - as the default value of <link linkend="large-messages.core.config">min-large-message-size</link>.</para> - </section> - </section> - - <section id="stomp.websockets"> - <title>Stomp Over Web Sockets</title> - <para>ActiveMQ also support Stomp over <ulink url="http://dev.w3.org/html5/websockets/">Web Sockets</ulink>. Modern web browser which support Web Sockets can send and receive - Stomp messages from ActiveMQ.</para> - <para>To enable Stomp over Web Sockets, you must configure a <literal>NettyAcceptor</literal> with a <literal>protocol</literal> - parameter set to <literal>stomp_ws</literal>:</para> - <programlisting> -<acceptor name="stomp-ws-acceptor"> - <factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> - <param key="protocols" value="STOMP_WS"/> - <param key="port" value="61614"/> -</acceptor></programlisting> - <para>With this configuration, ActiveMQ will accept Stomp connections over Web Sockets on - the port <literal>61614</literal> with the URL path <literal>/stomp</literal>. - Web browser can then connect to <literal>ws://<server>:61614/stomp</literal> using a Web Socket to send and receive Stomp - messages.</para> - <para>A companion JavaScript library to ease client-side development is available from - <ulink url="http://github.com/jmesnil/stomp-websocket">GitHub</ulink> (please see - its <ulink url="http://jmesnil.net/stomp-websocket/doc/">documentation</ulink> for a complete description).</para> - <para>The <literal>stomp-websockets</literal> example shows how to configure ActiveMQ server to have web browsers and Java - applications exchanges messages on a JMS topic.</para> - </section> - - <section id="stompconnect"> - <title>StompConnect</title> - <para><ulink url="http://stomp.codehaus.org/StompConnect">StompConnect</ulink> is a server that - can act as a Stomp broker and proxy the Stomp protocol to the standard JMS API. - Consequently, using StompConnect it is possible to turn ActiveMQ into a Stomp Broker and - use any of the available stomp clients. These include clients written in C, C++, c# and - .net etc.</para> - <para>To run StompConnect first start the ActiveMQ server and make sure that it is using - JNDI.</para> - <para>Stomp requires the file <literal>jndi.properties</literal> to be available on the - classpath. This should look something like:</para> - <programlisting> -java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory</programlisting> - <para>Configure any required JNDI resources in this file according to the documentation.</para> - <para>Make sure this file is in the classpath along with the StompConnect jar and the - ActiveMQ jars and simply run <literal>java org.codehaus.stomp.jms.Main</literal>.</para> - </section> - - </section> - <section> - <title>REST</title> - <para>Please see <xref linkend="rest"/></para> - </section> - <section> - <title>AMQP</title> - <para>ActiveMQ supports the <ulink url="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=amqp">AMQP 1.0</ulink> - specification. To enable AMQP you must configure a Netty Acceptor to receive AMQP clients, like so:</para> - <programlisting> -<acceptor name="stomp-acceptor"> -<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> -<param key="protocols" value="AMQP"/> -<param key="port" value="5672"/> -</acceptor> - </programlisting> - <para>ActiveMQ will then accept AMQP 1.0 clients on port 5672 which is the default AMQP port.</para> - <para>There are 2 Stomp examples available see proton-j and proton-ruby which use the qpid Java and Ruby clients - respectively</para> - <section> - <title>AMQP and security</title> - <para>The ActiveMQ Server accepts AMQP SASL Authentication and will use this to map onto the underlying session created - for the connection so you can use the normal ActiveMQ security configuration.</para> - </section> - <section> - <title>AMQP Links</title> - <para>An AMQP Link is a uni directional transport for messages between a source and a target, i.e. a client and the - ActiveMQ Broker. A link will have an endpoint of which there are 2 kinds, a Sender and A Receiver. At the Broker a - Sender will have its messages converted into a ActiveMQ Message and forwarded to its destination or target. A - Receiver will map onto a ActiveMQ Server Consumer and convert ActiveMQ messages back into AMQP messages before being delivered.</para> - </section> - <section> - <title>AMQP and destinations</title> - <para>If an AMQP Link is dynamic then a temporary queue will be created and either the remote source or remote - target address will be set to the name of the temporary queue. If the Link is not dynamic then the the address - of the remote target or source will used for the queue. If this does not exist then an exception will be sent</para> - <note><para>For the next version we will add a flag to aut create durable queue but for now you will have to add them via - the configuration</para></note> - </section> - <section> - <title>AMQP and Coordinations - Handling Transactions</title> - <para>An AMQP links target can also be a Coordinator, the Coordinator is used to handle transactions. If a - coordinator is used the the underlying HormetQ Server session will be transacted and will be either rolled back - or committed via the coordinator.</para> - <note><para>AMQP allows the use of multiple transactions per session, <literal>amqp:multi-txns-per-ssn</literal>, - however in this version ActiveMQ will only support single transactions per session</para></note> - </section> - </section> - <section> - <title>OpenWire</title> - <para>ActiveMQ now supports the <ulink url="http://activemq.apache.org/openwire.html">OpenWire</ulink> - protocol so that an ActiveMQ JMS client can talk directly to a ActiveMQ server. To enable OpenWire support - you must configure a Netty Acceptor, like so:</para> - <programlisting> -<acceptor name="openwire-acceptor"> -<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> -<param key="protocols" value="OPENWIRE"/> -<param key="port" value="61616"/> -</acceptor> - </programlisting> - <para>The ActiveMQ server will then listens on port 61616 for incoming openwire commands. Please note the "protocols" is not mandatory here. - The openwire configuration conforms to ActiveMQ's "Single Port" feature. Please refer to - <link linkend="configuring-transports.single-port">Configuring Single Port</link> for details.</para> - <para>Please refer to the openwire example for more coding details.</para> - <para>Currently we support ActiveMQ clients that using standard JMS APIs. In the future we will get more supports - for some advanced, ActiveMQ specific features into ActiveMQ.</para> - </section> -</chapter>
http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/jms-bridge.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/jms-bridge.md b/docs/user-manual/en/jms-bridge.md new file mode 100644 index 0000000..437a177 --- /dev/null +++ b/docs/user-manual/en/jms-bridge.md @@ -0,0 +1,460 @@ +The JMS Bridge +============== + +ActiveMQ includes a fully functional JMS message bridge. + +The function of the bridge is to consume messages from a source queue or +topic, and send them to a target queue or topic, typically on a +different server. + +The source and target servers do not have to be in the same cluster +which makes bridging suitable for reliably sending messages from one +cluster to another, for instance across a WAN, and where the connection +may be unreliable. + +A bridge can be deployed as a standalone application, with ActiveMQ +standalone server or inside a JBoss AS instance. The source and the +target can be located in the same virtual machine or another one. + +The bridge can also be used to bridge messages from other non ActiveMQ +JMS servers, as long as they are JMS 1.1 compliant. + +> **Note** +> +> Do not confuse a JMS bridge with a core bridge. A JMS bridge can be +> used to bridge any two JMS 1.1 compliant JMS providers and uses the +> JMS API. A core bridge (described in ?) is used to bridge any two +> ActiveMQ instances and uses the core API. Always use a core bridge if +> you can in preference to a JMS bridge. The core bridge will typically +> provide better performance than a JMS bridge. Also the core bridge can +> provide *once and only once* delivery guarantees without using XA. + +The bridge has built-in resilience to failure so if the source or target +server connection is lost, e.g. due to network failure, the bridge will +retry connecting to the source and/or target until they come back +online. When it comes back online it will resume operation as normal. + +The bridge can be configured with an optional JMS selector, so it will +only consume messages matching that JMS selector + +It can be configured to consume from a queue or a topic. When it +consumes from a topic it can be configured to consume using a non +durable or durable subscription + +Typically, the bridge is deployed by the JBoss Micro Container via a +beans configuration file. This would typically be deployed inside the +JBoss Application Server and the following example shows an example of a +beans file that bridges 2 destinations which are actually on the same +server. + + <?xml version="1.0" encoding="UTF-8"?> + <deployment xmlns="urn:jboss:bean-deployer:2.0"> + <bean name="JMSBridge" class="org.apache.activemq.api.jms.bridge.impl.JMSBridgeImpl"> + <!-- ActiveMQ must be started before the bridge --> + <depends>ActiveMQServer</depends> + <constructor> + <!-- Source ConnectionFactory Factory --> + <parameter> + <inject bean="SourceCFF"/> + </parameter> + <!-- Target ConnectionFactory Factory --> + <parameter> + <inject bean="TargetCFF"/> + </parameter> + <!-- Source DestinationFactory --> + <parameter> + <inject bean="SourceDestinationFactory"/> + </parameter> + <!-- Target DestinationFactory --> + <parameter> + <inject bean="TargetDestinationFactory"/> + </parameter> + <!-- Source User Name (no username here) --> + <parameter><null /></parameter> + <!-- Source Password (no password here)--> + <parameter><null /></parameter> + <!-- Target User Name (no username here)--> + <parameter><null /></parameter> + <!-- Target Password (no password here)--> + <parameter><null /></parameter> + <!-- Selector --> + <parameter><null /></parameter> + <!-- Failure Retry Interval (in ms) --> + <parameter>5000</parameter> + <!-- Max Retries --> + <parameter>10</parameter> + <!-- Quality Of Service --> + <parameter>ONCE_AND_ONLY_ONCE</parameter> + <!-- Max Batch Size --> + <parameter>1</parameter> + <!-- Max Batch Time (-1 means infinite) --> + <parameter>-1</parameter> + <!-- Subscription name (no subscription name here)--> + <parameter><null /></parameter> + <!-- Client ID (no client ID here)--> + <parameter><null /></parameter> + <!-- Add MessageID In Header --> + <parameter>true</parameter> + <!-- register the JMS Bridge in the AS MBeanServer --> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter>org.apache.activemq:service=JMSBridge</parameter> + </constructor> + <property name="transactionManager"> + <inject bean="RealTransactionManager"/> + </property> + </bean> + + <!-- SourceCFF describes the ConnectionFactory used to connect to the source destination --> + <bean name="SourceCFF" + class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- TargetCFF describes the ConnectionFactory used to connect to the target destination --> + <bean name="TargetCFF" + class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- SourceDestinationFactory describes the Destination used as the source --> + <bean name="SourceDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/source</parameter> + </constructor> + </bean> + + <!-- TargetDestinationFactory describes the Destination used as the target --> + <bean name="TargetDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/target</parameter> + </constructor> + </bean> + + <!-- JNDI is a Hashtable containing the JNDI properties required --> + <!-- to connect to the sources and targets JMS resrouces --> + <bean name="JNDI" class="java.util.Hashtable"> + <constructor class="java.util.Map"> + <map class="java.util.Hashtable" keyClass="String" + valueClass="String"> + <entry> + <key>java.naming.factory.initial</key> + <value>org.jnp.interfaces.NamingContextFactory</value> + </entry> + <entry> + <key>java.naming.provider.url</key> + <value>jnp://localhost:1099</value> + </entry> + <entry> + <key>java.naming.factory.url.pkgs</key> + <value>org.jboss.naming:org.jnp.interfaces"</value> + </entry> + <entry> + <key>jnp.timeout</key> + <value>5000</value> + </entry> + <entry> + <key>jnp.sotimeout</key> + <value>5000</value> + </entry> + </map> + </constructor> + </bean> + + <bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" factoryMethod="locateJBoss"/> + </bean> + </deployment> + +JMS Bridge Parameters +===================== + +The main bean deployed is the `JMSBridge` bean. The bean is configurable +by the parameters passed to its constructor. + +> **Note** +> +> To let a parameter be unspecified (for example, if the authentication +> is anonymous or no message selector is provided), use `<null +> />` for the unspecified parameter value. + +- Source Connection Factory Factory + + This injects the `SourceCFF` bean (also defined in the beans file). + This bean is used to create the *source* `ConnectionFactory` + +- Target Connection Factory Factory + + This injects the `TargetCFF` bean (also defined in the beans file). + This bean is used to create the *target* `ConnectionFactory` + +- Source Destination Factory Factory + + This injects the `SourceDestinationFactory` bean (also defined in + the beans file). This bean is used to create the *source* + `Destination` + +- Target Destination Factory Factory + + This injects the `TargetDestinationFactory` bean (also defined in + the beans file). This bean is used to create the *target* + `Destination` + +- Source User Name + + this parameter is the username for creating the *source* connection + +- Source Password + + this parameter is the parameter for creating the *source* connection + +- Target User Name + + this parameter is the username for creating the *target* connection + +- Target Password + + this parameter is the password for creating the *target* connection + +- Selector + + This represents a JMS selector expression used for consuming + messages from the source destination. Only messages that match the + selector expression will be bridged from the source to the target + destination + + The selector expression must follow the [JMS selector + syntax](http://docs.oracle.com/javaee/6/api/javax/jms/Message.html) + +- Failure Retry Interval + + This represents the amount of time in ms to wait between trying to + recreate connections to the source or target servers when the bridge + has detected they have failed + +- Max Retries + + This represents the number of times to attempt to recreate + connections to the source or target servers when the bridge has + detected they have failed. The bridge will give up after trying this + number of times. `-1` represents 'try forever' + +- Quality Of Service + + This parameter represents the desired quality of service mode + + Possible values are: + + - `AT_MOST_ONCE` + + - `DUPLICATES_OK` + + - `ONCE_AND_ONLY_ONCE` + + See ? for a explanation of these modes. + +- Max Batch Size + + This represents the maximum number of messages to consume from the + source destination before sending them in a batch to the target + destination. Its value must `>= 1` + +- Max Batch Time + + This represents the maximum number of milliseconds to wait before + sending a batch to target, even if the number of messages consumed + has not reached `MaxBatchSize`. Its value must be `-1` to represent + 'wait forever', or `>= 1` to specify an actual time + +- Subscription Name + + If the source destination represents a topic, and you want to + consume from the topic using a durable subscription then this + parameter represents the durable subscription name + +- Client ID + + If the source destination represents a topic, and you want to + consume from the topic using a durable subscription then this + attribute represents the the JMS client ID to use when + creating/looking up the durable subscription + +- Add MessageID In Header + + If `true`, then the original message's message ID will be appended + in the message sent to the destination in the header + `ACTIVEMQ_BRIDGE_MSG_ID_LIST`. If the message is bridged more than + once, each message ID will be appended. This enables a distributed + request-response pattern to be used + + > **Note** + > + > when you receive the message you can send back a response using + > the correlation id of the first message id, so when the original + > sender gets it back it will be able to correlate it. + +- MBean Server + + To manage the JMS Bridge using JMX, set the MBeanServer where the + JMS Bridge MBean must be registered (e.g. the JVM Platform + MBeanServer or JBoss AS MBeanServer) + +- ObjectName + + If you set the MBeanServer, you also need to set the ObjectName used + to register the JMS Bridge MBean (must be unique) + +The "transactionManager" property points to a JTA transaction manager +implementation. ActiveMQ doesn't ship with such an implementation, but +one is available in the JBoss Community. If you are running ActiveMQ in +standalone mode and wish to use a JMS bridge simply download the latest +version of JBossTS from http://www.jboss.org/jbosstm/downloads and add +it to ActiveMQ's classpath. If you are running ActiveMQ with JBoss AS +then you won't need to do this as JBoss AS ships with a JTA transaction +manager already. The bean definition for the transaction manager would +look something like this: + + <bean name="RealTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/> + +Source and Target Connection Factories +====================================== + +The source and target connection factory factories are used to create +the connection factory used to create the connection for the source or +target server. + +The configuration example above uses the default implementation provided +by ActiveMQ that looks up the connection factory using JNDI. For other +Application Servers or JMS providers a new implementation may have to be +provided. This can easily be done by implementing the interface +`org.apache.activemq.jms.bridge.ConnectionFactoryFactory`. + +Source and Target Destination Factories +======================================= + +Again, similarly, these are used to create or lookup up the +destinations. + +In the configuration example above, we have used the default provided by +ActiveMQ that looks up the destination using JNDI. + +A new implementation can be provided by implementing +`org.apache.activemq.jms.bridge.DestinationFactory` interface. + +Quality Of Service +================== + +The quality of service modes used by the bridge are described here in +more detail. + +AT\_MOST\_ONCE +-------------- + +With this QoS mode messages will reach the destination from the source +at most once. The messages are consumed from the source and acknowledged +before sending to the destination. Therefore there is a possibility that +if failure occurs between removing them from the source and them +arriving at the destination they could be lost. Hence delivery will +occur at most once. + +This mode is available for both durable and non-durable messages. + +DUPLICATES\_OK +-------------- + +With this QoS mode, the messages are consumed from the source and then +acknowledged after they have been successfully sent to the destination. +Therefore there is a possibility that if failure occurs after sending to +the destination but before acknowledging them, they could be sent again +when the system recovers. I.e. the destination might receive duplicates +after a failure. + +This mode is available for both durable and non-durable messages. + +ONCE\_AND\_ONLY\_ONCE +--------------------- + +This QoS mode ensures messages will reach the destination from the +source once and only once. (Sometimes this mode is known as "exactly +once"). If both the source and the destination are on the same ActiveMQ +server instance then this can be achieved by sending and acknowledging +the messages in the same local transaction. If the source and +destination are on different servers this is achieved by enlisting the +sending and consuming sessions in a JTA transaction. The JTA transaction +is controlled by JBoss Transactions JTA \* implementation which is a +fully recovering transaction manager, thus providing a very high degree +of durability. If JTA is required then both supplied connection +factories need to be XAConnectionFactory implementations. This is likely +to be the slowest mode since it requires extra persistence for the +transaction logging. + +This mode is only available for durable messages. + +> **Note** +> +> For a specific application it may possible to provide once and only +> once semantics without using the ONCE\_AND\_ONLY\_ONCE QoS level. This +> can be done by using the DUPLICATES\_OK mode and then checking for +> duplicates at the destination and discarding them. Some JMS servers +> provide automatic duplicate message detection functionality, or this +> may be possible to implement on the application level by maintaining a +> cache of received message ids on disk and comparing received messages +> to them. The cache would only be valid for a certain period of time so +> this approach is not as watertight as using ONCE\_AND\_ONLY\_ONCE but +> may be a good choice depending on your specific application. + +Time outs and the JMS bridge +---------------------------- + +There is a possibility that the target or source server will not be +available at some point in time. If this occurs then the bridge will try +`Max Retries` to reconnect every `Failure Retry Interval` milliseconds +as specified in the JMS Bridge definition. + +However since a third party JNDI is used, in this case the JBoss naming +server, it is possible for the JNDI lookup to hang if the network were +to disappear during the JNDI lookup. To stop this from occurring the +JNDI definition can be configured to time out if this occurs. To do this +set the `jnp.timeout` and the `jnp.sotimeout` on the Initial Context +definition. The first sets the connection timeout for the initial +connection and the second the read timeout for the socket. + +> **Note** +> +> Once the initial JNDI connection has succeeded all calls are made +> using RMI. If you want to control the timeouts for the RMI connections +> then this can be done via system properties. JBoss uses Sun's RMI and +> the properties can be found +> [here](http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html). +> The default connection timeout is 10 seconds and the default read +> timeout is 18 seconds. + +If you implement your own factories for looking up JMS resources then +you will have to bear in mind timeout issues. + +Examples +-------- + +Please see ? which shows how to configure and use a JMS Bridge with +JBoss AS to send messages to the source destination and consume them +from the target destination. + +Please see ? which shows how to configure and use a JMS Bridge between +two standalone ActiveMQ servers. http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/jms-bridge.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/jms-bridge.xml b/docs/user-manual/en/jms-bridge.xml deleted file mode 100644 index bc5dd5c..0000000 --- a/docs/user-manual/en/jms-bridge.xml +++ /dev/null @@ -1,449 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="jms-bridge"> - <title>The JMS Bridge</title> - <para>ActiveMQ includes a fully functional JMS message bridge.</para> - <para>The function of the bridge is to consume messages from a source queue or topic, and - send them to a target queue or topic, typically on a different server.</para> - <para>The source and target servers do not have to be in the same cluster which makes - bridging suitable for reliably sending messages from one cluster to another, for - instance across a WAN, and where the connection may be unreliable.</para> - <para>A bridge can be deployed as a standalone application, with ActiveMQ standalone server or inside a JBoss AS - instance. The source and the target can be located in the same virtual machine or another one.</para> - <para>The bridge can also be used to bridge messages from other non ActiveMQ JMS servers, as - long as they are JMS 1.1 compliant.<note><para>Do not confuse a JMS bridge with a core - bridge. A JMS bridge can be used to bridge any two JMS 1.1 compliant JMS - providers and uses the JMS API. A core bridge (described in <xref - linkend="core-bridges"/>) is used to bridge any two ActiveMQ instances and - uses the core API. Always use a core bridge if you can in preference to a JMS - bridge. The core bridge will typically provide better performance than a JMS - bridge. Also the core bridge can provide <emphasis>once and only once</emphasis> - delivery guarantees without using XA.</para></note></para> - <para>The bridge has built-in resilience to failure so if the source or target server - connection is lost, e.g. due to network failure, the bridge will retry connecting to the - source and/or target until they come back online. When it comes back online it will - resume operation as normal.</para> - <para>The bridge can be configured with an optional JMS selector, so it will only consume - messages matching that JMS selector</para> - <para>It can be configured to consume from a queue or a topic. When it consumes from a topic - it can be configured to consume using a non durable or durable subscription</para> - <para>Typically, the bridge is deployed by the JBoss Micro Container via a beans configuration file. - This would typically be deployed inside the JBoss Application Server and the following - example shows an example of a beans file that bridges 2 destinations which are actually - on the same server. </para> - <programlisting> -<?xml version="1.0" encoding="UTF-8"?> -<deployment xmlns="urn:jboss:bean-deployer:2.0"> - <bean name="JMSBridge" class="org.apache.activemq.api.jms.bridge.impl.JMSBridgeImpl"> - <!-- ActiveMQ must be started before the bridge --> - <depends>ActiveMQServer</depends> - <constructor> - <!-- Source ConnectionFactory Factory --> - <parameter> - <inject bean="SourceCFF"/> - </parameter> - <!-- Target ConnectionFactory Factory --> - <parameter> - <inject bean="TargetCFF"/> - </parameter> - <!-- Source DestinationFactory --> - <parameter> - <inject bean="SourceDestinationFactory"/> - </parameter> - <!-- Target DestinationFactory --> - <parameter> - <inject bean="TargetDestinationFactory"/> - </parameter> - <!-- Source User Name (no username here) --> - <parameter><null /></parameter> - <!-- Source Password (no password here)--> - <parameter><null /></parameter> - <!-- Target User Name (no username here)--> - <parameter><null /></parameter> - <!-- Target Password (no password here)--> - <parameter><null /></parameter> - <!-- Selector --> - <parameter><null /></parameter> - <!-- Failure Retry Interval (in ms) --> - <parameter>5000</parameter> - <!-- Max Retries --> - <parameter>10</parameter> - <!-- Quality Of Service --> - <parameter>ONCE_AND_ONLY_ONCE</parameter> - <!-- Max Batch Size --> - <parameter>1</parameter> - <!-- Max Batch Time (-1 means infinite) --> - <parameter>-1</parameter> - <!-- Subscription name (no subscription name here)--> - <parameter><null /></parameter> - <!-- Client ID (no client ID here)--> - <parameter><null /></parameter> - <!-- Add MessageID In Header --> - <parameter>true</parameter> - <!-- register the JMS Bridge in the AS MBeanServer --> - <parameter> - <inject bean="MBeanServer"/> - </parameter> - <parameter>org.apache.activemq:service=JMSBridge</parameter> - </constructor> - <property name="transactionManager"> - <inject bean="RealTransactionManager"/> - </property> - </bean> - - <!-- SourceCFF describes the ConnectionFactory used to connect to the source destination --> - <bean name="SourceCFF" - class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> - <constructor> - <parameter> - <inject bean="JNDI" /> - </parameter> - <parameter>/ConnectionFactory</parameter> - </constructor> - </bean> - - <!-- TargetCFF describes the ConnectionFactory used to connect to the target destination --> - <bean name="TargetCFF" - class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> - <constructor> - <parameter> - <inject bean="JNDI" /> - </parameter> - <parameter>/ConnectionFactory</parameter> - </constructor> - </bean> - - <!-- SourceDestinationFactory describes the Destination used as the source --> - <bean name="SourceDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory"> - <constructor> - <parameter> - <inject bean="JNDI" /> - </parameter> - <parameter>/queue/source</parameter> - </constructor> - </bean> - - <!-- TargetDestinationFactory describes the Destination used as the target --> - <bean name="TargetDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory"> - <constructor> - <parameter> - <inject bean="JNDI" /> - </parameter> - <parameter>/queue/target</parameter> - </constructor> - </bean> - - <!-- JNDI is a Hashtable containing the JNDI properties required --> - <!-- to connect to the sources and targets JMS resrouces --> - <bean name="JNDI" class="java.util.Hashtable"> - <constructor class="java.util.Map"> - <map class="java.util.Hashtable" keyClass="String" - valueClass="String"> - <entry> - <key>java.naming.factory.initial</key> - <value>org.jnp.interfaces.NamingContextFactory</value> - </entry> - <entry> - <key>java.naming.provider.url</key> - <value>jnp://localhost:1099</value> - </entry> - <entry> - <key>java.naming.factory.url.pkgs</key> - <value>org.jboss.naming:org.jnp.interfaces"</value> - </entry> - <entry> - <key>jnp.timeout</key> - <value>5000</value> - </entry> - <entry> - <key>jnp.sotimeout</key> - <value>5000</value> - </entry> - </map> - </constructor> - </bean> - - <bean name="MBeanServer" class="javax.management.MBeanServer"> - <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" factoryMethod="locateJBoss"/> - </bean> -</deployment></programlisting> - <section> - <title>JMS Bridge Parameters</title> - <para>The main bean deployed is the <literal>JMSBridge</literal> bean. The bean is - configurable by the parameters passed to its constructor.</para> - <note> - <para>To let a parameter be unspecified (for example, if the authentication is - anonymous or no message selector is provided), use <literal><null - /></literal> for the unspecified parameter value.</para> - </note> - <itemizedlist> - <listitem> - <para>Source Connection Factory Factory</para> - <para>This injects the <literal>SourceCFF</literal> bean (also defined in the - beans file). This bean is used to create the <emphasis>source</emphasis> - <literal>ConnectionFactory</literal> - </para> - </listitem> - <listitem> - <para>Target Connection Factory Factory</para> - <para>This injects the <literal>TargetCFF</literal> bean (also defined in the - beans file). This bean is used to create the <emphasis>target</emphasis> - <literal>ConnectionFactory</literal> - </para> - </listitem> - <listitem> - <para>Source Destination Factory Factory</para> - <para>This injects the <literal>SourceDestinationFactory</literal> bean (also - defined in the beans file). This bean is used to create the - <emphasis>source</emphasis> - <literal>Destination</literal> - </para> - </listitem> - <listitem> - <para>Target Destination Factory Factory</para> - <para>This injects the <literal>TargetDestinationFactory</literal> bean (also - defined in the beans file). This bean is used to create the - <emphasis>target</emphasis> - <literal>Destination</literal> - </para> - </listitem> - <listitem> - <para>Source User Name</para> - <para>this parameter is the username for creating the - <emphasis>source</emphasis> connection</para> - </listitem> - <listitem> - <para>Source Password</para> - <para>this parameter is the parameter for creating the - <emphasis>source</emphasis> connection</para> - </listitem> - <listitem> - <para>Target User Name</para> - <para>this parameter is the username for creating the - <emphasis>target</emphasis> connection</para> - </listitem> - <listitem> - <para>Target Password</para> - <para>this parameter is the password for creating the - <emphasis>target</emphasis> connection</para> - </listitem> - <listitem> - <para>Selector</para> - <para>This represents a JMS selector expression used for consuming messages from - the source destination. Only messages that match the selector expression - will be bridged from the source to the target destination</para> - <para>The selector expression must follow the <ulink - url="http://docs.oracle.com/javaee/6/api/javax/jms/Message.html">JMS - selector syntax</ulink></para> - </listitem> - <listitem> - <para>Failure Retry Interval</para> - <para>This represents the amount of time in ms to wait between trying to - recreate connections to the source or target servers when the bridge has - detected they have failed</para> - </listitem> - <listitem> - <para>Max Retries</para> - <para>This represents the number of times to attempt to recreate connections to - the source or target servers when the bridge has detected they have failed. - The bridge will give up after trying this number of times. <literal - >-1</literal> represents 'try forever'</para> - </listitem> - <listitem> - <para>Quality Of Service</para> - <para>This parameter represents the desired quality of service mode</para> - <para>Possible values are:</para> - <itemizedlist> - <listitem> - <para><literal>AT_MOST_ONCE</literal></para> - </listitem> - <listitem> - <para><literal>DUPLICATES_OK</literal></para> - </listitem> - <listitem> - <para><literal>ONCE_AND_ONLY_ONCE</literal></para> - </listitem> - </itemizedlist> - <para>See <xref linkend="quality-of-service"/> for a explanation of these - modes.</para> - </listitem> - <listitem> - <para>Max Batch Size</para> - <para>This represents the maximum number of messages to consume from the source - destination before sending them in a batch to the target destination. Its - value must <literal>>= 1</literal> - </para> - </listitem> - <listitem> - <para>Max Batch Time</para> - <para>This represents the maximum number of milliseconds to wait before sending - a batch to target, even if the number of messages consumed has not reached - <literal>MaxBatchSize</literal>. Its value must be <literal>-1</literal> - to represent 'wait forever', or <literal>>= 1</literal> to specify an actual - time </para> - </listitem> - <listitem> - <para>Subscription Name</para> - <para>If the source destination represents a topic, and you want to consume from - the topic using a durable subscription then this parameter represents the - durable subscription name</para> - </listitem> - <listitem> - <para>Client ID</para> - <para>If the source destination represents a topic, and you want to consume from - the topic using a durable subscription then this attribute represents the - the JMS client ID to use when creating/looking up the durable - subscription</para> - </listitem> - <listitem> - <para>Add MessageID In Header</para> - <para>If <literal>true</literal>, then the original message's message ID will be - appended in the message sent to the destination in the header <literal - >ACTIVEMQ_BRIDGE_MSG_ID_LIST</literal>. If the message is bridged more - than once, each message ID will be appended. This enables a distributed - request-response pattern to be used</para> - <note> - <para>when you receive the message you can send back a response using the - correlation id of the first message id, so when the original sender gets - it back it will be able to correlate it. </para> - </note> - </listitem> - <listitem> - <para>MBean Server</para> - <para>To manage the JMS Bridge using JMX, set the MBeanServer where the JMS Bridge MBean - must be registered (e.g. the JVM Platform MBeanServer or JBoss AS MBeanServer)</para> - </listitem> - <listitem> - <para>ObjectName</para> - <para>If you set the MBeanServer, you also need to set the ObjectName used to register - the JMS Bridge MBean (must be unique)</para> - </listitem> - </itemizedlist> - <para>The "transactionManager" property points to a JTA transaction manager implementation. - ActiveMQ doesn't ship with such an implementation, but one is available in the JBoss - Community. If you are running ActiveMQ in standalone mode and wish to use a JMS bridge - simply download the latest version of JBossTS from http://www.jboss.org/jbosstm/downloads - and add it to ActiveMQ's classpath. If you are running ActiveMQ with JBoss AS then you - won't need to do this as JBoss AS ships with a JTA transaction manager already. The - bean definition for the transaction manager would look something like this: - </para> - <programlisting><bean name="RealTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/></programlisting> - </section> - <section> - <title>Source and Target Connection Factories</title> - <para>The source and target connection factory factories are used to create the - connection factory used to create the connection for the source or target - server.</para> - <para>The configuration example above uses the default implementation provided by - ActiveMQ that looks up the connection factory using JNDI. For other Application - Servers or JMS providers a new implementation may have to be provided. This can - easily be done by implementing the interface <literal - >org.apache.activemq.jms.bridge.ConnectionFactoryFactory</literal>.</para> - </section> - <section> - <title>Source and Target Destination Factories</title> - <para>Again, similarly, these are used to create or lookup up the destinations.</para> - <para>In the configuration example above, we have used the default provided by ActiveMQ - that looks up the destination using JNDI.</para> - <para>A new implementation can be provided by implementing <literal - >org.apache.activemq.jms.bridge.DestinationFactory</literal> interface.</para> - </section> - <section id="quality-of-service"> - <title>Quality Of Service</title> - <para>The quality of service modes used by the bridge are described here in more - detail.</para> - <section> - <title>AT_MOST_ONCE</title> - <para>With this QoS mode messages will reach the destination from the source at most - once. The messages are consumed from the source and acknowledged before sending - to the destination. Therefore there is a possibility that if failure occurs - between removing them from the source and them arriving at the destination they - could be lost. Hence delivery will occur at most once.</para> - <para>This mode is available for both durable and non-durable messages.</para> - </section> - <section> - <title>DUPLICATES_OK</title> - <para>With this QoS mode, the messages are consumed from the source and then - acknowledged after they have been successfully sent to the destination. - Therefore there is a possibility that if failure occurs after sending to the - destination but before acknowledging them, they could be sent again when the - system recovers. I.e. the destination might receive duplicates after a - failure.</para> - <para>This mode is available for both durable and non-durable messages.</para> - </section> - <section> - <title>ONCE_AND_ONLY_ONCE</title> - <para>This QoS mode ensures messages will reach the destination from the source once - and only once. (Sometimes this mode is known as "exactly once"). If both the - source and the destination are on the same ActiveMQ server instance then this can - be achieved by sending and acknowledging the messages in the same local - transaction. If the source and destination are on different servers this is - achieved by enlisting the sending and consuming sessions in a JTA transaction. - The JTA transaction is controlled by JBoss Transactions JTA * implementation - which is a fully recovering transaction manager, thus providing a very high - degree of durability. If JTA is required then both supplied connection factories - need to be XAConnectionFactory implementations. This is likely to be the slowest - mode since it requires extra persistence for the transaction logging.</para> - <para>This mode is only available for durable messages.</para> - <note> - <para>For a specific application it may possible to provide once and only once - semantics without using the ONCE_AND_ONLY_ONCE QoS level. This can be done - by using the DUPLICATES_OK mode and then checking for duplicates at the - destination and discarding them. Some JMS servers provide automatic - duplicate message detection functionality, or this may be possible to - implement on the application level by maintaining a cache of received - message ids on disk and comparing received messages to them. The cache would - only be valid for a certain period of time so this approach is not as - watertight as using ONCE_AND_ONLY_ONCE but may be a good choice depending on - your specific application.</para> - </note> - </section> - <section> - <title>Time outs and the JMS bridge</title> - <para>There is a possibility that the target or source server will not be available at some point in time. - If this occurs then the bridge will try <literal>Max Retries</literal> to reconnect every - <literal>Failure Retry Interval</literal> milliseconds as specified in the JMS Bridge definition.</para> - <para>However since a third party JNDI is used, in this case the JBoss naming server, it is possible for the - JNDI lookup to hang if the network were to disappear during the JNDI lookup. To stop this from occurring the JNDI - definition can be configured to time out if this occurs. To do this set the <literal>jnp.timeout</literal> - and the <literal>jnp.sotimeout</literal> on the Initial Context definition. The first sets the connection - timeout for the initial connection and the second the read timeout for the socket.</para> - <note> - <para>Once the initial JNDI connection has succeeded all calls are made using RMI. If you want to control - the timeouts for the RMI connections then this can be done via system properties. JBoss uses Sun's RMI - and the properties can be found <ulink - url="http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html">here</ulink>. - The default connection timeout is 10 seconds and the default read timeout is 18 seconds.</para> - </note> - <para>If you implement your own factories for looking up JMS resources then you will have to bear in mind timeout issues.</para> - </section> - <section> - <title>Examples</title> - <para>Please see <xref linkend="examples.javaee.jms-bridge"/> which shows how to configure - and use a JMS Bridge with JBoss AS to send messages to the source destination and consume them - from the target destination.</para> - <para>Please see <xref linkend="examples.jms.jms-bridge"/> which shows how to configure - and use a JMS Bridge between two standalone ActiveMQ servers.</para> - </section> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/jms-core-mapping.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/jms-core-mapping.md b/docs/user-manual/en/jms-core-mapping.md new file mode 100644 index 0000000..0be2829 --- /dev/null +++ b/docs/user-manual/en/jms-core-mapping.md @@ -0,0 +1,39 @@ +Mapping JMS Concepts to the Core API +==================================== + +This chapter describes how JMS destinations are mapped to ActiveMQ +addresses. + +ActiveMQ core is JMS-agnostic. It does not have any concept of a JMS +topic. A JMS topic is implemented in core as an address (the topic name) +with zero or more queues bound to it. Each queue bound to that address +represents a topic subscription. Likewise, a JMS queue is implemented as +an address (the JMS queue name) with one single queue bound to it which +represents the JMS queue. + +By convention, all JMS queues map to core queues where the core queue +name has the string `jms.queue.` prepended to it. E.g. the JMS queue +with the name "orders.europe" would map to the core queue with the name +"jms.queue.orders.europe". The address at which the core queue is bound +is also given by the core queue name. + +For JMS topics the address at which the queues that represent the +subscriptions are bound is given by prepending the string "jms.topic." +to the name of the JMS topic. E.g. the JMS topic with name "news.europe" +would map to the core address "jms.topic.news.europe" + +In other words if you send a JMS message to a JMS queue with name +"orders.europe" it will get routed on the server to any core queues +bound to the address "jms.queue.orders.europe". If you send a JMS +message to a JMS topic with name "news.europe" it will get routed on the +server to any core queues bound to the address "jms.topic.news.europe". + +If you want to configure settings for a JMS Queue with the name +"orders.europe", you need to configure the corresponding core queue +"jms.queue.orders.europe": + + <!-- expired messages in JMS Queue "orders.europe" will be sent to the JMS Queue "expiry.europe" --> + <address-setting match="jms.queue.orders.europe"> + <expiry-address>jms.queue.expiry.europe</expiry-address> + ... + </address-setting> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/jms-core-mapping.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/jms-core-mapping.xml b/docs/user-manual/en/jms-core-mapping.xml deleted file mode 100644 index ae44f76..0000000 --- a/docs/user-manual/en/jms-core-mapping.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="jms-core-mapping"> - <title>Mapping JMS Concepts to the Core API</title> - <para>This chapter describes how JMS destinations are mapped to ActiveMQ addresses.</para> - <para>ActiveMQ core is JMS-agnostic. It does not have any concept of a JMS topic. A JMS topic is - implemented in core as an address (the topic name) with zero or more queues bound to it. - Each queue bound to that address represents a topic subscription. Likewise, a JMS queue is - implemented as an address (the JMS queue name) with one single queue bound to it which - represents the JMS queue.</para> - <para>By convention, all JMS queues map to core queues where the core queue name has the string - <literal>jms.queue.</literal> prepended to it. E.g. the JMS queue with the name - "orders.europe" would map to the core queue with the name "jms.queue.orders.europe". The - address at which the core queue is bound is also given by the core queue name.</para> - <para>For JMS topics the address at which the queues that represent the subscriptions are bound - is given by prepending the string "jms.topic." to the name of the JMS topic. E.g. the JMS - topic with name "news.europe" would map to the core address "jms.topic.news.europe"</para> - <para>In other words if you send a JMS message to a JMS queue with name "orders.europe" it will - get routed on the server to any core queues bound to the address "jms.queue.orders.europe". - If you send a JMS message to a JMS topic with name "news.europe" it will get routed on the - server to any core queues bound to the address "jms.topic.news.europe".</para> - <para>If you want to configure settings for a JMS Queue with the name "orders.europe", you need - to configure the corresponding core queue "jms.queue.orders.europe":</para> - <programlisting> -<!-- expired messages in JMS Queue "orders.europe" will be sent to the JMS Queue "expiry.europe" --> -<address-setting match="jms.queue.orders.europe"> - <expiry-address>jms.queue.expiry.europe</expiry-address> - ... -</address-setting></programlisting> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/large-messages.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/large-messages.md b/docs/user-manual/en/large-messages.md new file mode 100644 index 0000000..b04f201 --- /dev/null +++ b/docs/user-manual/en/large-messages.md @@ -0,0 +1,275 @@ +Large Messages +============== + +ActiveMQ supports sending and receiving of huge messages, even when the +client and server are running with limited memory. The only realistic +limit to the size of a message that can be sent or consumed is the +amount of disk space you have available. We have tested sending and +consuming messages up to 8 GiB in size with a client and server running +in just 50MiB of RAM! + +To send a large message, the user can set an `InputStream` on a message +body, and when that message is sent, ActiveMQ will read the +`InputStream`. A `FileInputStream` could be used for example to send a +huge message from a huge file on disk. + +As the `InputStream` is read the data is sent to the server as a stream +of fragments. The server persists these fragments to disk as it receives +them and when the time comes to deliver them to a consumer they are read +back of the disk, also in fragments and sent down the wire. When the +consumer receives a large message it initially receives just the message +with an empty body, it can then set an `OutputStream` on the message to +stream the huge message body to a file on disk or elsewhere. At no time +is the entire message body stored fully in memory, either on the client +or the server. + +Configuring the server +====================== + +Large messages are stored on a disk directory on the server side, as +configured on the main configuration file. + +The configuration property `large-messages-directory` specifies where +large messages are stored. + + <configuration xmlns="urn:activemq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:activemq /schema/activemq-configuration.xsd"> + ... + <large-messages-directory>/data/large-messages</large-messages-directory> + ... + </configuration + +By default the large message directory is `data/largemessages` + +For the best performance we recommend large messages directory is stored +on a different physical volume to the message journal or paging +directory. + +Configuring Parameters +====================== + +Any message larger than a certain size is considered a large message. +Large messages will be split up and sent in fragments. This is +determined by the parameter `min-large-message-size` + +> **Note** +> +> ActiveMQ messages are encoded using 2 bytes per character so if the +> message data is filled with ASCII characters (which are 1 byte) the +> size of the resulting ActiveMQ message would roughly double. This is +> important when calculating the size of a "large" message as it may +> appear to be less than the `min-large-message-size` before it is sent, +> but it then turns into a "large" message once it is encoded. + +The default value is 100KiB. + +Using Core API +-------------- + +If the ActiveMQ Core API is used, the minimal large message size is +specified by `ServerLocator.setMinLargeMessageSize`. + + ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(NettyConnectorFactory.class.getName())) + + locator.setMinLargeMessageSize(25 * 1024); + + ClientSessionFactory factory = ActiveMQClient.createClientSessionFactory(); + +? will provide more information on how to instantiate the session +factory. + +Using JMS +--------- + +If JNDI is used to instantiate and look up the connection factory, the +minimum large message size is configured in the JNDI context +environment, e.g. `jndi.properties`. Here's a simple example using the +"ConnectionFactory" connection factory which is available in the context +by default: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://localhost:5445 + connection.ConnectionFactory.minLargeMessageSize=250000 + + +If the connection factory is being instantiated directly, the minimum +large message size is specified by +`ActiveMQConnectionFactory.setMinLargeMessageSize`. + +Compressed Large Messages +------------------------- + +You can choose to send large messages in compressed form using ` + compress-large-messages` attributes. + +### `compress-large-messages` + +If you specify the boolean property `compress-large-messages` on the +`server locator` or `ConnectionFactory` as true, The system will use the +ZIP algorithm to compress the message body as the message is transferred +to the server's side. Notice that there's no special treatment at the +server's side, all the compressing and uncompressing is done at the +client. + +If the compressed size of a large message is below ` + min-large-message-size`, it is sent to server as regular +messages. This means that the message won't be written into the server's +large-message data directory, thus reducing the disk I/O. + +### + +If JNDI is used to instantiate and look up the connection factory, large +message compression can be configured in the JNDI context environment, +e.g. `jndi.properties`. Here's a simple example using the +"ConnectionFactory" connection factory which is available in the context +by default: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://localhost:5445 + connection.ConnectionFactory.compressLargeMessages=true + +Streaming large messages +======================== + +ActiveMQ supports setting the body of messages using input and output +streams (`java.lang.io`) + +These streams are then used directly for sending (input streams) and +receiving (output streams) messages. + +When receiving messages there are 2 ways to deal with the output stream; +you may choose to block while the output stream is recovered using the +method `ClientMessage.saveOutputStream` or alternatively using the +method `ClientMessage.setOutputstream` which will asynchronously write +the message to the stream. If you choose the latter the consumer must be +kept alive until the message has been fully received. + +You can use any kind of stream you like. The most common use case is to +send files stored in your disk, but you could also send things like JDBC +Blobs, `SocketInputStream`, things you recovered from `HTTPRequests` +etc. Anything as long as it implements `java.io.InputStream` for sending +messages or `java.io.OutputStream` for receiving them. + +Streaming over Core API +----------------------- + +The following table shows a list of methods available at `ClientMessage` +which are also available through JMS by the use of object properties. + + Name Description JMS Equivalent Property + --------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- ------------------------- + setBodyInputStream(InputStream) Set the InputStream used to read a message body when sending it. JMS\_HQ\_InputStream + setOutputStream(OutputStream) Set the OutputStream that will receive the body of a message. This method does not block. JMS\_HQ\_OutputStream + saveOutputStream(OutputStream) Save the body of the message to the `OutputStream`. It will block until the entire content is transferred to the `OutputStream`. JMS\_HQ\_SaveStream + + : org.apache.activemq.api.core.client.ClientMessage API + +To set the output stream when receiving a core message: + + ... + ClientMessage msg = consumer.receive(...); + + + // This will block here until the stream was transferred + msg.saveOutputStream(someOutputStream); + + ClientMessage msg2 = consumer.receive(...); + + // This will not wait the transfer to finish + msg.setOutputStream(someOtherOutputStream); + ... + +Set the input stream when sending a core message: + + ... + ClientMessage msg = session.createMessage(); + msg.setInputStream(dataInputStream); + ... + +Notice also that for messages with more than 2GiB the getBodySize() will +return invalid values since this is an integer (which is also exposed to +the JMS API). On those cases you can use the message property +\_HQ\_LARGE\_SIZE. + +Streaming over JMS +------------------ + +When using JMS, ActiveMQ maps the streaming methods on the core API (see +?) by setting object properties . You can use the method +`Message.setObjectProperty` to set the input and output streams. + +The `InputStream` can be defined through the JMS Object Property +JMS\_HQ\_InputStream on messages being sent: + + BytesMessage message = session.createBytesMessage(); + + FileInputStream fileInputStream = new FileInputStream(fileInput); + + BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream); + + message.setObjectProperty("JMS_HQ_InputStream", bufferedInput); + + someProducer.send(message); + +The `OutputStream` can be set through the JMS Object Property +JMS\_HQ\_SaveStream on messages being received in a blocking way. + + BytesMessage messageReceived = (BytesMessage)messageConsumer.receive(120000); + + File outputFile = new File("huge_message_received.dat"); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + + BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream); + + // This will block until the entire content is saved on disk + messageReceived.setObjectProperty("JMS_HQ_SaveStream", bufferedOutput); + +Setting the `OutputStream` could also be done in a non blocking way +using the property JMS\_HQ\_OutputStream. + + // This won't wait the stream to finish. You need to keep the consumer active. + messageReceived.setObjectProperty("JMS_HQ_OutputStream", bufferedOutput); + +> **Note** +> +> When using JMS, Streaming large messages are only supported on +> `StreamMessage` and `BytesMessage`. + +Streaming Alternative +===================== + +If you choose not to use the `InputStream` or `OutputStream` capability +of ActiveMQ You could still access the data directly in an alternative +fashion. + +On the Core API just get the bytes of the body as you normally would. + + ClientMessage msg = consumer.receive(); + + byte[] bytes = new byte[1024]; + for (int i = 0 ; i < msg.getBodySize(); i += bytes.length) + { + msg.getBody().readBytes(bytes); + // Whatever you want to do with the bytes + } + +If using JMS API, `BytesMessage` and `StreamMessage` also supports it +transparently. + + BytesMessage rm = (BytesMessage)cons.receive(10000); + + byte data[] = new byte[1024]; + + for (int i = 0; i < rm.getBodyLength(); i += 1024) + { + int numberOfBytes = rm.readBytes(data); + // Do whatever you want with the data + } + +Large message example +===================== + +Please see ? for an example which shows how large message is configured +and used with JMS.