http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/core-bridges.xml
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/core-bridges.xml 
b/docs/user-manual/en/core-bridges.xml
new file mode 100644
index 0000000..9004e7f
--- /dev/null
+++ b/docs/user-manual/en/core-bridges.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
============================================================================= 
-->
+<!-- Copyright © 2009 Red Hat, Inc. and others.                               
     -->
+<!--                                                                           
    -->
+<!-- The text of and illustrations in this document are licensed by Red Hat 
under  -->
+<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license 
("CC-BY-SA"). -->
+<!--                                                                           
    -->
+<!-- An explanation of CC-BY-SA is available at                                
    -->
+<!--                                                                           
    -->
+<!--            http://creativecommons.org/licenses/by-sa/3.0/.                
    -->
+<!--                                                                           
    -->
+<!-- In accordance with CC-BY-SA, if you distribute this document or an 
adaptation -->
+<!-- of it, you must provide the URL for the original version.                 
    -->
+<!--                                                                           
    -->
+<!-- Red Hat, as the licensor of this document, waives the right to enforce,   
    -->
+<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent    
    -->
+<!-- permitted by applicable law.                                              
    -->
+<!-- 
============================================================================= 
-->
+
+<!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 "HornetQ_User_Manual.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="core-bridges">
+    <title>Core Bridges</title>
+    <para>The function of a bridge is to consume messages from a source queue, 
and forward them to a
+        target address, typically on a different HornetQ 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, or internet and where the connection may be unreliable.</para>
+    <para>The bridge has built in resilience to failure so if the target 
server connection is lost,
+        e.g. due to network failure, the bridge will retry connecting to the 
target until it comes
+        back online. When it comes back online it will resume operation as 
normal.</para>
+    <para>In summary, bridges are a way to reliably connect two separate 
HornetQ servers together.
+        With a core bridge both source and target servers must be HornetQ 
servers.</para>
+    <para>Bridges can be configured to provide <emphasis>once and only 
once</emphasis> delivery
+        guarantees even in the event of the failure of the source or the 
target server. They do this
+        by using duplicate detection (described in <xref 
linkend="duplicate-detection"/>).</para>
+    <note>
+        <para>Although they have similar function, don't confuse core bridges 
with JMS
+            bridges!</para>
+        <para>Core bridges are for linking a HornetQ node with another HornetQ 
node and do not use
+            the JMS API. A JMS Bridge is used for linking any two JMS 1.1 
compliant JMS providers.
+            So, a JMS Bridge could be used for bridging to or from different 
JMS compliant messaging
+            system. It's always preferable to use a core bridge if you can. 
Core bridges use
+            duplicate detection to provide <emphasis>once and only 
once</emphasis> guarantees. To
+            provide the same guarantee using a JMS bridge you would have to 
use XA which has a
+            higher overhead and is more complex to configure.</para>
+    </note>
+    <section>
+        <title>Configuring Bridges</title>
+        <para>Bridges are configured in 
<literal>hornetq-configuration.xml</literal>. Let's kick off
+            with an example (this is actually from the bridge example):</para>
+        <programlisting>
+&lt;bridge name="my-bridge">
+   &lt;queue-name>jms.queue.sausage-factory&lt;/queue-name>
+   &lt;forwarding-address>jms.queue.mincing-machine&lt;/forwarding-address>
+   &lt;filter-string="name='aardvark'"/>
+   &lt;transformer-class-name>
+      org.hornetq.jms.example.HatColourChangeTransformer
+   &lt;/transformer-class-name>
+   &lt;retry-interval>1000&lt;/retry-interval>
+   &lt;ha>true&lt;/ha>
+   &lt;retry-interval-multiplier>1.0&lt;/retry-interval-multiplier>
+   &lt;initial-connect-attempts>-1&lt;/initial-connect-attempts>
+   &lt;reconnect-attempts>-1&lt;/reconnect-attempts>
+   &lt;failover-on-server-shutdown>false&lt;/failover-on-server-shutdown>
+   &lt;use-duplicate-detection>true&lt;/use-duplicate-detection>
+   &lt;confirmation-window-size>10000000&lt;/confirmation-window-size>
+   &lt;user>foouser&lt;/user>
+   &lt;password>foopassword&lt;/password>
+   &lt;static-connectors>
+      &lt;connector-ref>remote-connector&lt;/connector-ref>
+   &lt;/static-connectors>
+   &lt;!-- alternative to static-connectors
+   &lt;discovery-group-ref discovery-group-name="bridge-discovery-group"/>
+   -->
+&lt;/bridge></programlisting>
+        <para>In the above example we have shown all the parameters its 
possible to configure for a
+            bridge. In practice you might use many of the defaults so it won't 
be necessary to
+            specify them all explicitly.</para>
+        <para>Let's take a look at all the parameters in turn:</para>
+        <itemizedlist>
+            <listitem>
+                <para><literal>name</literal> attribute. All bridges must have 
a unique name in the
+                    server.</para>
+            </listitem>
+            <listitem>
+                <para><literal>queue-name</literal>. This is the unique name 
of the local queue that
+                    the bridge consumes from, it's a mandatory 
parameter.</para>
+                <para>The queue must already exist by the time the bridge is 
instantiated at
+                    start-up.</para>
+                <note>
+                    <para>If you're using JMS then normally the JMS 
configuration <literal
+                            >hornetq-jms.xml</literal> is loaded after the 
core configuration file
+                            <literal>hornetq-configuration.xml</literal> is 
loaded. If your bridge
+                        is consuming from a JMS queue then you'll need to make 
sure the JMS queue is
+                        also deployed as a core queue in the core 
configuration. Take a look at the
+                        bridge example for an example of how this is 
done.</para>
+                </note>
+            </listitem>
+            <listitem>
+                <para><literal>forwarding-address</literal>. This is the 
address on the target
+                    server that the message will be forwarded to. If a 
forwarding address is not
+                    specified, then the original address of the message will 
be retained.</para>
+            </listitem>
+            <listitem>
+                <para><literal>filter-string</literal>. An optional filter 
string can be supplied.
+                    If specified then only messages which match the filter 
expression specified in
+                    the filter string will be forwarded. The filter string 
follows the HornetQ
+                    filter expression syntax described in <xref 
linkend="filter-expressions"
+                    />.</para>
+            </listitem>
+            <listitem>
+                <para><literal>transformer-class-name</literal>. An optional 
transformer-class-name
+                    can be specified. This is the name of a user-defined class 
which implements the
+                        
<literal>org.hornetq.core.server.cluster.Transformer</literal>
+                    interface.</para>
+                <para>If this is specified then the transformer's 
<literal>transform()</literal>
+                    method will be invoked with the message before it is 
forwarded. This gives you
+                    the opportunity to transform the message's header or body 
before forwarding
+                    it.</para>
+            </listitem>
+            <listitem>
+                <para><literal>ha</literal>. This optional parameter 
determines whether or not this
+                   bridge should support high availability. True means it will 
connect to any available
+                   server in a cluster and support failover. The default value 
is <literal
+                        >false</literal>.</para>
+            </listitem>
+            <listitem>
+                <para><literal>retry-interval</literal>. This optional 
parameter determines the
+                    period in milliseconds between subsequent reconnection 
attempts, if the
+                    connection to the target server has failed. The default 
value is <literal
+                        >2000</literal>milliseconds.</para>
+            </listitem>
+            <listitem>
+                <para><literal>retry-interval-multiplier</literal>. This 
optional parameter
+                    determines determines a multiplier to apply to the time 
since the last retry to
+                    compute the time to the next retry.</para>
+                <para>This allows you to implement an <emphasis>exponential 
backoff</emphasis>
+                    between retry attempts.</para>
+                <para>Let's take an example:</para>
+                <para>If we set <literal>retry-interval</literal>to 
<literal>1000</literal> ms and
+                    we set <literal>retry-interval-multiplier</literal> to 
<literal>2.0</literal>,
+                    then, if the first reconnect attempt fails, we will wait 
<literal>1000</literal>
+                    ms then <literal>2000</literal> ms then 
<literal>4000</literal> ms between
+                    subsequent reconnection attempts.</para>
+                <para>The default value is <literal>1.0</literal> meaning each 
reconnect attempt is
+                    spaced at equal intervals.</para>
+            </listitem>
+            <listitem>
+                <para><literal>initial-connect-attempts</literal>. This 
optional parameter determines the
+                    total number of initial connect attempts the bridge will 
make before giving up and
+                    shutting down. A value of <literal>-1</literal> signifies 
an unlimited number of
+                    attempts. The default value is 
<literal>-1</literal>.</para>
+            </listitem>
+            <listitem>
+                <para><literal>reconnect-attempts</literal>. This optional 
parameter determines the
+                    total number of reconnect attempts the bridge will make 
before giving up and
+                    shutting down. A value of <literal>-1</literal> signifies 
an unlimited number of
+                    attempts. The default value is 
<literal>-1</literal>.</para>
+            </listitem>
+            <listitem>
+                <para><literal>failover-on-server-shutdown</literal>. This 
optional parameter
+                    determines whether the bridge will attempt to failover 
onto a backup server (if
+                    specified) when the target server is cleanly shutdown 
rather than
+                    crashed.</para>
+                <para>The bridge connector can specify both a live and a 
backup server, if it
+                    specifies a backup server and this parameter is set to 
<literal>true</literal>
+                    then if the target server is <emphasis>cleanly</emphasis> 
shutdown the bridge
+                    connection will attempt to failover onto its backup. If 
the bridge connector has
+                    no backup server configured then this parameter has no 
effect. </para>
+                <para>Sometimes you want a bridge configured with a live and a 
backup target server,
+                    but you don't want to failover to the backup if the live 
server is simply taken
+                    down temporarily for maintenance, this is when this 
parameter comes in
+                    handy.</para>
+                <para>The default value for this parameter is 
<literal>false</literal>.</para>
+            </listitem>
+            <listitem>
+                <para><literal>use-duplicate-detection</literal>. This 
optional parameter determines
+                    whether the bridge will automatically insert a duplicate 
id property into each
+                    message that it forwards.</para>
+                <para>Doing so, allows the target server to perform duplicate 
detection on messages
+                    it receives from the source server. If the connection 
fails or server crashes,
+                    then, when the bridge resumes it will resend 
unacknowledged messages. This might
+                    result in duplicate messages being sent to the target 
server. By enabling
+                    duplicate detection allows these duplicates to be screened 
out and
+                    ignored.</para>
+                <para>This allows the bridge to provide a <emphasis>once and 
only once</emphasis>
+                    delivery guarantee without using heavyweight methods such 
as XA (see <xref
+                        linkend="duplicate-detection"/> for more 
information).</para>
+                <para>The default value for this parameter is 
<literal>true</literal>.</para>
+            </listitem>
+            <listitem>
+                <para><literal>confirmation-window-size</literal>. This 
optional parameter
+                    determines the <literal>confirmation-window-size</literal> 
to use for the
+                    connection used to forward messages to the target node. 
This attribute is
+                    described in section <xref 
linkend="client-reconnection"/></para>
+
+                 <warning><para>When using the bridge to forward messages from 
a queue which has a
+                    max-size-bytes set it's important that 
confirmation-window-size is less than
+                    or equal to <literal>max-size-bytes</literal> to prevent 
the flow of
+                    messages from ceasing.</para>
+                 </warning>
+
+            </listitem>
+            <listitem>
+                <para><literal>user</literal>. This optional parameter 
determines the user name to
+                    use when creating the bridge connection to the remote 
server. If it is not
+                    specified the default cluster user specified by 
<literal>cluster-user</literal>
+                    in <literal>hornetq-configuration.xml</literal> will be 
used. </para>
+            </listitem>
+            <listitem>
+                <para><literal>password</literal>. This optional parameter 
determines the password
+                    to use when creating the bridge connection to the remote 
server. If it is not
+                    specified the default cluster password specified by 
<literal
+                            >cluster-password</literal> in 
<literal>hornetq-configuration.xml</literal>
+                    will be used. </para>
+            </listitem>
+            <listitem>
+                <para><literal>static-connectors</literal> or 
<literal>discovery-group-ref</literal>.
+                    Pick either of these options to connect the bridge to the 
target server.
+                </para>
+                <para> The <literal>static-connectors</literal> is a list of 
<literal>connector-ref</literal>
+                    elements pointing to <literal>connector</literal> elements 
defined elsewhere.
+                    A <emphasis>connector</emphasis> encapsulates knowledge of 
what transport to
+                    use (TCP, SSL, HTTP etc) as well as the server connection 
parameters (host, port
+                    etc). For more information about what connectors are and 
how to configure them,
+                    please see <xref linkend="configuring-transports"/>.
+                </para>
+                <para>The <literal>discovery-group-ref</literal> element has 
one attribute -
+                    <literal>discovery-group-name</literal>.  This attribute 
points to a
+                    <literal>discovery-group</literal> defined elsewhere. For 
more information about
+                    what discovery-groups are and how to configure them, 
please see
+                    <xref linkend="clusters.discovery-groups"/>.
+                </para>
+            </listitem>
+        </itemizedlist>
+    </section>
+</chapter>

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/diagrams/architecture-diagrams.odg
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/diagrams/architecture-diagrams.odg 
b/docs/user-manual/en/diagrams/architecture-diagrams.odg
new file mode 100644
index 0000000..33d99cf
Binary files /dev/null and 
b/docs/user-manual/en/diagrams/architecture-diagrams.odg differ

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/diagrams/ha-replicated-store.odg
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/diagrams/ha-replicated-store.odg 
b/docs/user-manual/en/diagrams/ha-replicated-store.odg
new file mode 100644
index 0000000..495c672
Binary files /dev/null and 
b/docs/user-manual/en/diagrams/ha-replicated-store.odg differ

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/diagrams/ha-shared-store.odg
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/diagrams/ha-shared-store.odg 
b/docs/user-manual/en/diagrams/ha-shared-store.odg
new file mode 100644
index 0000000..3b97692
Binary files /dev/null and b/docs/user-manual/en/diagrams/ha-shared-store.odg 
differ

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/diverts.xml
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/diverts.xml b/docs/user-manual/en/diverts.xml
new file mode 100644
index 0000000..3cddf09
--- /dev/null
+++ b/docs/user-manual/en/diverts.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- 
============================================================================= 
-->
+<!-- Copyright © 2009 Red Hat, Inc. and others.                               
     -->
