http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/docs/user-manual/en/rest.xml
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/rest.xml b/docs/user-manual/en/rest.xml
new file mode 100644
index 0000000..ae5c416
--- /dev/null
+++ b/docs/user-manual/en/rest.xml
@@ -0,0 +1,2151 @@
+<?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.                                              
    -->
+<!-- 
============================================================================= 
-->
+<chapter id="rest">
+    <title>REST Interface</title>
+
+    <para>The HornetQ REST interface allows you to leverage the reliability
+        and scalability features of HornetQ over a simple REST/HTTP interface.
+        Messages are produced and consumed by sending and receiving simple HTTP
+        messages that contain the content you want to push around. For 
instance,
+        here's a simple example of posting an order to an order processing 
queue
+        express as an HTTP message:
+    </para>
+
+    <programlisting>
+POST /queue/orders/create HTTP/1.1
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone 4&lt;/item>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order></programlisting>
+
+    <para>As you can see, we're just posting some arbitrary XML
+        document to a URL. When the XML is received on the server is it 
processed
+        within HornetQ as a JMS message and distributed through core HornetQ.
+        Simple and easy. Consuming messages from a queue or topic looks very
+        similar. We'll discuss the entire interface in detail later in this
+        docbook.
+    </para>
+
+    <section>
+        <title>Goals of REST Interface</title>
+
+        <para>Why would you want to use HornetQ's REST interface? What are the
+            goals of the REST interface?
+        </para>
+
+        <itemizedlist>
+            <listitem>
+                <para>Easily usable by machine-based (code) clients.</para>
+            </listitem>
+
+            <listitem>
+                <para>Zero client footprint. We want HornetQ to be usable by 
any
+                    client/programming language that has an adequate HTTP 
client
+                    library. You shouldn't have to download, install, and 
configure a
+                    special library to interact with HornetQ.
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>Lightweight interoperability. The HTTP protocol is strong
+                    enough to be our message exchange protocol. Since 
interactions are
+                    RESTful the HTTP uniform interface provides all the 
interoperability
+                    you need to communicate between different languages, 
platforms, and
+                    even messaging implementations that choose to implement 
the same
+                    RESTful interface as HornetQ (i.e. the
+                    <ulink url="http://rest-star.org";>REST-*</ulink> effort.)
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>No envelope (e.g. SOAP) or feed (e.g. Atom) format
+                    requirements. You shouldn't have to learn, use, or parse a 
specific
+                    XML document format in order to send and receive messages 
through
+                    HornetQ's REST interface.
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>Leverage the reliability, scalability, and clustering 
features
+                    of HornetQ on the back end without sacrificing the 
simplicity of a
+                    REST interface.
+                </para>
+            </listitem>
+        </itemizedlist>
+    </section>
+
+
+    <section id="install">
+        <title>Installation and Configuration</title>
+
+        <para>HornetQ's REST interface is installed as a Web archive (WAR). It
+            depends on the
+            <ulink url="http://jboss.org/resteasy";>RESTEasy</ulink>
+            project and can currently only run within a servlet container. 
Installing
+            the HornetQ REST interface is a little bit different depending 
whether
+            HornetQ is already installed and configured for your environment 
(e.g.
+            you're deploying within JBoss AS 7) or you want the HornetQ REST
+            WAR to startup and manage the HornetQ server (e.g. you're deploying
+            within something like Apache Tomcat).
+        </para>
+
+        <section>
+            <title>Installing Within Pre-configured Environment</title>
+
+            <para>This section should be used when you want to use the HornetQ 
REST
+                interface in an environment that already has HornetQ installed 
and
+                running, e.g. JBoss AS 7. You must create a Web archive
+                (.WAR) file with the following web.xml settings:
+            </para>
+
+            <programlisting>
+&lt;web-app>
+   &lt;listener>
+      &lt;listener-class>
+         org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
+      &lt;/listener-class>
+   &lt;/listener>
+
+   &lt;listener>
+      &lt;listener-class>
+         org.hornetq.rest.integration.RestMessagingBootstrapListener
+      &lt;/listener-class>
+   &lt;/listener>
+
+   &lt;filter>
+      &lt;filter-name>Rest-Messaging&lt;/filter-name>
+      &lt;filter-class>
+         org.jboss.resteasy.plugins.server.servlet.FilterDispatcher
+      &lt;/filter-class>
+   &lt;/filter>
+
+   &lt;filter-mapping>
+      &lt;filter-name>Rest-Messaging&lt;/filter-name>
+      &lt;url-pattern>/*&lt;/url-pattern>
+   &lt;/filter-mapping>
+&lt;/web-app></programlisting>
+
+            <para>Within your WEB-INF/lib directory you must have the
+                hornetq-rest.jar file. If RESTEasy is not installed within your
+                environment, you must add the RESTEasy jar files within the lib
+                directory as well. Here's a sample Maven pom.xml that can 
build your WAR
+                for this case.
+            </para>
+
+            <programlisting>
+&lt;project xmlns="http://maven.apache.org/POM/4.0.0";
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+   &lt;modelVersion>4.0.0&lt;/modelVersion>
+   &lt;groupId>org.somebody&lt;/groupId>
+   &lt;artifactId>myapp&lt;/artifactId>
+   &lt;packaging>war&lt;/packaging>
+   &lt;name>My App&lt;/name>
+   &lt;version>0.1-SNAPSHOT&lt;/version>
+   &lt;repositories>
+      &lt;repository>
+         &lt;id>jboss&lt;/id>
+         
&lt;url>http://repository.jboss.org/nexus/content/groups/public/&lt;/url>
+      &lt;/repository>
+   &lt;/repositories>
+
+   &lt;build>
+      &lt;plugins>
+         &lt;plugin>
+            &lt;groupId>org.apache.maven.plugins&lt;/groupId>
+            &lt;artifactId>maven-compiler-plugin&lt;/artifactId>
+            &lt;configuration>
+               &lt;source>1.6&lt;/source>
+               &lt;target>1.6&lt;/target>
+            &lt;/configuration>
+         &lt;/plugin>
+      &lt;/plugins>
+   &lt;/build>
+
+   &lt;dependencies>
+      &lt;dependency>
+         &lt;groupId>org.hornetq.rest&lt;/groupId>
+         &lt;artifactId>hornetq-rest&lt;/artifactId>
+         &lt;version>2.3.0-SNAPSHOT&lt;/version>
+      &lt;/dependency>
+   &lt;/dependencies>
+&lt;/project></programlisting>
+
+            <note>
+                <para>JBoss AS 7 loads classes differently than previous 
versions.
+                    To work properly in AS 7 the WAR will need this in its 
MANIFEST.MF:
+                </para>
+                <programlisting>Dependencies: org.hornetq, 
org.jboss.netty</programlisting>
+                <para>You can add this to the<literal>&lt;plugins></literal>
+                    section of the pom.xml to create this entry automatically:
+                </para>
+                <programlisting>
+&lt;plugin>
+   &lt;groupId>org.apache.maven.plugins&lt;/groupId>
+   &lt;artifactId>maven-war-plugin&lt;/artifactId>
+   &lt;configuration>
+      &lt;archive>
+         &lt;manifestEntries>
+            &lt;Dependencies>org.hornetq, org.jboss.netty&lt;/Dependencies>
+         &lt;/manifestEntries>
+      &lt;/archive>
+   &lt;/configuration>
+&lt;/plugin></programlisting>
+            </note>
+
+            <para>
+                It is worth noting that when deploying a WAR in a Java EE 
application server
+                like AS7 the URL for the resulting application will include 
the name of the
+                WAR by default.  For example, if you've constructed a WAR as 
described above
+                named "hornetq-rest.war" then clients will access it at, e.g.
+                http://localhost:8080/hornetq-rest/[queues|topics].  We'll see 
more about
+                this later.
+            </para>
+            <note>
+                <para>
+                    It is possible to put the WAR file at the "root context" 
of AS7, but
+                    that is beyond the scope of this documentation.
+                </para>
+            </note>
+        </section>
+
+        <section>
+            <title>Bootstrapping HornetQ Along with REST</title>
+
+            <para>You can bootstrap HornetQ within your WAR as well. To do 
this, you
+                must have the HornetQ core and JMS jars along with Netty, 
Resteasy, and
+                the HornetQ REST jar within your WEB-INF/lib. You must also 
have a
+                hornetq-configuration.xml, hornetq-jms.xml, and 
hornetq-users.xml config
+                files within WEB-INF/classes. The examples that come with the 
HornetQ
+                REST distribution show how to do this. You must also add an 
additional
+                listener to your web.xml file. Here's an example:
+            </para>
+
+            <programlisting>
+&lt;web-app>
+   &lt;listener>
+      &lt;listener-class>
+         org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
+      &lt;/listener-class>
+   &lt;/listener>
+
+   &lt;listener>
+      &lt;listener-class>
+         org.hornetq.rest.integration.HornetqBootstrapListener
+      &lt;/listener-class>
+   &lt;/listener>
+
+   &lt;listener>
+      &lt;listener-class>
+         org.hornetq.rest.integration.RestMessagingBootstrapListener
+      &lt;/listener-class>
+   &lt;/listener>
+
+   &lt;filter>
+      &lt;filter-name>Rest-Messaging&lt;/filter-name>
+      &lt;filter-class>
+         org.jboss.resteasy.plugins.server.servlet.FilterDispatcher
+      &lt;/filter-class>
+   &lt;/filter>
+
+   &lt;filter-mapping>
+      &lt;filter-name>Rest-Messaging&lt;/filter-name>
+      &lt;url-pattern>/*&lt;/url-pattern>
+   &lt;/filter-mapping>
+&lt;/web-app></programlisting>
+
+            <para>Here's a Maven pom.xml file for creating a WAR for this
+                environment. Make sure your hornetq configuration files are 
within the
+                src/main/resources directory so that they are stuffed within 
the WAR's
+                WEB-INF/classes directory!
+            </para>
+
+            <programlisting>
+&lt;project xmlns="http://maven.apache.org/POM/4.0.0";
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+   &lt;modelVersion>4.0.0&lt;/modelVersion>
+   &lt;groupId>org.somebody&lt;/groupId>
+   &lt;artifactId>myapp&lt;/artifactId>
+   &lt;packaging>war&lt;/packaging>
+   &lt;name>My App&lt;/name>
+   &lt;version>0.1-SNAPSHOT&lt;/version>
+   &lt;repositories>
+      &lt;repository>
+         &lt;id>jboss&lt;/id>
+         
&lt;url>http://repository.jboss.org/nexus/content/groups/public/&lt;/url>
+      &lt;/repository>
+   &lt;/repositories>
+   &lt;build>
+      &lt;plugins>
+         &lt;plugin>
+            &lt;groupId>org.apache.maven.plugins&lt;/groupId>
+            &lt;artifactId>maven-compiler-plugin&lt;/artifactId>
+            &lt;configuration>
+               &lt;source>1.6&lt;/source>
+               &lt;target>1.6&lt;/target>
+            &lt;/configuration>
+         &lt;/plugin>
+      &lt;/plugins>
+   &lt;/build>
+   &lt;dependencies>
+      &lt;dependency>
+         &lt;groupId>org.hornetq&lt;/groupId>
+         &lt;artifactId>hornetq-core&lt;/artifactId>
+         &lt;version>2.3.0-SNAPSHOT&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>io.netty&lt;/groupId>
+         &lt;artifactId>netty&lt;/artifactId>
+         &lt;version>3.4.5.Final&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>org.hornetq&lt;/groupId>
+         &lt;artifactId>hornetq-jms&lt;/artifactId>
+         &lt;version>2.3.0-SNAPSHOT&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>org.jboss.spec.javax.jms&lt;/groupId>
+         &lt;artifactId>jboss-jms-api_2.0_spec&lt;/artifactId>
+         &lt;version>1.0.0.Final&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>org.hornetq.rest&lt;/groupId>
+         &lt;artifactId>hornetq-rest&lt;/artifactId>
+         &lt;version>2.3.0-SNAPSHOT&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>org.jboss.resteasy&lt;/groupId>
+         &lt;artifactId>resteasy-jaxrs&lt;/artifactId>
+         &lt;version>2.3.4.Final&lt;/version>
+      &lt;/dependency>
+      &lt;dependency>
+         &lt;groupId>org.jboss.resteasy&lt;/groupId>
+         &lt;artifactId>resteasy-jaxb-provider&lt;/artifactId>
+         &lt;version>2.3.4.Final&lt;/version>
+      &lt;/dependency>
+   &lt;/dependencies>
+&lt;/project></programlisting>
+        </section>
+
+        <section id="configuration">
+            <title>REST Configuration</title>
+
+            <para>The HornetQ REST implementation does have some configuration
+                options. These are configured via XML configuration file that 
must be in
+                your WEB-INF/classes directory. You must set the web.xml 
context-param
+                <literal>rest.messaging.config.file</literal> to specify the 
name of the
+                configuration file. Below is the format of the XML 
configuration file
+                and the default values for each.
+            </para>
+
+            <programlisting>
+&lt;rest-messaging>
+   &lt;server-in-vm-id>0&lt;/server-in-vm-id>
+   &lt;use-link-headers>false&lt;/use-link-headers>
+   &lt;default-durable-send>false&lt;/default-durable-send>
+   &lt;dups-ok>true&lt;/dups-ok>
+   &lt;topic-push-store-dir>topic-push-store&lt;/topic-push-store-dir>
+   &lt;queue-push-store-dir>queue-push-store&lt;/queue-push-store-dir>
+   &lt;producer-time-to-live>0&lt;/producer-time-to-live>
+   &lt;producer-session-pool-size>10&lt;/producer-session-pool-size>
+   &lt;session-timeout-task-interval>1&lt;/session-timeout-task-interval>
+   
&lt;consumer-session-timeout-seconds>300&lt;/consumer-session-timeout-seconds>
+   &lt;consumer-window-size>-1&lt;/consumer-window-size>
+&lt;/rest-messaging></programlisting>
+
+            <para>Let's give an explanation of each config option.</para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>server-in-vm-id</literal>. The HornetQ REST
+                        impl uses the IN-VM transport to communicate with 
HornetQ.
+                        It uses the default server id, which is "0".
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>use-link-headers</literal>. By default, all
+                        links (URLs) are published using custom headers. You 
can
+                        instead have the HornetQ REST implementation publish 
links
+                        using the <ulink 
url="http://tools.ietf.org/html/draft-nottingham-http-link-header-10";>
+                            Link Header specification
+                        </ulink> instead if you desire.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>default-durable-send</literal>. Whether a 
posted
+                        message should be persisted by default if the user 
does not
+                        specify a durable query parameter.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>dups-ok</literal>. If this is true, no 
duplicate
+                        detection protocol will be enforced for message 
posting.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>topic-push-store-dir</literal>. This must be
+                        a relative or absolute file system path. This is a 
directory
+                        where push registrations for topics are stored. See
+                        <link linkend="message-push">Pushing Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>queue-push-store-dir</literal>. This must be
+                        a relative or absolute file system path. This is a
+                        directory where push registrations for queues are 
stored.
+                        See <link linkend="message-push">Pushing 
Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>producer-session-pool-size</literal>. The 
REST
+                        implementation pools HornetQ sessions for sending 
messages.
+                        This is the size of the pool. That number of sessions 
will
+                        be created at startup time.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>producer-time-to-live</literal>. Default 
time
+                        to live for posted messages. Default is no ttl.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>session-timeout-task-interval</literal>. 
Pull
+                        consumers and pull subscriptions can time out. This is
+                        the interval the thread that checks for timed-out 
sessions
+                        will run at. A value of 1 means it will run every 1 
second.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>consumer-session-timeout-seconds</literal>.
+                        Timeout in seconds for pull consumers/subscriptions 
that
+                        remain idle for that amount of time.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>consumer-window-size</literal>. For 
consumers,
+                        this config option is the same as the HornetQ one of 
the
+                        same name. It will be used by sessions created by the
+                        HornetQ REST implementation.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </section>
+    </section>
+
+
+    <section id="basics">
+        <title>HornetQ REST Interface Basics</title>
+
+        <para>The HornetQ REST interface publishes a variety of REST resources 
to
+            perform various tasks on a queue or topic. Only the top-level 
queue and
+            topic URI schemes are published to the outside world. You must 
discover
+            all over resources to interact with by looking for and traversing 
links.
+            You'll find published links within custom response headers and 
embedded in
+            published XML representations. Let's look at how this works.
+        </para>
+
+        <section>
+            <title>Queue and Topic Resources</title>
+
+            <para>To interact with a queue or topic you do a HEAD or GET 
request on
+                the following relative URI pattern:
+            </para>
+
+            <programlisting>
+/queues/{name}
+/topics/{name}</programlisting>
+
+            <para>The base of the URI is the base URL of the WAR you deployed 
the
+                HornetQ REST server within as defined in the
+                <link linkend="install">Installation and Configuration</link>
+                section of this document. Replace the <literal>{name}</literal>
+                string within the above URI pattern with the name of the queue 
or
+                topic you are interested in interacting with. For example if 
you
+                have configured a JMS topic named "foo" within your
+                <literal>hornetq-jms.xml</literal> file, the URI name should be
+                "jms.topic.foo". If you have configured a JMS queue name "bar" 
within
+                your <literal>hornetq-jms.xml</literal> file, the URI name 
should be
+                "jms.queue.bar". Internally, HornetQ prepends the "jms.topic" 
or
+                "jms.queue" strings to the name of the deployed destination. 
Next,
+                perform your HEAD or GET request on this URI. Here's what a
+                request/response would look like.
+            </para>
+
+            <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-create-with-id: http://example.com/queues/jms.queue.bar/create/{id}
+msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers
+msg-push-consumers: 
http://example.com/queues/jms.queue.bar/push-consumers</programlisting>
+
+            <note>
+                <para>
+                    You can use the "curl" utility to test this easily. Simply 
execute
+                    a command like this:
+                </para>
+
+                <programlisting>
+curl --head http://example.com/queues/jms.queue.bar</programlisting>
+            </note>
+
+            <para>The HEAD or GET response contains a number of custom response
+                headers that are URLs to additional REST resources that allow 
you to
+                interact with the queue or topic in different ways. It is 
important not
+                to rely on the scheme of the URLs returned within these 
headers as they
+                are an implementation detail. Treat them as opaque and query 
for them
+                each and every time you initially interact (at boot time) with 
the
+                server. If you treat all URLs as opaque then you will be 
isolated from
+                implementation changes as the HornetQ REST interface evolves 
over
+                time.
+            </para>
+        </section>
+
+        <section>
+            <title>Queue Resource Response Headers</title>
+
+            <para>Below is a list of response headers you should expect when
+                interacting with a Queue resource.
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>msg-create</literal>. This is a URL you 
POST messages
+                        to. The semantics of this link are described in
+                        <link linkend="posting-messages">Posting 
Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-create-with-id</literal>. This is a URL
+                        <emphasis>template</emphasis> you can use to POST 
messages.
+                        The semantics of this link are described in
+                        <link linkend="posting-messages">Posting 
Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-pull-consumers</literal>. This is a URL 
for
+                        creating consumers that will pull from a queue. The 
semantics
+                        of this link are described in
+                        <link linkend="message-pull">Consuming Messages via 
Pull</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-push-consumers</literal>. This is a URL 
for
+                        registering other URLs you want the HornetQ REST 
server to
+                        push messages to. The semantics of this link are 
described
+                        in <link linkend="message-push">Pushing 
Messages</link>.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </section>
+
+        <section>
+            <title>Topic Resource Response Headers</title>
+
+            <para>Below is a list of response headers you should expect when
+                interacting with a Topic resource.
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>msg-create</literal>. This is a URL you POST
+                        messages to. The semantics of this link are described 
in
+                        <link linkend="posting-messages">Posting 
Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-create-with-id</literal>. This is a URL
+                        <emphasis>template</emphasis> you can use to POST 
messages.
+                        The semantics of this link are described in
+                        <link linkend="posting-messages">Posting 
Messages</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-pull-subscriptions</literal>. This is a
+                        URL for creating subscribers that will pull from a 
topic.
+                        The semantics of this link are described in
+                        <link linkend="message-pull">Consuming Messages via 
Pull</link>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-push-subscriptions</literal>. This is a
+                        URL for registering other URLs you want the HornetQ 
REST
+                        server to push messages to. The semantics of this link
+                        are described in <link linkend="message-push">Pushing
+                        Messages</link>.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </section>
+    </section>
+
+
+    <section id="posting-messages">
+        <title>Posting Messages</title>
+
+        <para>This chapter discusses the protocol for posting messages to a 
queue
+            or a topic. In <link linkend="basics">HornetQ REST Interface 
Basics</link>,
+            you saw that a queue or topic resource publishes variable custom 
headers
+            that are links to other RESTful resources. The 
<literal>msg-create</literal>
+            header is a URL you can post a message to. Messages are published 
to a queue
+            or topic by sending a simple HTTP message to the URL published by 
the
+            <literal>msg-create</literal> header. The HTTP message contains 
whatever
+            content you want to publish to the HornetQ destination. Here's an 
example
+            scenario:
+        </para>
+
+        <note>
+            <para>You can also post messages to the URL template found in
+                <literal>msg-create-with-id</literal>, but this is a more 
advanced
+                use-case involving duplicate detection that we will discuss 
later in
+                this section.
+            </para>
+        </note>
+
+        <orderedlist>
+            <listitem>
+                <para>Obtain the starting <literal>msg-create</literal> header 
from
+                    the queue or topic resource.
+                </para>
+
+                <para>
+                    <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-create-with-id: 
http://example.com/queues/jms.queue.bar/create/{id}</programlisting>
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>Do a POST to the URL contained in the 
<literal>msg-create</literal>
+                    header.
+                </para>
+
+                <programlisting>
+POST /queues/jms.queue.bar/create
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone4&lt;/name>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order>
+
+--- Response ---
+HTTP/1.1 201 Created
+msg-create-next: 
http://example.com/queues/jms.queue.bar/create</programlisting>
+
+                <note>
+                    <para>You can use the "curl" utility to test this easily. 
Simply execute
+                        a command like this:
+                    </para>
+                    <programlisting>
+curl --verbose --data "123" 
http://example.com/queues/jms.queue.bar/create</programlisting>
+                </note>
+
+                <para>A successful response will return a 201 response code. 
Also
+                    notice that a <literal>msg-create-next</literal> response 
header
+                    is sent as well. You must use this URL to POST your next 
message.
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>POST your next message to the queue using the URL 
returned in
+                    the <literal>msg-create-next</literal> header.
+                </para>
+
+                <programlisting>
+POST /queues/jms.queue.bar/create
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Monica&lt;/name>
+   &lt;item>iPad&lt;/item>
+   &lt;cost>$499.99&lt;/cost>
+&lt;/order>
+
+--- Response --
+HTTP/1.1 201 Created
+msg-create-next: 
http://example.com/queues/jms.queue.bar/create</programlisting>
+                <para>Continue using the new <literal>msg-create-next</literal>
+                    header returned with each response.
+                </para>
+            </listitem>
+        </orderedlist>
+
+        <warning>
+            <para>It is <emphasis>VERY IMPORTANT</emphasis> that you never 
re-use returned
+                <literal>msg-create-next</literal> headers to post new 
messages. If the
+                <literal>dups-ok</literal> configuration property is set to
+                <literal>false</literal> on the server then this URL will be 
uniquely
+                generated for each message and used for duplicate detection. 
If you lose
+                the URL within the <literal>msg-create-next</literal> header, 
then just
+                go back to the queue or topic resource to get the
+                <literal>msg-create</literal> URL again.
+            </para>
+        </warning>
+
+        <section>
+            <title>Duplicate Detection</title>
+
+            <para>Sometimes you might have network problems when posting new
+                messages to a queue or topic. You may do a POST and never 
receive a
+                response. Unfortunately, you don't know whether or not the 
server
+                received the message and so a re-post of the message might 
cause
+                duplicates to be posted to the queue or topic. By default, the 
HornetQ
+                REST interface is configured to accept and post duplicate 
messages. You
+                can change this by turning on duplicate message detection by 
setting the
+                <literal>dups-ok</literal> config option to 
<literal>false</literal>
+                as described in <link linkend="basics">HornetQ REST Interface 
Basics</link>.
+                When you do this, the initial POST to the 
<literal>msg-create</literal>
+                URL will redirect you, using the standard HTTP 307 redirection 
mechanism
+                to a unique URL to POST to. All other interactions remain the 
same as
+                discussed earlier. Here's an example:
+            </para>
+
+            <orderedlist>
+                <listitem>
+                    <para>Obtain the starting <literal>msg-create</literal> 
header from
+                        the queue or topic resource.
+                    </para>
+
+                    <para>
+                        <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-create-with-id: 
http://example.com/queues/jms.queue.bar/create/{id}</programlisting>
+                    </para>
+                </listitem>
+
+                <listitem>
+                    <para>Do a POST to the URL contained in the 
<literal>msg-create</literal>
+                        header.
+                    </para>
+
+                    <programlisting>
+POST /queues/jms.queue.bar/create
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone4&lt;/name>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order>
+
+--- Response ---
+HTTP/1.1 307 Redirect
+Location: 
http://example.com/queues/jms.queue.bar/create/13582001787372</programlisting>
+
+                    <para>A successful response will return a 307 response 
code. This
+                        is standard HTTP protocol. It is telling you that you 
must re-POST
+                        to the URL contained within the 
<literal>Location</literal>
+                        header.
+                    </para>
+                </listitem>
+
+                <listitem>
+                    <para>re-POST your message to the URL provided within the
+                        <literal>Location</literal> header.
+                    </para>
+
+                    <programlisting>
+POST /queues/jms.queue.bar/create/13582001787372
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone4&lt;/name>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order>
+
+--- Response --
+HTTP/1.1 201 Created
+msg-create-next: 
http://example.com/queues/jms.queue.bar/create/13582001787373</programlisting>
+                    <para>You should receive a 201 Created response. If there 
is a
+                        network failure, just re-POST to the Location header. 
For new
+                        messages, use the returned 
<literal>msg-create-next</literal>
+                        header returned with each response.
+                    </para>
+                </listitem>
+
+                <listitem>
+                    <para>POST any new message to the returned
+                        <literal>msg-create-next</literal> header.
+                    </para>
+
+                    <programlisting>
+POST /queues/jms.queue.bar/create/13582001787373
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Monica&lt;/name>
+   &lt;item>iPad&lt;/name>
+   &lt;cost>$499.99&lt;/cost>
+&lt;/order>
+
+--- Response --
+HTTP/1.1 201 Created
+msg-create-next: 
http://example.com/queues/jms.queue.bar/create/13582001787374</programlisting>
+                    <para>If there ever is a network problem, just repost to 
the URL
+                        provided in the <literal>msg-create-next</literal> 
header.
+                    </para>
+                </listitem>
+            </orderedlist>
+
+            <para>How can this work? As you can see, with each successful 
response,
+                the HornetQ REST server returns a uniquely generated URL 
within the
+                msg-create-next header. This URL is dedicated to the next new 
message
+                you want to post. Behind the scenes, the code extracts an 
identify from
+                the URL and uses HornetQ's duplicate detection mechanism by 
setting the
+                <literal>DUPLICATE_DETECTION_ID</literal> property of the JMS 
message
+                that is actually posted to the system.
+            </para>
+
+            <para>If you happen to use the same ID more than once you'll see a 
message
+                like this on the server:
+            </para>
+            <programlisting>
+WARN  [org.hornetq.core.server] (Thread-3 
(HornetQ-remoting-threads-HornetQServerImpl::serverUUID=8d6be6f8-5e8b-11e2-80db-51bbde66f473-26319292-267207))
 HQ112098: Duplicate message detected - message will not be routed. Message 
information:
+ServerMessage[messageID=20,priority=4, bodySize=1500,expiration=0, 
durable=true, 
address=jms.queue.bar,properties=TypedProperties[{http_content$type=application/x-www-form-urlencoded,
 http_content$length=3, postedAsHttpMessage=true, 
_HQ_DUPL_ID=42}]]@12835058</programlisting>
+
+            <para>An alternative to this approach is to use the 
<literal>msg-create-with-id</literal>
+                header. This is not an invokable URL, but a URL template. The 
idea is that
+                the client provides the 
<literal>DUPLICATE_DETECTION_ID</literal> and creates
+                its own <literal>create-next</literal> URL. The 
<literal>msg-create-with-id</literal>
+                header looks like this (you've see it in previous examples, 
but we haven't used it):
+            </para>
+
+            <programlisting>
+msg-create-with-id: 
http://example.com/queues/jms.queue.bar/create/{id}</programlisting>
+
+            <para>You see that it is a regular URL appended with a 
<literal>{id}</literal>. This
+                <literal>{id}</literal> is a pattern matching substring. A 
client would generate its
+                <literal>DUPLICATE_DETECTION_ID</literal> and replace 
<literal>{id}</literal>
+                with that generated id, then POST to the new URL. The URL the 
client creates
+                works exactly like a <literal>create-next</literal> URL 
described earlier. The 
+                response of this POST would also return a new 
<literal>msg-create-next</literal>
+                header. The client can continue to generate its own 
DUPLICATE_DETECTION_ID, or 
+                use the new URL returned via the 
<literal>msg-create-nex</literal>t header.
+            </para>
+
+            <para>The advantage of this approach is that the client does not 
have to
+                repost the message. It also only has to come up with a unique
+                <literal>DUPLICATE_DETECTION_ID</literal> once.
+            </para>
+        </section>
+
+        <section>
+            <title>Persistent Messages</title>
+
+            <para>By default, posted messages are not durable and will not be
+                persisted in HornetQ's journal. You can create durable 
messages by
+                modifying the default configuration as expressed in Chapter 2 
so that
+                all messages are persisted when sent. Alternatively, you can 
set a URL
+                query parameter called <literal>durable</literal> to true when 
you post
+                your messages to the URLs returned in the 
<literal>msg-create</literal>,
+                <literal>msg-create-with-id</literal>, or 
<literal>msg-create-next</literal>
+                headers. here's an example of that.
+            </para>
+
+            <programlisting>
+POST /queues/jms.queue.bar/create?durable=true
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone4&lt;/item>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order></programlisting>
+        </section>
+
+        <section>
+            <title>TTL, Expiration and Priority</title>
+
+            <para>You can set the time to live, expiration, and/or the 
priority of
+                the message in the queue or topic by setting an additional 
query
+                parameter. The <literal>expiration</literal> query parameter 
is an long
+                specify the time in milliseconds since epoch (a long date). The
+                <literal>ttl</literal> query parameter is a time in 
milliseconds you
+                want the message active. The <literal>priority</literal> is 
another
+                query parameter with an integer value between 0 and 9 
expressing the
+                priority of the message. i.e.:
+            </para>
+
+            <programlisting>
+POST /queues/jms.queue.bar/create?expiration=30000&amp;priority=3
+Host: example.com
+Content-Type: application/xml
+
+&lt;order>
+   &lt;name>Bill&lt;/name>
+   &lt;item>iPhone4&lt;/item>
+   &lt;cost>$199.99&lt;/cost>
+&lt;/order></programlisting>
+        </section>
+    </section>
+
+    <section id="message-pull">
+        <title>Consuming Messages via Pull</title>
+
+        <para>There are two different ways to consume messages from a topic or
+            queue. You can wait and have the messaging server push them to 
you, or you
+            can continuously poll the server yourself to see if messages are
+            available. This chapter discusses the latter. Consuming messages 
via a
+            pull works almost identically for queues and topics with some 
minor, but
+            important caveats. To start consuming you must create a consumer 
resource
+            on the server that is dedicated to your client. Now, this pretty 
much
+            breaks the stateless principle of REST, but after much 
prototyping, this
+            is the best way to work most effectively with HornetQ through a 
REST
+            interface.
+        </para>
+
+        <para>You create consumer resources by doing a simple POST to the URL
+            published by the <literal>msg-pull-consumers</literal>
+            response header if you are interacting with a queue, the
+            <literal>msg-pull-subscribers</literal> response header if you're
+            interacting with a topic. These headers are provided by the main 
queue or
+            topic resource discussed in <link linkend="basics">HornetQ REST 
Interface
+            Basics</link>. Doing an empty POST to one of these
+            URLs will create a consumer resource that follows an 
auto-acknowledge
+            protocol and, if you are interacting with a topic, creates a 
temporarily 
+            subscription to the topic. If you want to use the acknowledgement 
protocol
+            and/or create a durable subscription (topics only), then you must 
use the
+            form parameters 
(<literal>application/x-www-form-urlencoded</literal>)
+            described below.
+        </para>
+
+        <itemizedlist>
+            <listitem>
+                <para><literal>autoAck</literal>. A value of 
<literal>true</literal>
+                    or <literal>false</literal> can be given. This defaults to
+                    <literal>true</literal> if you do not pass this parameter.
+                </para>
+            </listitem>
+            <listitem>
+                <para><literal>durable</literal>. A value of 
<literal>true</literal>
+                    or <literal>false</literal> can be given. This defaults to
+                    <literal>false</literal> if you do not pass this parameter.
+                    Only available on topics. This specifies whether you want a
+                    durable subscription or not. A durable subscription 
persists
+                    through server restart.
+                </para>
+            </listitem>
+            <listitem>
+                <para><literal>name</literal>. This is the name of the durable
+                    subscription. If you do not provide this parameter, the 
name
+                    will be automatically generated by the server. Only usable
+                    on topics.
+                </para>
+            </listitem>
+            <listitem>
+                <para><literal>selector</literal>. This is an optional JMS 
selector
+                    string. The HornetQ REST interface adds HTTP headers to the
+                    JMS message for REST produced messages. HTTP headers are
+                    prefixed with "http_" and every '-' character is converted
+                    to a '$'.
+                </para>
+            </listitem>
+            <listitem>
+                <para><literal>idle-timeout</literal>. For a topic 
subscription,
+                    idle time in milliseconds in which the consumer connections
+                    will be closed if idle.
+                </para>
+            </listitem>
+            <listitem>
+                <para><literal>delete-when-idle</literal>. Boolean value, If
+                    true, a topic subscription will be deleted (even if it is
+                    durable) when an the idle timeout is reached.
+                </para>
+            </listitem>
+        </itemizedlist>
+
+        <note>
+            <para>If you have multiple pull-consumers active at the same time
+                on the same destination be aware that unless the
+                <literal>consumer-window-size</literal> is 0 then one consumer
+                might buffer messages while the other consumer gets none.
+            </para>
+        </note>
+
+        <section>
+            <title>Auto-Acknowledge</title>
+
+            <para>This section focuses on the auto-acknowledge protocol for
+                consuming messages via a pull. Here's a list of the response
+                headers and URLs you'll be interested in.
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>msg-pull-consumers</literal>. The URL of
+                        a factory resource for creating queue consumer
+                        resources. You will pull from these created resources.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-pull-subscriptions</literal>. The URL
+                        of a factory resource for creating topic subscription
+                        resources. You will pull from the created resources.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-consume-next</literal>. The URL you
+                        will pull the next message from. This is returned
+                        with every response.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-consumer</literal>. This is a URL
+                        pointing back to the consumer or subscription
+                        resource created for the client.
+                    </para>
+                </listitem>
+            </itemizedlist>
+
+            <section>
+                <title>Creating an Auto-Ack Consumer or Subscription</title>
+
+                <para>Here is an example of creating an auto-acknowledged
+                    queue pull consumer.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Find the pull-consumers URL by doing a HEAD or
+                            GET request to the base queue resource.
+                        </para>
+
+                        <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers
+msg-push-consumers: 
http://example.com/queues/jms.queue.bar/push-consumers</programlisting>
+                    </listitem>
+
+                    <listitem>
+                        <para>Next do an empty POST to the URL returned in the
+                            <literal>msg-pull-consumers</literal>
+                            header.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers HTTP/1.1
+Host: example.com
+
+--- response ---
+HTTP/1.1 201 Created
+Location: http://example.com/queues/jms.queue.bar/pull-consumers/auto-ack/333
+msg-consume-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/auto-ack/333/consume-next-1</programlisting>
+
+                        <para>The
+                            <literal>Location</literal>
+                            header points to the JMS
+                            consumer resource that was created on the server. 
It is good to
+                            remember this URL, although, as you'll see later, 
it is
+                            transmitted with each response just to remind you.
+                        </para>
+                    </listitem>
+                </orderedlist>
+
+                <para>Creating an auto-acknowledged consumer for a topic is 
pretty
+                    much the same. Here's an example of creating a durable
+                    auto-acknowledged topic pull subscription.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Find the
+                            <literal>pull-subscriptions</literal>
+                            URL by doing
+                            a HEAD or GET request to the base topic resource
+                        </para>
+
+                        <programlisting>
+HEAD /topics/jms.topic.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/topics/jms.topic.foo/create
+msg-pull-subscriptions: 
http://example.com/topics/jms.topic.foo/pull-subscriptions
+msg-push-subscriptions: 
http://example.com/topics/jms.topic.foo/push-subscriptions</programlisting>
+                    </listitem>
+
+                    <listitem>
+                        <para>Next do a POST to the URL returned in the
+                            <literal>msg-pull-subscriptions</literal>
+                            header passing in a <literal>true</literal>
+                            value for the <literal>durable</literal>
+                            form parameter.
+                        </para>
+
+                        <programlisting>
+POST /topics/jms.topic.foo/pull-subscriptions HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+durable=true
+
+--- Response ---
+HTTP/1.1 201 Created
+Location: 
http://example.com/topics/jms.topic.foo/pull-subscriptions/auto-ack/222
+msg-consume-next:
+http://example.com/topics/jms.topic.foo/pull-subscriptions/auto-ack/222/consume-next-1</programlisting>
+
+                        <para>The
+                            <literal>Location</literal>
+                            header points to the JMS
+                            subscription resource that was created on the 
server. It is good
+                            to remember this URL, although, as you'll see 
later, it is
+                            transmitted with each response just to remind you.
+                        </para>
+                    </listitem>
+                </orderedlist>
+            </section>
+
+            <section>
+                <title>Consuming Messages</title>
+
+                <para>After you have created a consumer resource, you are 
ready to
+                    start pulling messages from the server. Notice that when 
you created
+                    the consumer for either the queue or topic, the response 
contained a
+                    <literal>msg-consume-next</literal> response header. POST 
to the URL
+                    contained within this header to consume the next message 
in the queue
+                    or topic subscription. A successful POST causes the server 
to extract
+                    a message from the queue or topic subscription, 
acknowledge it, and
+                    return it to the consuming client. If there are no 
messages in the
+                    queue or topic subscription, a 503 (Service Unavailable) 
HTTP code is
+                    returned.
+                </para>
+
+                <warning>
+                    <para>For both successful and unsuccessful posts to the
+                        msg-consume-next URL, the response will contain a new
+                        msg-consume-next header. You must ALWAYS use this new 
URL returned
+                        within the new msg-consume-next header to consume new
+                        messages.
+                    </para>
+                </warning>
+
+                <para>Here's an example of pulling multiple messages from the 
consumer
+                    resource.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Do a POST on the msg-consume-next URL that was 
returned with
+                            the consumer or subscription resource discussed 
earlier.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/consume-next-1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+Content-Type: application/xml
+msg-consume-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-2
+msg-consumer: http://example.com/queues/jms.queue.bar/pull-consumers/333
+
+&lt;order>...&lt;/order></programlisting>
+
+                        <para>The POST returns the message consumed from the 
queue. It
+                            also returns a new msg-consume-next link. Use this 
new link to get
+                            the next message. Notice also a msg-consumer 
response header is
+                            returned. This is a URL that points back to the 
consumer or
+                            subscription resource. You will need that to clean 
up your
+                            connection after you are finished using the queue 
or topic.
+                        </para>
+                    </listitem>
+
+                    <listitem>
+                        <para>The POST returns the message consumed from the 
queue. It
+                            also returns a new msg-consume-next link. Use this 
new link to get
+                            the next message.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/consume-next-2
+Host: example.com
+
+--- Response ---
+Http/1.1 503 Service Unavailable
+Retry-After: 5
+msg-consume-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-2</programlisting>
+
+                        <para>In this case, there are no messages in the 
queue, so we get
+                            a 503 response back. As per the HTTP 1.1 spec, a 
503 response may
+                            return a Retry-After head specifying the time in 
seconds that you
+                            should retry a post. Also notice, that another new
+                            msg-consume-next URL is present. Although it 
probably is the same
+                            URL you used last post, get in the habit of using 
URLs returned in
+                            response headers as future versions of HornetQ 
REST might be
+                            redirecting you or adding additional data to the 
URL after
+                            timeouts like this.
+                        </para>
+                    </listitem>
+
+                    <listitem>
+                        <para>POST to the URL within the last
+                            <literal>msg-consume-next</literal>
+                            to get the next
+                            message.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/consume-next-2
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+Content-Type: application/xml
+msg-consume-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-3
+
+&lt;order>...&lt;/order></programlisting>
+                    </listitem>
+                </orderedlist>
+            </section>
+
+            <section>
+                <title>Recovering From Network Failures</title>
+
+                <para>If you experience a network failure and do not know if 
your post
+                    to a msg-consume-next URL was successful or not, just 
re-do your POST.
+                    A POST to a msg-consume-next URL is idempotent, meaning 
that it will
+                    return the same result if you execute on any one 
msg-consume-next URL
+                    more than once. Behind the scenes, the consumer resource 
caches the
+                    last consumed message so that if there is a message 
failure and you do
+                    a re-post, the cached last message will be returned (along 
with a new
+                    msg-consume-next URL). This is the reason why the protocol 
always
+                    requires you to use the next new msg-consume-next URL 
returned with
+                    each response. Information about what state the client is 
in is
+                    embedded within the actual URL.
+                </para>
+            </section>
+
+            <section>
+                <title>Recovering From Client or Server Crashes</title>
+
+                <para>If the server crashes and you do a POST to the 
msg-consume-next
+                    URL, the server will return a 412 (Preconditions Failed) 
response
+                    code. This is telling you that the URL you are using is 
out of sync
+                    with the server. The response will contain a new 
msg-consume-next
+                    header to invoke on.
+                </para>
+
+                <para>If the client crashes there are multiple ways you can 
recover.
+                    If you have remembered the last msg-consume-next link, you 
can just
+                    re-POST to it. If you have remembered the consumer 
resource URL, you
+                    can do a GET or HEAD request to obtain a new 
msg-consume-next URL. If
+                    you have created a topic subscription using the name 
parameter
+                    discussed earlier, you can re-create the consumer. 
Re-creation will
+                    return a msg-consume-next URL you can use. If you cannot 
do any of
+                    these things, you will have to create a new consumer.
+                </para>
+
+                <para>The problem with the auto-acknowledge protocol is that 
if the
+                    client or server crashes, it is possible for you to skip 
messages. The
+                    scenario would happen if the server crashes after 
auto-acknowledging a
+                    message and before the client receives the message. If you 
want more
+                    reliable messaging, then you must use the acknowledgement
+                    protocol.
+                </para>
+            </section>
+        </section>
+
+        <section>
+            <title>Manual Acknowledgement</title>
+
+            <para>The manual acknowledgement protocol is similar to the 
auto-ack
+                protocol except there is an additional round trip to the 
server to tell
+                it that you have received the message and that the server can 
internally
+                ack the message. Here is a list of the response headers you 
will be
+                interested in.
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>msg-pull-consumers</literal>. The URL of a 
factory resource for creating queue
+                        consumer
+                        resources. You will pull from these created resources
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-pull-subscriptions</literal>. The URL 
of a factory resource for creating topic
+                        subscription resources. You will pull from the created
+                        resources.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-acknowledge-next</literal>. URL used to 
obtain the next message in the queue or
+                        topic
+                        subscription. It does not acknowledge the message 
though.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-acknowledgement</literal>. URL used to 
acknowledge a message.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>msg-consumer</literal>. This is a URL 
pointing back to the consumer or subscription
+                        resource created for the client.
+                    </para>
+                </listitem>
+            </itemizedlist>
+
+            <section>
+                <title>Creating manually-acknowledged consumers or
+                    subscriptions
+                </title>
+
+                <para>Here is an example of creating an auto-acknowledged 
queue pull
+                    consumer.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Find the pull-consumers URL by doing a HEAD or 
GET request
+                            to the base queue resource.
+                        </para>
+
+                        <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers
+msg-push-consumers: 
http://example.com/queues/jms.queue.bar/push-consumers</programlisting>
+                    </listitem>
+
+                    <listitem>
+                        <para>Next do a POST to the URL returned in the
+                            <literal>msg-pull-consumers</literal>
+                            header passing in a
+                            <literal>false</literal>
+                            value to the
+                            <literal>autoAck</literal>
+                            form parameter .
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+autoAck=false
+
+--- response ---
+HTTP/1.1 201 Created
+Location: 
http://example.com/queues/jms.queue.bar/pull-consumers/acknowledged/333
+msg-acknowledge-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/acknowledged/333/acknowledge-next-1</programlisting>
+
+                        <para>The
+                            <literal>Location</literal>
+                            header points to the JMS
+                            consumer resource that was created on the server. 
It is good to
+                            remember this URL, although, as you'll see later, 
it is
+                            transmitted with each response just to remind you.
+                        </para>
+                    </listitem>
+                </orderedlist>
+
+                <para>Creating an manually-acknowledged consumer for a topic 
is pretty
+                    much the same. Here's an example of creating a durable
+                    manually-acknowledged topic pull subscription.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Find the
+                            <literal>pull-subscriptions</literal>
+                            URL by doing
+                            a HEAD or GET request to the base topic resource
+                        </para>
+
+                        <programlisting>
+HEAD /topics/jms.topic.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/topics/jms.topic.foo/create
+msg-pull-subscriptions: 
http://example.com/topics/jms.topic.foo/pull-subscriptions
+msg-push-subscriptions: 
http://example.com/topics/jms.topic.foo/push-subscriptions</programlisting>
+                    </listitem>
+
+                    <listitem>
+                        <para>Next do a POST to the URL returned in the
+                            <literal>msg-pull-subscriptions</literal>
+                            header passing in a <literal>true</literal>
+                            value for the <literal>durable</literal>
+                            form parameter and a <literal>false</literal>
+                            value to the <literal>autoAck</literal>
+                            form parameter.
+                        </para>
+
+                        <programlisting>
+POST /topics/jms.topic.foo/pull-subscriptions HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+durable=true&amp;autoAck=false
+
+--- Response ---
+HTTP/1.1 201 Created
+Location: 
http://example.com/topics/jms.topic.foo/pull-subscriptions/acknowledged/222
+msg-acknowledge-next:
+http://example.com/topics/jms.topic.foo/pull-subscriptions/acknowledged/222/consume-next-1</programlisting>
+
+                        <para>The
+                            <literal>Location</literal> header points to the 
JMS
+                            subscription resource that was created on the 
server. It is good
+                            to remember this URL, although, as you'll see 
later, it is
+                            transmitted with each response just to remind you.
+                        </para>
+                    </listitem>
+                </orderedlist>
+            </section>
+
+            <section>
+                <title>Consuming and Acknowledging a Message</title>
+
+                <para>After you have created a consumer resource, you are 
ready to
+                    start pulling messages from the server. Notice that when 
you created
+                    the consumer for either the queue or topic, the response 
contained a
+                    <literal>msg-acknowledge-next</literal> response header. 
POST to the
+                    URL contained within this header to consume the next 
message in the
+                    queue or topic subscription. If there are no messages in 
the queue or
+                    topic subscription, a 503 (Service Unavailable) HTTP code 
is returned.
+                    A successful POST causes the server to extract a message 
from the
+                    queue or topic subscription and return it to the consuming 
client. It
+                    does not acknowledge the message though. The response will 
contain the
+                    <literal>acknowledgement</literal>
+                    header which you will use to
+                    acknowledge the message.
+                </para>
+
+                <para>Here's an example of pulling multiple messages from the 
consumer
+                    resource.
+                </para>
+
+                <orderedlist>
+                    <listitem>
+                        <para>Do a POST on the msg-acknowledge-next URL that 
was returned
+                            with the consumer or subscription resource 
discussed
+                            earlier.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/consume-next-1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+Content-Type: application/xml
+msg-acknowledgement:
+http://example.com/queues/jms.queue.bar/pull-consumers/333/acknowledgement/2
+msg-consumer: http://example.com/queues/jms.queue.bar/pull-consumers/333
+
+&lt;order>...&lt;/order></programlisting>
+
+                        <para>The POST returns the message consumed from the 
queue. It
+                            also returns 
a<literal>msg-acknowledgemen</literal>t link. You
+                            will use this new link to acknowledge the message. 
Notice also a
+                            <literal>msg-consumer</literal> response header is 
returned. This
+                            is a URL that points back to the consumer or 
subscription
+                            resource. You will need that to clean up your 
connection after you
+                            are finished using the queue or topic.
+                        </para>
+                    </listitem>
+
+                    <listitem>
+                        <para>Acknowledge or unacknowledge the message by 
doing a POST to
+                            the URL contained in the 
<literal>msg-acknowledgement</literal>
+                            header. You must pass an 
<literal>acknowledge</literal>
+                            form parameter set to <literal>true</literal>
+                            or <literal>false</literal> depending on whether 
you want to
+                            acknowledge or unacknowledge the message on the 
server.
+                        </para>
+
+                        <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/acknowledgement/2
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+acknowledge=true
+
+--- Response ---
+Http/1.1 200 Ok
+msg-acknowledge-next:
+http://example.com/queues/jms.queue.bar/pull-consumers/333/acknowledge-next-2</programlisting>
+
+                        <para>Whether you acknowledge or unacknowledge the 
message, the
+                            response will contain a new msg-acknowledge-next 
header that you
+                            must use to obtain the next message.
+                        </para>
+                    </listitem>
+                </orderedlist>
+            </section>
+
+            <section>
+                <title>Recovering From Network Failures</title>
+
+                <para>If you experience a network failure and do not know if 
your post
+                    to a
+                    <literal>msg-acknowledge-next</literal>
+                    or
+                    <literal>msg-acknowledgement</literal> URL was successful 
or not, just
+                    re-do your POST. A POST to one of these URLs is 
idempotent, meaning
+                    that it will return the same result if you re-post. Behind 
the scenes,
+                    the consumer resource keeps track of its current state. If 
the last
+                    action was a call 
to<literal>msg-acknowledge-next</literal>, it will
+                    have the last message cached, so that if a re-post is 
done, it will
+                    return the message again. Same goes with re-posting to
+                    <literal>msg-acknowledgement</literal>. The server 
remembers its last
+                    state and will return the same results. If you look at the 
URLs you'll
+                    see that they contain information about the expected 
current state of
+                    the server. This is how the server knows what the client is
+                    expecting.
+                </para>
+            </section>
+
+            <section>
+                <title>Recovering From Client or Server Crashes</title>
+
+                <para>If the server crashes and while you are doing a POST to 
the
+                    <literal>msg-acknowledge-next</literal> URL, just re-post. 
Everything
+                    should reconnect all right. On the other hand, if the 
server crashes
+                    while you are doing a POST 
to<literal>msg-acknowledgement</literal>,
+                    the server will return a 412 (Preconditions Failed) 
response code.
+                    This is telling you that the URL you are using is out of 
sync with the
+                    server and the message you are acknowledging was probably 
re-enqueued.
+                    The response will contain a new 
<literal>msg-acknowledge-next</literal>
+                    header to invoke on.
+                </para>
+
+                <para>As long as you have "bookmarked" the consumer resource 
URL
+                    (returned from <literal>Location</literal> header on a 
create, or the
+                    <literal>msg-consumer</literal> header), you can recover 
from client
+                    crashes by doing a GET or HEAD request on the consumer 
resource to
+                    obtain what state you are in. If the consumer resource is 
expecting
+                    you to acknowledge a message, it will return a
+                    <literal>msg-acknowledgement</literal> header in the 
response. If the
+                    consumer resource is expecting you to pull for the next 
message, the
+                    <literal>msg-acknowledge-next</literal> header will be in 
the
+                    response. With manual acknowledgement you are pretty much 
guaranteed
+                    to avoid skipped messages. For topic subscriptions that 
were created
+                    with a name parameter, you do not have to "bookmark" the 
returned URL.
+                    Instead, you can re-create the consumer resource with the 
same exact
+                    name. The response will contain the same information as if 
you did a
+                    GET or HEAD request on the consumer resource.
+                </para>
+            </section>
+        </section>
+
+        <section>
+            <title>Blocking Pulls with Accept-Wait</title>
+
+            <para>Unless your queue or topic has a high rate of message flowing
+                though it, if you use the pull protocol, you're going to be 
receiving a
+                lot of 503 responses as you continuously pull the server for 
new
+                messages. To alleviate this problem, the HornetQ REST 
interface provides
+                the <literal>Accept-Wait</literal> header. This is a generic 
HTTP
+                request header that is a hint to the server for how long the 
client is
+                willing to wait for a response from the server. The value of 
this header
+                is the time in seconds the client is willing to block for. You 
would
+                send this request header with your pull requests. Here's an
+                example:
+            </para>
+
+            <programlisting>
+POST /queues/jms.queue.bar/pull-consumers/consume-next-2
+Host: example.com
+Accept-Wait: 30
+
+--- Response ---
+HTTP/1.1 200 Ok
+Content-Type: application/xml
+msg-consume-next: 
http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-3
+
+&lt;order>...&lt;/order></programlisting>
+
+            <para>In this example, we're posting to a msg-consume-next URL and
+                telling the server that we would be willing to block for 30
+                seconds.
+            </para>
+        </section>
+
+        <section>
+            <title>Clean Up Your Consumers!</title>
+
+            <para>When the client is done with its consumer or topic 
subscription it
+                should do an HTTP DELETE call on the consumer URL passed back 
from the
+                Location header or the msg-consumer response header. The 
server will
+                time out a consumer with the value of
+                <literal>consumer-session-timeout-seconds</literal> configured 
from
+                <link linkend="configuration">REST configuration</link>, so you
+                don't have to clean up if you don't want to, but if you are a 
good kid,
+                you will clean up your messes. A consumer timeout for durable
+                subscriptions will not delete the underlying durable JMS 
subscription
+                though, only the server-side consumer resource (and underlying 
JMS
+                session).
+            </para>
+        </section>
+    </section>
+
+
+    <section id="message-push">
+        <title>Pushing Messages</title>
+
+        <para>You can configure the HornetQ REST server to push messages to a
+            registered URL either remotely through the REST interface, or by 
creating
+            a pre-configured XML file for the HornetQ REST server to load at 
boot
+            time.
+        </para>
+
+        <section>
+            <title>The Queue Push Subscription XML</title>
+
+            <para>Creating a push consumer for a queue first involves creating 
a
+                very simple XML document. This document tells the server if 
the push
+                subscription should survive server reboots (is it durable). It 
must
+                provide a URL to ship the forwarded message to. Finally, you 
have to
+                provide authentication information if the final endpoint 
requires
+                authentication. Here's a simple example:
+            </para>
+
+            <programlisting>
+&lt;push-registration>
+   &lt;durable>false&lt;/durable>
+   &lt;selector>&lt;![CDATA[
+   SomeAttribute > 1
+   ]]&gt;
+   &lt;/selector>
+   &lt;link rel="push" href="http://somewhere.com"; type="application/json" 
method="PUT"/>
+   &lt;maxRetries>5&lt;/maxRetries>
+   &lt;retryWaitMillis>1000&lt;/retryWaitMillis>
+   &lt;disableOnFailure>true&lt;/disableOnFailure>
+&lt;/push-registration></programlisting>
+
+            <para>The <literal>durable</literal> element specifies whether the
+                registration should be saved to disk so that if there is a 
server
+                restart, the push subscription will still work. This element 
is not
+                required. If left out it defaults to<literal>false</literal>. 
If
+                durable is set to true, an XML file for the push subscription 
will be
+                created within the directory specified by the
+                <literal>queue-push-store-dir</literal> config variable 
defined in
+                Chapter 2 (<literal>topic-push-store-dir</literal> for topics).
+            </para>
+
+            <para>The <literal>selector</literal> element is optional and 
defines a
+                JMS message selector. You should enclose it within CDATA 
blocks as some
+                of the selector characters are illegal XML.
+            </para>
+
+            <para>The <literal>maxRetries</literal> element specifies how many 
times
+                a the server will try to push a message to a URL if there is a
+                connection failure.
+            </para>
+
+            <para>The <literal>retryWaitMillis</literal> element specifies how 
long
+                to wait before performing a retry.
+            </para>
+
+            <para>The
+                <literal>disableOnFailure</literal> element, if set to true,
+                will disable the registration if all retries have failed. It 
will not
+                disable the connection on non-connection-failure issues (like 
a bad
+                request for instance). In these cases, the dead letter queue 
logic of
+                HornetQ will take over.
+            </para>
+
+            <para>The <literal>link</literal> element specifies the basis of 
the
+                interaction. The <literal>href</literal> attribute contains 
the URL you
+                want to interact with. It is the only required attribute. The
+                <literal>type</literal> attribute specifies the content-type 
of what the
+                push URL is expecting. The <literal>method</literal> attribute 
defines
+                what HTTP method the server will use when it sends the message 
to the
+                server. If it is not provided it defaults to POST. The
+                <literal>rel</literal> attribute is very important and the 
value of it
+                triggers different behavior. Here's the values a rel attribute 
can
+                have:
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para><literal>destination</literal>. The href URL is 
assumed to be a queue or topic resource of
+                        another HornetQ REST server. The push registration 
will initially
+                        do a HEAD request to this URL to obtain a 
msg-create-with-id
+                        header. It will use this header to push new messages 
to the
+                        HornetQ REST endpoint reliably. Here's an example:
+                    </para>
+
+                    <programlisting>
+&lt;push-registration>
+   &lt;link rel="destination" 
href="http://somewhere.com/queues/jms.queue.foo"/>
+&lt;/push-registration></programlisting>
+                </listitem>
+                <listitem>
+                    <para><literal>template</literal>. In this case, the 
server is expecting the link element's
+                        href attribute to be a URL expression. The URL 
expression must
+                        have one and only one URL parameter within it. The 
server will use
+                        a unique value to create the endpoint URL. Here's an
+                        example:
+                    </para>
+
+                    <programlisting>
+&lt;push-registration>
+   &lt;link rel="template" href="http://somewhere.com/resources/{id}/messages"; 
method="PUT"/>
+&lt;/push-registration></programlisting>
+
+                    <para>In this example, the {id} sub-string is the one and 
only one
+                        URL parameter.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para><literal>user defined</literal>. If the rel 
attributes is not destination or template (or is
+                        empty or missing), then the server will send an HTTP 
message to
+                        the href URL using the HTTP method defined in the 
method
+                        attribute. Here's an example:
+                    </para>
+
+                    <programlisting>
+&lt;push-registration>
+   &lt;link href="http://somewhere.com"; type="application/json" method="PUT"/>
+&lt;/push-registration></programlisting>
+                </listitem>
+            </itemizedlist>
+        </section>
+
+        <section>
+            <title>The Topic Push Subscription XML</title>
+
+            <para>The push XML for a topic is the same except the root element 
is
+                push-topic-registration. (Also remember the 
<literal>selector</literal>
+                element is optional). The rest of the document is the same. 
Here's an
+                example of a template registration:
+            </para>
+
+            <programlisting>
+&lt;push-topic-registration>
+   &lt;durable>true&lt;/durable>
+   &lt;selector>&lt;![CDATA[
+   SomeAttribute > 1
+   ]]&gt;
+   &lt;/selector>
+   &lt;link rel="template" href="http://somewhere.com/resources/{id}/messages"; 
method="POST"/>
+&lt;/push-topic registration></programlisting>
+        </section>
+
+        <section>
+            <title>Creating a Push Subscription at Runtime</title>
+
+            <para>Creating a push subscription at runtime involves getting the
+                factory resource URL from the msg-push-consumers header, if the
+                destination is a queue, or msg-push-subscriptions header, if 
the
+                destination is a topic. Here's an example of creating a push
+                registration for a queue:
+            </para>
+
+            <orderedlist>
+                <listitem>
+                    <para>First do a HEAD request to the queue resource:</para>
+
+                    <programlisting>
+HEAD /queues/jms.queue.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/queues/jms.queue.bar/create
+msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers
+msg-push-consumers: 
http://example.com/queues/jms.queue.bar/push-consumers</programlisting>
+                </listitem>
+
+                <listitem>
+                    <para>Next POST your subscription XML to the URL returned 
from
+                        msg-push-consumers header
+                    </para>
+
+                    <programlisting>
+POST /queues/jms.queue.bar/push-consumers
+Host: example.com
+Content-Type: application/xml
+
+&lt;push-registration>
+   &lt;link rel="destination" 
href="http://somewhere.com/queues/jms.queue.foo"/>
+&lt;/push-registration>
+
+--- Response ---
+HTTP/1.1 201 Created
+Location: 
http://example.com/queues/jms.queue.bar/push-consumers/1-333-1212</programlisting>
+
+                    <para>The Location header contains the URL for the created 
resource.
+                        If you want to unregister this, then do a HTTP DELETE 
on this
+                        URL.
+                    </para>
+                </listitem>
+            </orderedlist>
+
+            <para>Here's an example of creating a push registration for a
+                topic:
+            </para>
+
+            <orderedlist>
+                <listitem>
+                    <para>First do a HEAD request to the topic resource:</para>
+
+                    <programlisting>
+HEAD /topics/jms.topic.bar HTTP/1.1
+Host: example.com
+
+--- Response ---
+HTTP/1.1 200 Ok
+msg-create: http://example.com/topics/jms.topic.bar/create
+msg-pull-subscriptions: 
http://example.com/topics/jms.topic.bar/pull-subscriptions
+msg-push-subscriptions: 
http://example.com/topics/jms.topic.bar/push-subscriptions</programlisting>
+                </listitem>
+
+                <listitem>
+                    <para>Next POST your subscription XML to the URL returned 
from
+                        msg-push-subscriptions header
+                    </para>
+
+                    <programlisting>
+POST /topics/jms.topic.bar/push-subscriptions
+Host: example.com
+Content-Type: application/xml
+
+&lt;push-registration>
+   &lt;link rel="template" href="http://somewhere.com/resources/{id}"/>
+&lt;/push-registration>
+
+--- Response ---
+HTTP/1.1 201 Created
+Location: 
http://example.com/topics/jms.topic.bar/push-subscriptions/1-333-1212</programlisting>
+
+                    <para>The Location header contains the URL for the created 
resource.
+                        If you want to unregister this, then do a HTTP DELETE 
on this
+                        URL.
+                    </para>
+                </listitem>
+            </orderedlist>
+        </section>
+
+        <section>
+            <title>Creating a Push Subscription by Hand</title>
+
+            <para>You can create a push XML file yourself if you do not want 
to go
+                through the REST interface to create a push subscription. 
There is some
+                additional information you need to provide though. First, in 
the root
+                element, you must define a unique id attribute. You must also 
define a
+                destination element to specify the queue you should register a 
consumer
+                with. For a topic, the destination element is the name of the
+                subscription that will be created. For a topic, you must also 
specify the
+                topic name within the topic element.
+            </para>
+
+            <para>Here's an example of a hand-created queue registration. This 
file
+                must go in the directory specified by the queue-push-store-dir 
config
+                variable defined in Chapter 2:
+            </para>
+
+            <programlisting>
+&lt;push-registration id="111">
+   &lt;destination>jms.queue.bar&lt;/destination>
+   &lt;durable>true&lt;/durable>
+   &lt;link rel="template" href="http://somewhere.com/resources/{id}/messages"; 
method="PUT"/>
+&lt;/push-registration></programlisting>
+
+            <para>Here's an example of a hand-created topic registration. This 
file
+                must go in the directory specified by the topic-push-store-dir 
config
+                variable defined in Chapter 2:
+            </para>
+
+            <programlisting>
+&lt;push-topic-registration id="112">
+   &lt;destination>my-subscription-1&lt;/destination
+   &lt;durable>true&lt;/durable>
+   &lt;link rel="template" href="http://somewhere.com/resources/{id}/messages"; 
method="PUT"/>
+   &lt;topic>jms.topic.foo&lt;/topic>
+&lt;/push-topic-registration></programlisting>
+        </section>
+
+        <section>
+

<TRUNCATED>

Reply via email to