+<!--                                                                           
    -->
+<!-- The text of and illustrations in this document are licensed by Red Hat 
under  -->
+<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license 
("CC-BY-SA"). -->
+<!--                                                                           
    -->
+<!-- An explanation of CC-BY-SA is available at                                
    -->
+<!--                                                                           
    -->
+<!--            http://creativecommons.org/licenses/by-sa/3.0/.                
    -->
+<!--                                                                           
    -->
+<!-- In accordance with CC-BY-SA, if you distribute this document or an 
adaptation -->
+<!-- of it, you must provide the URL for the original version.                 
    -->
+<!--                                                                           
    -->
+<!-- Red Hat, as the licensor of this document, waives the right to enforce,   
    -->
+<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent    
    -->
+<!-- permitted by applicable law.                                              
    -->
+<!-- 
============================================================================= 
-->
+
+<!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 "HornetQ_User_Manual.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="diverts">
+    <title>Diverting and Splitting Message Flows</title>
+    <para>HornetQ allows you to configure objects called 
<emphasis>diverts</emphasis> with
+        some simple server configuration.</para>
+    <para>Diverts allow you to transparently divert messages routed to one 
address to some other
+        address, without making any changes to any client application 
logic.</para>
+    <para>Diverts can be <emphasis>exclusive</emphasis>, meaning that the 
message is diverted
+        to the new address, and does not go to the old address at all, or they 
can be
+            <emphasis>non-exclusive</emphasis> which means the message 
continues to go the old
+        address, and a <emphasis>copy</emphasis> of it is also sent to the new 
address.
+        Non-exclusive diverts can therefore be used for 
<emphasis>splitting</emphasis> message
+        flows, e.g. there may be a requirement to monitor every order sent to 
an order queue.</para>
+    <para>Diverts can also be configured to have an optional message filter. 
If specified then only
+        messages that match the filter will be diverted.</para>
+    <para>Diverts can also be configured to apply a 
<literal>Transformer</literal>. If specified,
+        all diverted messages will have the opportunity of being transformed 
by the <literal
+            >Transformer</literal>.</para>
+    <para>A divert will only divert a message to an address on the 
<emphasis>same server</emphasis>,
+        however, if you want to divert to an address on a different server, a 
common pattern would
+        be to divert to a local store-and-forward queue, then set up a bridge 
which consumes from
+        that queue and forwards to an address on a different server.</para>
+    <para>Diverts are therefore a very sophisticated concept, which when 
combined with bridges can
+        be used to create interesting and complex routings. The set of diverts 
on a server can be
+        thought of as a type of routing table for messages. Combining diverts 
with bridges allows
+        you to create a distributed network of reliable routing connections 
between multiple
+        geographically distributed servers, creating your global messaging 
mesh.</para>
+    <para>Diverts are defined as xml in the 
<literal>hornetq-configuration.xml</literal> file. There can
+        be zero or more diverts in the file.</para>
+    <para>Please see <xref linkend="divert-example" /> for a full working
+        example showing you how to configure and use diverts.</para>
+    <para>Let's take a look at some divert examples:</para>
+    <section>
+        <title>Exclusive Divert</title>
+        <para>Let's take a look at an exclusive divert. An exclusive divert 
diverts all matching
+            messages that are routed to the old address to the new address. 
Matching messages do not
+            get routed to the old address.</para>
+        <para>Here's some example xml configuration for an exclusive divert, 
it's taken from the
+            divert example:</para>
+        <programlisting>
+&lt;divert name="prices-divert">
+   &lt;address>jms.topic.priceUpdates&lt;/address>
+   &lt;forwarding-address>jms.queue.priceForwarding&lt;/forwarding-address>
+   &lt;filter string="office='New York'"/>
+   &lt;transformer-class-name>
+      org.hornetq.jms.example.AddForwardingTimeTransformer
+   &lt;/transformer-class-name>
+   &lt;exclusive>true&lt;/exclusive>
+&lt;/divert></programlisting>
+        <para>We define a divert called '<literal>prices-divert</literal>' 
that will divert any
+            messages sent to the address 
'<literal>jms.topic.priceUpdates</literal>' (this
+            corresponds to any messages sent to a JMS Topic called '<literal
+            >priceUpdates</literal>') to another local address '<literal
+                >jms.queue.priceForwarding</literal>' (this corresponds to a 
local JMS queue called
+                '<literal>priceForwarding</literal>'</para>
+        <para>We also specify a message filter string so only messages with 
the message property
+                <literal>office</literal> with value <literal>New 
York</literal> will get diverted,
+            all other messages will continue to be routed to the normal 
address. The filter string
+            is optional, if not specified then all messages will be considered 
matched.</para>
+        <para>In this example a transformer class is specified. Again this is 
optional, and if
+            specified the transformer will be executed for each matching 
message. This allows you to
+            change the messages body or properties before it is diverted. In 
this example the
+            transformer simply adds a header that records the time the divert 
happened.</para>
+        <para>This example is actually diverting messages to a local store and 
forward queue, which
+            is configured with a bridge which forwards the message to an 
address on another HornetQ
+            server. Please see the example for more details.</para>
+    </section>
+    <section>
+        <title>Non-exclusive Divert</title>
+        <para>Now we'll take a look at a non-exclusive divert. Non exclusive 
diverts are the same as
+            exclusive diverts, but they only forward a 
<emphasis>copy</emphasis> of the message to
+            the new address. The original message continues to the old 
address</para>
+        <para>You can therefore think of non-exclusive diverts as 
<emphasis>splitting</emphasis> a
+            message flow.</para>
+        <para>Non exclusive diverts can be configured in the same way as 
exclusive diverts with an
+            optional filter and transformer, here's an example non-exclusive 
divert, again from the
+            divert example:</para>
+        <programlisting>
+&lt;divert name="order-divert">
+    &lt;address>jms.queue.orders&lt;/address>
+    &lt;forwarding-address>jms.topic.spyTopic&lt;/forwarding-address>
+    &lt;exclusive>false&lt;/exclusive>
+&lt;/divert></programlisting>
+        <para>The above divert example takes a copy of every message sent to 
the address '<literal
+                >jms.queue.orders</literal>' (Which corresponds to a JMS Queue 
called '<literal
+                >orders</literal>') and sends it to a local address called 
'<literal
+                >jms.topic.SpyTopic</literal>' (which corresponds to a JMS 
Topic called '<literal
+                >SpyTopic</literal>').</para>
+    </section>
+</chapter>

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/duplicate-detection.xml
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/duplicate-detection.xml 
b/docs/user-manual/en/duplicate-detection.xml
new file mode 100644
index 0000000..c2577ff
--- /dev/null
+++ b/docs/user-manual/en/duplicate-detection.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- 
============================================================================= 
-->
+<!-- Copyright © 2009 Red Hat, Inc. and others.                               
     -->
+<!--                                                                           
    -->
+<!-- The text of and illustrations in this document are licensed by Red Hat 
under  -->
+<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license 
("CC-BY-SA"). -->
+<!--                                                                           
    -->
+<!-- An explanation of CC-BY-SA is available at                                
    -->
+<!--                                                                           
    -->
+<!--            http://creativecommons.org/licenses/by-sa/3.0/.                
    -->
+<!--                                                                           
    -->
+<!-- In accordance with CC-BY-SA, if you distribute this document or an 
adaptation -->
+<!-- of it, you must provide the URL for the original version.                 
    -->
+<!--                                                                           
    -->
+<!-- Red Hat, as the licensor of this document, waives the right to enforce,   
    -->
+<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent    
    -->
+<!-- permitted by applicable law.                                              
    -->
+<!-- 
============================================================================= 
-->
+
+<!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 "HornetQ_User_Manual.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="duplicate-detection">
+    <title>Duplicate Message Detection</title>
+    <para>HornetQ includes powerful automatic duplicate message detection, 
filtering out
+        duplicate messages without you having to code your own fiddly 
duplicate detection logic at
+        the application level. This chapter will explain what duplicate 
detection is, how HornetQ
+        uses it and how and where to configure it.</para>
+    <para>When sending messages from a client to a server, or indeed from a 
server to another
+        server, if the target server or connection fails sometime after 
sending the message, but
+        before the sender receives a response that the send (or commit) was 
processed successfully
+        then the sender cannot know for sure if the message was sent 
successfully to the
+        address.</para>
+    <para>If the target server or connection failed after the send was 
received and processed but
+        before the response was sent back then the message will have been sent 
to the address
+        successfully, but if the target server or connection failed before the 
send was received and
+        finished processing then it will not have been sent to the address 
successfully. From the
+        senders point of view it's not possible to distinguish these two 
cases.</para>
+    <para>When the server recovers this leaves the client in a difficult 
situation. It knows the
+        target server failed, but it does not know if the last message reached 
its destination ok.
+        If it decides to resend the last message, then that could result in a 
duplicate message
+        being sent to the address. If each message was an order or a trade 
then this could result in
+        the order being fulfilled twice or the trade being double booked. This 
is clearly not a
+        desirable situation.</para>
+    <para>Sending the message(s) in a transaction does not help out either. If 
the server or
+        connection fails while the transaction commit is being processed it is 
also indeterminate
+        whether the transaction was successfully committed or not!</para>
+    <para>To solve these issues HornetQ provides automatic duplicate messages 
detection for
+        messages sent to addresses.</para>
+    <section>
+        <title>Using Duplicate Detection for Message Sending</title>
+        <para>Enabling duplicate message detection for sent messages is 
simple: you just need to set
+            a special property on the message to a unique value. You can 
create the value however
+            you like, as long as it is unique. When the target server receives 
the message it will
+            check if that property is set, if it is, then it will check in its 
in memory cache if it
+            has already received a message with that value of the header. If 
it has received a
+            message with the same value before then it will ignore the 
message.</para>
+        <note>
+            <para>Using duplicate detection to move messages between nodes can 
give you the same
+                    <emphasis>once and only once</emphasis> delivery 
guarantees as if you were using
+                an XA transaction to consume messages from source and send 
them to the target, but
+                with less overhead and much easier configuration than using 
XA.</para>
+        </note>
+        <para>If you're sending messages in a transaction then you don't have 
to set the property
+            for <emphasis>every</emphasis> message you send in that 
transaction, you only need to
+            set it once in the transaction. If the server detects a duplicate 
message for any
+            message in the transaction, then it will ignore the entire 
transaction.</para>
+        <para>The name of the property that you set is given by the value of 
<literal
+                
>org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID</literal>, which
+            is <literal>_HQ_DUPL_ID</literal></para>
+        <para>The value of the property can be of type 
<literal>byte[]</literal> or <literal
+                >SimpleString</literal> if you're using the core API. If 
you're using JMS it must be
+            a <literal>String</literal>, and its value should be unique. An 
easy way of generating
+            a unique id is by generating a UUID.</para>
+        <para>Here's an example of setting the property using the core 
API:</para>
+        <programlisting>
+...     
+
+ClientMessage message = session.createMessage(true);
+
+SimpleString myUniqueID = "This is my unique id";   // Could use a UUID for 
this
+
+message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID);
+
+...</programlisting>
+        <para>And here's an example using the JMS API:</para>
+        <programlisting>
+...     
+
+Message jmsMessage = session.createMessage();
+
+String myUniqueID = "This is my unique id";   // Could use a UUID for this
+
+message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);
+
+...</programlisting>
+    </section>
+    <section id="duplicate.id.cache">
+        <title>Configuring the Duplicate ID Cache</title>
+        <para>The server maintains caches of received values of the <literal
+                
>org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID</literal> property
+            sent to each address. Each address has its own distinct 
cache.</para>
+        <para>The cache is a circular fixed size cache. If the cache has a 
maximum size of <literal
+                >n</literal> elements, then the <literal>n + 1</literal>th id 
stored will overwrite
+            the <literal>0</literal>th element in the cache.</para>
+        <para>The maximum size of the cache is configured by the parameter 
<literal
+                >id-cache-size</literal> in 
<literal>hornetq-configuration.xml</literal>, the default
+            value is <literal>2000</literal> elements.</para>
+        <para>The caches can also be configured to persist to disk or not. 
This is configured by the
+            parameter <literal>persist-id-cache</literal>, also in <literal
+                >hornetq-configuration.xml</literal>. If this is set to 
<literal>true</literal> then
+            each id will be persisted to permanent storage as they are 
received. The default value
+            for this parameter is <literal>true</literal>.</para>
+        <note>
+            <para>When choosing a size of the duplicate id cache be sure to 
set it to a larger
+                enough size so if you resend messages all the previously sent 
ones are in the cache
+                not having been overwritten.</para>
+        </note>
+    </section>
+    <section>
+        <title>Duplicate Detection and Bridges</title>
+        <para>Core bridges can be configured to automatically add a unique 
duplicate id value (if there
+            isn't already one in the message) before forwarding the message to 
it's target. This
+            ensures that if the target server crashes or the connection is 
interrupted and the
+            bridge resends the message, then if it has already been received 
by the target server,
+            it will be ignored.</para>
+        <para>To configure a core bridge to add the duplicate id header, 
simply set the <parameter
+                >use-duplicate-detection</parameter> to 
<literal>true</literal> when configuring a
+            bridge in <literal>hornetq-configuration.xml</literal>.</para>
+        <para>The default value for this parameter is 
<literal>true</literal>.</para>
+        <para>For more information on core bridges and how to configure them, 
please see 
+                <xref linkend="core-bridges" />.</para>
+    </section>
+    <section>
+        <title>Duplicate Detection and Cluster Connections</title>
+        <para>Cluster connections internally use core bridges to move messages 
reliable between
+            nodes of the cluster. Consequently they can also be configured to 
insert the duplicate
+            id header for each message they move using their internal 
bridges.</para>
+        <para>To configure a cluster connection to add the duplicate id 
header, simply set the
+                <parameter>use-duplicate-detection</parameter> to 
<literal>true</literal> when
+            configuring a cluster connection in 
<literal>hornetq-configuration.xml</literal>.</para>
+        <para>The default value for this parameter is 
<literal>true</literal>.</para>
+        <para>For more information on cluster connections and how to configure 
them, please see <xref
+                linkend="clusters"/>.</para>
+    </section>
+</chapter>

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/embedding-hornetq.xml
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/embedding-hornetq.xml 
b/docs/user-manual/en/embedding-hornetq.xml
new file mode 100644
index 0000000..e2bea3a
--- /dev/null
+++ b/docs/user-manual/en/embedding-hornetq.xml
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
+"../../../lib/docbook-support/support/docbook-dtd/docbookx.dtd"> -->
+<!-- 
============================================================================= 
-->
+<!-- Copyright © 2009 Red Hat, Inc. and others.                               
     -->
+<!--                                                                           
    -->
+<!-- The text of and illustrations in this document are licensed by Red Hat 
under  -->
+<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license 
("CC-BY-SA"). -->
+<!--                                                                           
    -->
+<!-- An explanation of CC-BY-SA is available at                                
    -->
+<!--                                                                           
    -->
+<!--            http://creativecommons.org/licenses/by-sa/3.0/.                
    -->
+<!--                                                                           
    -->
+<!-- In accordance with CC-BY-SA, if you distribute this document or an 
adaptation -->
+<!-- of it, you must provide the URL for the original version.                 
    -->
+<!--                                                                           
    -->
+<!-- Red Hat, as the licensor of this document, waives the right to enforce,   
    -->
+<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent    
    -->
+<!-- permitted by applicable law.                                              
    -->
+<!-- 
============================================================================= 
-->
+
+<!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 "HornetQ_User_Manual.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="embedding-hornetq">
+  <title>Embedding HornetQ</title>
+
+  <para>HornetQ is designed as set of simple Plain Old Java Objects (POJOs).
+  This means HornetQ can be instantiated and run in any dependency injection
+  framework such as JBoss Microcontainer, Spring or Google Guice. It also
+  means that if you have an application that could use messaging functionality
+  internally, then it can <emphasis>directly instantiate</emphasis> HornetQ
+  clients and servers in its own application code to perform that
+  functionality. We call this <emphasis>embedding</emphasis> HornetQ.</para>
+
+  <para>Examples of applications that might want to do this include any
+  application that needs very high performance, transactional, persistent
+  messaging but doesn't want the hassle of writing it all from scratch.</para>
+
+  <para>Embedding HornetQ can be done in very few easy steps. Instantiate the
+  configuration object, instantiate the server, start it, and you have a
+  HornetQ running in your virtual machine. It's as simple and easy as
+  that.</para>
+
+  <section>
+    <title>Simple Config File Embedding</title>
+
+    <para>The simplest way to embed HornetQ is to use the embedded wrapper
+    classes and configure HornetQ through its configuration files. There are
+    two different helper classes for this depending on whether your using the
+    HornetQ Core API or JMS.</para>
+
+    <section>
+      <title>Core API Only</title>
+      <para>For instantiating a core HornetQ Server only, the steps are pretty
+      simple. The example requires that you have defined a configuration file
+      <literal>hornetq-configuration.xml</literal> in your
+      classpath:</para>
+        <programlisting>
+import org.hornetq.core.server.embedded.EmbeddedHornetQ;
+
+...
+
+EmbeddedHornetQ embedded = new EmbeddedHornetQ();
+embedded.start();
+
+ClientSessionFactory nettyFactory =  HornetQClient.createClientSessionFactory(
+                                        new TransportConfiguration(
+                                           
InVMConnectorFactory.class.getName()));
+
+ClientSession session = factory.createSession();
+
+session.createQueue("example", "example", true);
+
+ClientProducer producer = session.createProducer("example");
+
+ClientMessage message = session.createMessage(true);
+
+message.getBody().writeString("Hello");
+
+producer.send(message);
+
+session.start();
+
+ClientConsumer consumer = session.createConsumer("example");
+
+ClientMessage msgReceived = consumer.receive();
+
+System.out.println("message = " + msgReceived.getBody().readString());
+
+session.close();</programlisting>
+
+<para>The <literal>EmbeddedHornetQ</literal> class has a
+      few additional setter methods that allow you to specify a different
+      config file name as well as other properties. See the javadocs for this
+      class for more details.</para>
+    </section>
+
+    <section id="simple.embedded.jms">
+      <title>JMS API</title>
+
+      <para>JMS embedding is simple as well. This example requires that you
+      have defined the config files
+      <literal>hornetq-configuration.xml</literal>,
+      <literal>hornetq-jms.xml</literal>, and a
+      <literal>hornetq-users.xml</literal> if you have security enabled. Let's
+      also assume that a queue and connection factory has been defined in the
+      <literal>hornetq-jms.xml</literal> config file.</para>
+
+      <programlisting>
+import org.hornetq.jms.server.embedded.EmbeddedJMS;
+
+...
+
+EmbeddedJMS jms = new EmbeddedJMS();
+jms.start();
+
+// This assumes we have configured hornetq-jms.xml with the appropriate config 
information
+ConnectionFactory connectionFactory = jms.lookup("ConnectionFactory");
+Destination destination = jms.lookup("/example/queue");
+
+... regular JMS code ...</programlisting>
+        <para>By default, the <literal>EmbeddedJMS</literal>
+      class will store component entries defined within your
+      <literal>hornetq-jms.xml</literal> file in an internal concurrent hash
+      map. The <literal>EmbeddedJMS.lookup()</literal> method returns
+      components stored in this map. If you want to use JNDI, call the
+      <literal>EmbeddedJMS.setContext()</literal> method with the root JNDI
+      context you want your components bound into. See the javadocs for this
+      class for more details on other config options.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>POJO instantiation - Embedding Programmatically</title>
+
+    <para>You can follow this step-by-step guide to programmatically embed the
+    core, non-JMS HornetQ Server instance:</para>
+
+    <para>Create the configuration object - this contains configuration
+    information for a HornetQ instance. The setter methods of this class allow
+    you to programmatically set configuration options as describe in the <xref
+    linkend="server.configuration" /> section.</para>
+
+    <para>The acceptors are configured through
+    <literal>ConfigurationImpl</literal>. Just add the
+    <literal>NettyAcceptorFactory</literal> on the transports the same way you
+    would through the main configuration file.</para>
+
+    <programlisting>
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.config.impl.ConfigurationImpl;
+
+...
+
+Configuration config = new ConfigurationImpl();
+HashSet&lt;TransportConfiguration> transports = new 
HashSet&lt;TransportConfiguration>();
+      
+transports.add(new 
TransportConfiguration(NettyAcceptorFactory.class.getName()));
+transports.add(new 
TransportConfiguration(InVMAcceptorFactory.class.getName()));
+
+config.setAcceptorConfigurations(transports);</programlisting>
+
+    <para>You need to instantiate an instance of
+    <literal>org.hornetq.api.core.server.embedded.EmbeddedHornetQ</literal>
+    and add the configuration object to it.</para>
+
+    <programlisting>
+import org.hornetq.api.core.server.HornetQ;
+import org.hornetq.core.server.embedded.EmbeddedHornetQ;
+
+...
+
+EmbeddedHornetQ server = new EmbeddedHornetQ();
+server.setConfiguration(config);
+
+server.start();</programlisting>
+
+    <para>You also have the option of instantiating
+    <literal>HornetQServerImpl</literal> directly:</para>
+
+    <programlisting>
+HornetQServer server = new HornetQServerImpl(config);
+server.start();</programlisting>
+
+    <para>For JMS POJO instantiation, you work with the EmbeddedJMS class
+    instead as described earlier. First you define the configuration
+    programmatically for your ConnectionFactory and Destination objects, then
+    set the JmsConfiguration property of the EmbeddedJMS class. Here is an
+    example of this:</para>
+
+    <programlisting>
+// Step 1. Create HornetQ core configuration, and set the properties 
accordingly
+Configuration configuration = new ConfigurationImpl();
+configuration.setPersistenceEnabled(false);
+configuration.setSecurityEnabled(false);
+configuration.getAcceptorConfigurations().add(new 
TransportConfiguration(NettyAcceptorFactory.class.getName()));
+
+// Step 2. Create the JMS configuration
+JMSConfiguration jmsConfig = new JMSConfigurationImpl();
+
+// Step 3. Configure the JMS ConnectionFactory
+TransportConfiguration connectorConfig = new 
TransportConfiguration(NettyConnectorFactory.class.getName());
+ConnectionFactoryConfiguration cfConfig = new 
ConnectionFactoryConfigurationImpl("cf", connectorConfig, "/cf");
+jmsConfig.getConnectionFactoryConfigurations().add(cfConfig);
+
+// Step 4. Configure the JMS Queue
+JMSQueueConfiguration queueConfig = new JMSQueueConfigurationImpl("queue1", 
null, false, "/queue/queue1");
+jmsConfig.getQueueConfigurations().add(queueConfig);
+
+// Step 5. Start the JMS Server using the HornetQ core server and the JMS 
configuration
+EmbeddedJMS jmsServer = new EmbeddedJMS();
+jmsServer.setConfiguration(configuration);
+jmsServer.setJmsConfiguration(jmsConfig);
+jmsServer.start();</programlisting>
+
+    <para>Please see <xref linkend="examples.embedded.jms" /> for an example 
which
+    shows how to setup and run HornetQ embedded with JMS.</para>
+  </section>
+
+  <section>
+    <title>Dependency Frameworks</title>
+
+    <para>You may also choose to use a dependency injection framework such as
+    <trademark>JBoss Micro Container</trademark> or <trademark>Spring
+    Framework</trademark>. See <xref linkend="spring.integration" /> for more
+    details on Spring and HornetQ, but here's how you would do things with the
+    JBoss Micro Container.</para>
+
+    <para>HornetQ standalone uses JBoss Micro Container as the injection
+    framework. <literal>HornetQBootstrapServer</literal> and
+    <literal>hornetq-beans.xml</literal> which are part of the HornetQ
+    distribution provide a very complete implementation of what's needed to
+    bootstrap the server using JBoss Micro Container.</para>
+
+    <para>When using JBoss Micro Container, you need to provide an XML file
+    declaring the <literal>HornetQServer</literal> and
+    <literal>Configuration</literal> object, you can also inject a security
+    manager and a MBean server if you want, but those are optional.</para>
+
+    <para>A very basic XML Bean declaration for the JBoss Micro Container
+    would be:</para>
+
+    <programlisting>
+&lt;?xml version="1.0" encoding="UTF-8"?>
+&lt;deployment xmlns="urn:jboss:bean-deployer:2.0">
+   &lt;!-- The core configuration -->
+   &lt;bean name="Configuration" 
+         class="org.hornetq.core.config.impl.FileConfiguration">
+   &lt;/bean>
+
+     &lt;!-- The core server -->
+   &lt;bean name="HornetQServer" 
+         class="org.hornetq.core.server.impl.HornetQServerImpl">
+      &lt;constructor>
+         &lt;parameter>
+            &lt;inject bean="Configuration"/>
+         &lt;/parameter>
+      &lt;/constructor>
+   &lt;/bean>
+&lt;/deployment></programlisting>
+
+    <para><literal>HornetQBootstrapServer</literal> provides an easy
+    encapsulation of JBoss Micro Container.</para>
+
+    <programlisting>
+HornetQBootstrapServer bootStrap = new HornetQBootstrapServer(new String[] 
{"hornetq-beans.xml"});
+bootStrap.run();</programlisting>
+  </section>
+</chapter>

Reply via email to