blob: cb7b44d22a8a5f0f82c12b3e23db9ca703d51141 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Architecture
-->
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<meta content="ActiveMQ's next generation of messaging" name="description"/>
<meta content="messaging,stomp,jms,activemq,apollo" name="keywords"/>
<meta content="Apollo" name="author"/>
<script src="../scripts/jquery.js"></script>
<link type="text/css" rel="stylesheet" href="../styles/impact/css/pygmentize.css"/>
<link type="text/css" rel="stylesheet" href="../styles/impact/css/site.css"/>
<title></title>
</head>
<body>
<div id="navigation">
<div class="wrapper">
<ul>
<li><a href="../index.html">Apollo 1.7.1</a></li>
<li><a href="../community/developers.html">Developers</a></li>
<li><a href="../community/index.html">Community</a></li>
<li><a href="../download.html">Download</a></li>
</ul> <div></div>
</div>
</div>
<div id="content">
<div class="wrapper">
<h1 id = "Apollo_1_7_1_STOMP_Protocol_Manual">Apollo 1.7.1 STOMP Protocol Manual</h1>
<p><div class="toc"><ul style="list-style:none;">
<li><a href="#Using_the_STOMP_Protocol">Using the STOMP Protocol</a></li>
<li><ul style="list-style:none;">
<li><a href="#Stomp_Protocol_Options">Stomp Protocol Options</a></li>
<li><a href="#Client_Libraries">Client Libraries</a></li>
<li><a href="#Connecting">Connecting</a></li>
<li><a href="#Destination_Types">Destination Types</a></li>
<li><a href="#Topic_Retained_Messages">Topic Retained Messages</a></li>
<li><a href="#Reliable_Messaging">Reliable Messaging</a></li>
<li><a href="#Message_Expiration">Message Expiration</a></li>
<li><a href="#Subscription_Flow_Control">Subscription Flow Control</a></li>
<li><a href="#Topic_Durable_Subscriptions">Topic Durable Subscriptions</a></li>
<li><a href="#Browsing_Subscriptions">Browsing Subscriptions</a></li>
<li><a href="#Queue_Message_Sequences">Queue Message Sequences</a></li>
<li><a href="#Using_Queue_Browsers_to_Implement_Durable_Topic_Subscriptions">Using Queue Browsers to Implement Durable Topic Subscriptions</a></li>
<li><a href="#Exclusive_Subscriptions">Exclusive Subscriptions</a></li>
<li><a href="#Message_Groups">Message Groups</a></li>
<li><a href="#Temporary_Destinations">Temporary Destinations</a></li>
<li><a href="#Destination_Wildcards">Destination Wildcards</a></li>
<li><a href="#Composite_Destinations">Composite Destinations</a></li>
<li><a href="#Message_Selectors">Message Selectors</a></li>
<li><a href="#Destination_Name_Restrictions">Destination Name Restrictions</a></li>
</ul></li>
</ul></div></p>
<h2 id = "Using_the_STOMP_Protocol">Using the STOMP Protocol</h2>
<p>Clients can connect to Apollo using the
<a href="http://stomp.github.com/">STOMP</a> protocol. STOMP provides an interoperable
messaging wire level protocol that allows any STOMP clients can communicate
with any STOMP message broker. It aims to provide easy and widespread
messaging interoperability among many languages, platforms and brokers.</p>
<p>Apollo supports the following versions of the STOMP specification: </p>
<ul>
<li><a href="http://stomp.github.com/stomp-specification-1.0.html">STOMP 1.0</a></li>
<li><a href="http://stomp.github.com/stomp-specification-1.1.html">STOMP 1.1</a></li>
<li><a href="http://stomp.github.com/stomp-specification-1.2.html">STOMP 1.2</a></li>
</ul>
<p>The specification is short and simple to read, it is highly recommend that users
to get familiar with it before using one of the many available client libraries.</p>
<h3 id = "Stomp_Protocol_Options">Stomp Protocol Options</h3>
<p>You can use the <code>stomp</code> configuration element within the <code>connector</code> element
in the <code>apollo.xml</code> configuration file to change the default settings used
in the STOMP protocol implementation. The <code>stomp</code> element supports the
following configuration attributes:</p>
<ul>
<li><code>buffer_size</code> : How much each producer or subscription will buffer between
the client and the broker. If not set, it will be auto tuned between <code>640k</code>
and <code>20k</code> depending on the number of connections open on the broker.</li>
<li><code>add_user_header</code> : Name of the header which will be added to every received
message received. The value of the header will be set to the id of user that
sent the message. Not set by default.</li>
<li><code>add_timestamp_header</code> : Name of the header which will be added to every received
message received. The value of the header will be set to the time the message
was received. The time will be represented as the number of milliseconds elapsed
since the UNIX epoch in GMT. Not set by default.</li>
<li><code>add_redeliveries_header</code> : Name of the header which will be added to messages
sent to consumers if the messages has been redelivered. The value of the header
will be set to the number of times the message has been redeliverd. Not set
by default.</li>
<li><code>max_header_length</code> : The maximum allowed length of a STOMP header. Defaults
to <code>10k</code>.</li>
<li><code>max_headers</code> : The maximum number of allowed headers in a frame. Defaults
to 1000.</li>
<li><code>max_data_length</code> : The maximum size of the body portion of a STOMP frame. <br/>
Defaults to <code>100M</code>.</li>
<li><code>die_delay</code> : The amount of time to delay in milliseconds after an <code>ERROR</code>
message is sent to the client and the socket is closed.</li>
</ul>
<p>The stomp configuration element can also be used to control how the destination
headers are parsed and interpreted. The supported attributes are:</p>
<ul>
<li><code>queue_prefix</code> : Defaults to <code>/queue/</code></li>
<li><code>topic_prefix</code> : Defaults to <code>/topic/</code></li>
<li><code>path_separator</code> : Defaults to <code>.</code></li>
<li><code>destination_separator</code> : Defaults to <code>,</code></li>
<li><code>any_child_wildcard</code> : Defaults to <code>*</code></li>
<li><code>regex_wildcard_start</code> : Defaults to <code>{</code></li>
<li><code>regex_wildcard_end</code> : Defaults to <code>}</code></li>
<li><code>any_descendant_wildcard</code> : Defaults to <code>**</code></li>
</ul>
<p>It also supports nested <code>add_user_header</code> elements to more finely control how
user headers are added to received STOMP messages. The <code>add_user_header</code> element
should contain the name of the header to set on the STOMP message. It also
supports the following attributes:</p>
<ul>
<li><code>separator</code> : If user has multiple principles which match, this separator
will be used to delimit them in the header. If not set, then only the first
matching principle will be set in the header.</li>
<li><code>kind</code> : The principle kind to look for. Defaults to <code>*</code> (matches all
principle kinds)</li>
</ul>
<p>Example:</p>
<div class="syntax"><pre name='code' class='brush: xml; gutter: false;'><code>
&lt;connector id=&quot;tcp&quot; bind=&quot;tcp://0.0.0.0:61613&quot;&gt;
&lt;stomp max_header_length=&quot;10000&quot;&gt;
&lt;add_user_header separator=&quot;,&quot;&gt;user&lt;/add_user_header&gt;
&lt;/stomp&gt;
&lt;/connector&gt;
</code></pre></div>
<h3 id = "Client_Libraries">Client Libraries</h3>
<p>There are many open source STOMP clients for different platforms and
languages. You can find a full listing of available clients at:</p>
<ul>
<li><a href="http://stomp.github.com/implementations.html#Clients"><code>http://stomp.github.com/implementations.html#Clients</code></a></li>
</ul>
<p>The Apollo distribution ships with an <code>examples</code> directory
where you can find some simple examples of how to use some of those
clients to send and receive messages from a broker instance.</p>
<p>This section will focus on clarifying the parts of the STOMP specification
which allow servers to choose their behavior and to describe how to access
Apollo specific features.</p>
<h3 id = "Connecting">Connecting</h3>
<p>The default broker configuration secures access to the broker so that only
the <code>admin</code> user can connect. The default password for the <code>admin</code> user
is <code>password</code>.</p>
<p>Example STOMP frame to connect to the broker:</p>
<pre><code>CONNECT
login:admin
passcode:password
^@</code></pre>
<p>STOMP 1.0 clients don't specify which virtual host they are connecting to so
the broker connects those clients to the first virtual host defined in
it's configuration. STOMP 1.1 clients must specify a virtual host when they
connect. If no configured virtual host <code>host_name</code> matches the client's
requested host, the connection is terminated with an ERROR. Therefore,
it is critical that the virtual hosts configuration define all the
possible host names that clients may connect to host with.</p>
<h3 id = "Destination_Types">Destination Types</h3>
<p>Apollo supports three types of destinations, queues, topics, and
durable subscriptions.</p>
<p>The difference between queues and topics is how messages are delivered to
consumers. A queue will load balance it's messages over the connected
subscribers so that only one subscriber gets a message. Topics replicate
every message sent to it to all the connected subscribers. Queues hold
on to unconsumed messages even when there are no subscriptions attached,
while a topic will drop messages when there are no connected subscriptions.</p>
<p>A durable subscription allows you to create a subscription against a topic
which will queue messages even after the client disconnects. Clients
can reconnect and consume the queued message originating from the topic
at a later time.</p>
<p>If you want to send or subscribe to a queue, topic, or durable
subscription the STOMP destination should be prefixed with <code>/queue/</code>,
<code>/topic/</code> or <code>/dsub/</code> respectively.</p>
<p>Example STOMP frame sending to a queue:</p>
<pre><code>SEND
destination:/queue/a
hello queue a
^@</code></pre>
<h3 id = "Topic_Retained_Messages">Topic Retained Messages</h3>
<p>If a message sent to a Topic has the <code>retain:set</code> header, then
the message will be 'remembered' by the topic so that if a new
subscription arrives, the last retained message is sent
to the subscription. For example if you want a topic
to remember the last price published you can send a message
that looks like:</p>
<pre><code>SEND
destination:/topic/stock/IBM
retain:true
112.12
^@</code></pre>
<p>You can also send a new message with the <code>retain:remove</code> header
to have the topic forget about the last retained message.</p>
<p>Note: retained messages are not retained between broker restarts.</p>
<h3 id = "Reliable_Messaging">Reliable Messaging</h3>
<p>Apollo supports reliable messaging by allowing messages to be
persisted so that they can be recovered if there is failure which kills
the broker. Processing persistent messages has orders of magnitude more
overhead than non-persistent variety. You should only use it if your
application really needs it.</p>
<p>To have a message be persistent, the sender must add the <code>persistent:true</code>
header to the <code>SEND</code> STOMP frame. Furthermore, if you are not sending the
message in a transaction, it is recommend that you also add a <code>receipt</code>
header. Once the broker responds with a <code>RECEIPT</code> frame correlated to
the send, you are guaranteed the broker will not drop the message even if
a failure occurs.</p>
<p>Example:</p>
<pre><code>SEND
destination:/queue/a
receipt:001
hello queue a
^@</code></pre>
<p>The client should not consider the send to have succeeded until he receives
the correlated <code>RECEIPT</code> frame from the server. Example:</p>
<pre><code>RECEIPT
receipt-id:001
^@</code></pre>
<p>It is important to note that to do reliable messaging, your system will
be prone to receive duplicate messages. For example, if your sending
application dies before it receives the <code>RECEIPT</code> frame, then when it starts
up again will probably try to send the same message again which may
cause a duplicate message to get placed on the broker.</p>
<p>You should only use subscribers which use the <code>client</code> or <code>client-individual</code>
ack mode to consume reliable messages. Any messages on a queue delivered to a
client which have not been acked when the client disconnects will get
redelivered to another subscribed client.</p>
<h3 id = "Message_Expiration">Message Expiration</h3>
<p>Apollo supports expiring old messages. Unconsumed expired messages
are automatically removed from the queue. There's two way to specify
when the message will be expired. Y</p>
<p>The first way to configure the expiration is by setting the <code>expires</code> message
header. The expiration time must be specified as the number of milliseconds
since the Unix epoch.</p>
<p>Example:</p>
<pre><code>SEND
destination:/queue/a
expires:1308690148000
this message will expire on Tue Jun 21 17:02:28 EDT 2011
^@</code></pre>
<p>The first way to configure the expiration is by setting the <code>ttl</code> message
header. The ttl will be intereted to mean the number of milliseconds from
when the server receives the message. The broker will add an <code>expires</code>
header to the message on your behalf.</p>
<p>Example:</p>
<pre><code>SEND
destination:/queue/a
ttl:2000
This message will expire in 2 seconds.
^@</code></pre>
<h3 id = "Subscription_Flow_Control">Subscription Flow Control</h3>
<p>You can add a <code>credit</code> header to the <code>SUBSCRIBE</code> frame to control the
flow of messages delivered to the client. Each subscription maintains 2
credit windows which allows you to control the flow of messages either based
on number of messages sent or total number of content bytes delivered to the
client. The content bytes are the body of the frame which is usually also
set on the <code>content-length</code> header. If either of the two credit windows have
a positive value, the server will deliver messages to the client.</p>
<p>The <code>credit</code> header value is expected to use the
<code>count[,size]</code> syntax where:</p>
<ul>
<li>count: initial setting of the credit window tracking the remaining number
of messages that can be sent. Must be specified.</li>
<li>size: initial setting of the credit window tracking the remaining number
of content bytes that can be sent. Defaults to the receive buffer size of
the TCP socket which is typically 65536 bytes.</li>
</ul>
<p>If the <code>credit</code> header is not specified it has the same effect
as if it had been set to <code>credit:655360,655360</code>. This setting allows the broker
to optimally stream many small messages to the client or without overloading
the clients processing buffers.</p>
<p>As messages are sent from the server to the client, the credit windows are
reduced by the corresponding amount. When the client send <code>ACK</code> frames to the
server, the credit windows are incremented by the number of messages and content
sizes corresponding to the messages that were acknowledged.</p>
<p>Example:</p>
<pre><code>SUBSCRIBE
id:mysub
destination:/queue/foo
credit:5,0
^@</code></pre>
<p>The above example would cause the subscription to only receive at most 5
messages if the client is not sending any <code>ACK</code> messages back to the server.</p>
<p>If you need to receive more messages without acknowledging them than the
size of the credit window, you should use transactions and transactionally
<code>ACK</code> messages as they are received. A transactional ACK increases the
credit window without actually consuming the messages. If the transaction
is aborted subsequent acknowledgements of a previously acknowledged message
does not increase the credit window.</p>
<!-- The following feature seems complicated and not really that useful.-->
<!-- Commenting out as it may get removed. -->
<!--
If the `auto` option is set to `false`, then the credit windows are only
increased when the server receives `ACK` frames which contain a `credit`
header. The header value is expected to use the `count[,size]` syntax. If
`size` is specified, it defaults to 0.
Example:
SUBSCRIBE
id:mysub
destination:/queue/foo
credit:1,0,false
^@
ACK
id:mysub
message-id:id-52321
credit:1,1204
^@
You can also use the `ACK` frame to increase the credit windows sizes
without needing to acknowledge as message. To do this, don't include the
`message-id` header in the `ACK` frame. Example:
ACK
id:mysub
credit:3
^@
-->
<h3 id = "Topic_Durable_Subscriptions">Topic Durable Subscriptions</h3>
<p>A durable subscription is a queue which is subscribed to a topic so that even
if the client which created the durable subscription is not online, he can
still get a copy of all the messages sent to the topic when he comes back
online. Multiple clients can subscribe to the same durable subscription and
since it's backed by a queue, those subscribers will have the topic's messages
load balanced across them.</p>
<p>To create or reattach to a a durable subscription with STOMP, you uniquely
name the durable subscription using the <code>id</code> header on the <code>SUBSCRIBE</code> frame
and also adding a <code>persistent:true</code> header. Example:</p>
<pre><code>SUBSCRIBE
id:mysub
persistent:true
destination:/topic/foo
^@</code></pre>
<p>A standard <code>UNSUBSCRIBE</code> frame does not destroy the durable subscription, it
only disconnects the client from the durable subscription. To destroy a
durable subscription, you must once again add <code>persistent:true</code> header to the
<code>UNSUBSCRIBE</code> frame. Example:</p>
<pre><code>UNSUBSCRIBE
id:mysub
persistent:true
^@</code></pre>
<p>If the durable subscription already exists you can address it directly using
<code>/dsub/</code> prefix on the <code>destination</code> header. For example, send a message to
the previously created <code>mysub</code> durable subscription, you send the following
STOMP frame:</p>
<pre><code>SEND
destination:/dsub/mysub
hello durable sub!
^@</code></pre>
<p>Similarly, you can also subscribe to the subscription in the same way:</p>
<pre><code>SUBSCRIBE
id:0
destination:/dsub/mysub
^@</code></pre>
<p>Unlike typical STOMP subscriptions id's which are local to the STOMP client's
connection, the durable subscription id's are global across a virtual host. If
two different connections use the same durable subscription id, then messages
from the subscription will get load balanced across the two connections. If
the second connection uses a different <code>destination</code> or <code>selector</code> header,
then updates the original subscription, and the original connection will
subsequently only receive messages matching the updated destination or
selector.</p>
<h3 id = "Browsing_Subscriptions">Browsing Subscriptions</h3>
<p>A normal subscription on a queue will consume messages so that no other
subscription will get a copy of the message. If you want to browse all the
messages on a queue in a non-destructive fashion, you can create browsing
subscription. Browsing subscriptions also works with durable subscriptions
since they are backed by a queue. To make a a browsing subscription, just add
the <code>browser:true</code> header to the <code>SUBSCRIBE</code> frame. For example:</p>
<pre><code>SUBSCRIBE
id:mysub
browser:true
destination:/queue/foo
^@</code></pre>
<p>Once the broker sends a browsing subscription the last message in the queue,
it will send the subscription a special &ldquo;end of browse&rdquo; message to indicate
browsing has completed and that the subscription should not expect any more
messages. The &ldquo;end of browse&rdquo; message will have a <code>browser:end</code> header set.
Example:</p>
<pre><code>MESSAGE
subscription:mysub
destination:
message-id:
browser:end
^@</code></pre>
<p>If you want the browsing subscription to remain active and continue to listen
for message once the last message on the queue is reached, you should add the
<code>browser-end:false</code> header to the <code>SUBSCRIBE</code> frame. When the
<code>browser-end:false</code> header is added the subscription will not be sent the &ldquo;end
of browse&rdquo; message previously described.</p>
<h3 id = "Queue_Message_Sequences">Queue Message Sequences</h3>
<p>As messages are added to a queue in a broker, they are assigned an
incrementing sequence number. Messages delivered to subscribers can be updated
to include the sequence number if the <code>include-seq</code> header is added to the
<code>SUBSCRIBE</code> frame. This header should be set to a header name which will be
added messages delivered to hold value of the sequence number.</p>
<p>Example:</p>
<pre><code>SUBSCRIBE
id:mysub
destination:/queue/foo
include-seq:seq
^@</code></pre>
<p>Then you can expect to receive messages like:</p>
<pre><code>MESSAGE
subscription:mysub
destination:/queue/foo
seq:1
Hello
^@
MESSAGE
subscription:mysub
destination:/queue/foo
seq:2
World
^@</code></pre>
<p>Furthermore, you can configure the <code>SUBSCRIBE</code> frame so that the subscription
only receives messages that have a sequence id that is equal to or greater
than a requested value by using the <code>from-seq</code> header. Example:</p>
<pre><code>SUBSCRIBE
id:mysub
destination:/queue/foo
from-seq:10
^@</code></pre>
<p>If the <code>from-seq</code> is set to <code>-1</code>, then the subscription will receive messages
from the tail of the queue. In other words, it will only receive new messages
sent to the queue.</p>
<p>Note: You can only use the <code>from-seq</code> header with normal destinations. If you
attempt to use it with a wildcard or composite destination then the connection
will be closed due to invalid usage.</p>
<h3 id = "Using_Queue_Browsers_to_Implement_Durable_Topic_Subscriptions">Using Queue Browsers to Implement Durable Topic Subscriptions</h3>
<p>You can use queue browsers with consumer side message sequence tracking to
achieve the same semantics as durable topics subscriptions but with a better
performance profile. Since browsers do not delete messages from a queue, when
you use multiple browsers against one queue you get the same broadcast effects
that a topic provides.</p>
<p>In this approach the subscribing application keeps track of the last sequence
number processed from the subscription. The sequence number is typically
stored as part of the unit of work which is processing the message. The
subscription can use the default auto acknowledge mode but still get 'once and
only once' delivery guarantees since:</p>
<ul>
<li>consuming application records the last message sequence that
was processed</li>
<li>message are not deleted when delivered to the subscriber</li>
<li>on restart consuming application continues receiving from the queue
for the last sequence that it received.</li>
</ul>
<p>The <code>SUBSCRIBE</code> frame used to create the browser should add the <code>include-seq</code>,
<code>from-seq</code>, and <code>browser-end</code> headers so that they can resume receiving
messages from the queue from the last known sequence. If you are starting a
new consumer that does not have a last processed sequence number, you can
either set <code>from-seq</code> to:</p>
<ul>
<li><code>0</code> to start receiving at the head of the queue which sends
the subscription a copy of all the messages that are currently
queued.</li>
<li><code>-1</code> to start receiving at the tail of the queue which to skips
over all the message that exist in the queue so that the subscription
only receives new messages.</li>
</ul>
<p>Example:</p>
<pre><code>SUBSCRIBE
id:mysub
destination:/queue/foo
browser:true
browser-end:false
include-seq:seq
from-seq:0
^@</code></pre>
<p>Since this approach does not consume the messages from the queue, you should
either:</p>
<ul>
<li>Send messages to the queue with an expiration time so that they are
automatically delete once the expiration time is reached.</li>
<li>Periodically run a normal consumer application which can cursor the queue
and delete messages are are deemed no longer needed.</li>
</ul>
<h3 id = "Exclusive_Subscriptions">Exclusive Subscriptions</h3>
<p>We maintain the order of messages in queues and dispatch them to
subscriptions in order. However if you have multiple subscriptions consuming
from the same queue, you will loose the guarantee of processing the messages
in order; since the messages may be processed concurrently on different
subscribers.</p>
<p>Sometimes it is important to guarantee the order in which messages are
processed. e.g. you don't want to process the update to an order until an
insert has been done; or to go backwards in time, overwriting an newer update
of an order with an older one etc.</p>
<p>So what folks have to do in clusters is often to only run one consumer
process in a cluster to avoid loosing the ordering. The problem with this is
that if that process goes down, no one is processing the queue any more,
which can be problem.</p>
<p>Apollo supports exclusive subscriptions which avoids the end user
having to restrict himself to only running one process. The broker will pick
a single subscription to get all the messages for a queue to ensure ordering.
If that subscription fails, the broker will auto failover and choose another
subscription.</p>
<p>An exclusive subscription is created by adding a <code>exclusive:true</code> header
to the <code>SUBSCRIBE</code> frame. Example:</p>
<pre><code>SUBSCRIBE
id:mysub
exclusive:true
destination:/queue/foo
^@</code></pre>
<h3 id = "Message_Groups">Message Groups</h3>
<p>Message Groups are an enhancement to the Exclusive Consumer feature to provide</p>
<ul>
<li>guaranteed ordering of the processing of related messages across a single queue</li>
<li>load balancing of the processing of messages across multiple consumers</li>
<li>high availability / auto-failover to other consumers if a JVM goes down</li>
</ul>
<p>Message Groups are logically like a parallel Exclusive Consumer. Rather
than all messages going to a single consumer, the stomp <code>message_group</code> header
is used to define which message group the message belongs to. The Message Group
feature then ensures that all messages for the same message group will be sent to
the currently assigned consumer for the group. The assigned consumer consumer
for a message group may change but not before all messages sent to the previous
consumer are acked or if the consumer is disconnected.</p>
<p>Another way of explaining Message Groups is that it provides sticky load balancing
of messages across consumers; where the message group value is kinda like a HTTP
session ID or cookie value and the message broker is acting like a HTTP load balancer.</p>
<p>Here is an example message with the message group set:</p>
<pre><code>MESSAGE
destination:/queue/PO.REQUEST
message_group:hiram
PO145
^@</code></pre>
<p>The broker uses consistent hashing to map message groups to consumers. When you add another
subscription to a queue, the broker will first wait for messages sent to previous subscriptions
to be processed and then the broker rebalances the message groups across the attached consumers.</p>
<h3 id = "Temporary_Destinations">Temporary Destinations</h3>
<p>Temporary destinations are typically used to receive response messages in
a request/response messaging exchange. A temporary destination can only
be consumed by a subscription created on the connection which is associated
with the temporary destination. Once the connection is closed, all associated
temporary destinations are removed. Temporary destinations are prefixed with:</p>
<ul>
<li><code>/temp-queue/</code> - For temporary queues. Has the same delivery semantics as queues.</li>
<li><code>/temp-topic/</code> - For temporary topics. It has the same delivery semantics of topics.</li>
</ul>
<p>In a request/response scenario, you would first subscribe to the temporary topic:</p>
<pre><code>SUBSCRIBE
id:mysub
destination:/temp-queue/example
^@</code></pre>
<p>Then you would send a request with the reply-to header set to the temporary destination.
Example:</p>
<pre><code>SEND
destination:/queue/PO.REQUEST
reply-to:/temp-queue/example
PO145
^@</code></pre>
<p>The consumer receiving the request will receive a message similar to:</p>
<pre><code>MESSAGE
subscription:foo
reply-to:/queue/temp.default.23.example
destination:/queue/PO.REQUEST
reply-to:/temp-queue/example
PO145</code></pre>
<p>Notice that the reply-to` header value is updated from a temporary destination
name to normal destination name. The subscription servicing he requests should respond
to the updated destination value (<code>/queue/temp.default.23.example</code> in the example above).</p>
<p>Temporary destination names actually map to normal queues and topics. They just have
a <code>temp.&lt;broker&#95;id&gt;.&lt;connection&#95;id&gt;.</code> prefix. Any destination which starts with
<code>temp.</code> has a security policy which only allows the connection which created it
to subscribe from it. These destinations are also auto deleted once the connection
is closed.</p>
<h3 id = "Destination_Wildcards">Destination Wildcards</h3>
<p>We support destination wildcards to easily subscribe to multiple destinations
with one subscription. This concept has been popular in financial market data
for some time as a way of organizing events (such as price changes) into
hierarchies and to use wildcards for easy subscription of the range of
information you're interested in.</p>
<ul>
<li><code>.</code> is used to separate names in a path</li>
<li><code>*</code> is used to match any name in a path</li>
<li><code>{regex}</code> is used to match a path name against a regular expression.</li>
<li><code>**</code> is used to recursively match path names</li>
</ul>
<p>For example imagine you are sending price messages from a stock exchange feed.
You might use some kind of destination naming conventions such as:</p>
<ul>
<li><code>/topic/PRICE.STOCK.NASDAQ.IBM</code> to publish IBM's price on NASDAQ and</li>
<li><code>/topic/PRICE.STOCK.NYSE.SUNW</code> to publish Sun's price on the New York Stock Exchange</li>
</ul>
<p>A subscriber could then use exact destinations to subscribe to exactly the
prices it requires. Or it could use wildcards to define hierarchical pattern
matches to the destinations to subscribe from.</p>
<p>For example using the example above, these subscriptions are possible</p>
<ul>
<li><code>/topic/PRICE.**</code> : Any price for any product on any exchange</li>
<li><code>/topic/PRICE.STOCK.**</code> : Any price for a stock on any exchange</li>
<li><code>/topic/PRICE.STOCK.NASDAQ.*</code> : Any stock price on NASDAQ</li>
<li><code>/topic/PRICE.STOCK.*.IBM</code> : Any IBM stock price on any exchange</li>
<li><code>/topic/PRICE.STOCK.*.I*</code> : Any stock price starting with 'I' on any exchange</li>
<li><code>/topic/PRICE.STOCK.*.*{[0-9]}</code> : Any stock price that ends in a digit on any exchange</li>
</ul>
<p>Destination wildcards can only be used in a SUBSCRIBE frame.</p>
<h3 id = "Composite_Destinations">Composite Destinations</h3>
<p>You can use composite destinations to send or subscribe to multiple
destinations at one time. You use separator of <code>,</code> between destination
names. For example, to send one message to 2 queues and 1 topic:</p>
<pre><code>SEND
destination:/queue/a,/queue/b,/topic/c
Composites rock!
^@</code></pre>
<h3 id = "Message_Selectors">Message Selectors</h3>
<p>Message selectors allow a subscription to only receive a subset of the
messages sent to a destination. The selector acts like a filter which
is applied against the message properties and only those messages
which match pass through to the subscription. </p>
<p>Selectors are defined using SQL 92 syntax and typically apply to message
headers; whether the standard properties available on a JMS message or custom
headers you can add via the JMS code.</p>
<p>Here is an example:</p>
<pre><code>type = 'car' AND color = 'blue' AND weight &gt; 2500</code></pre>
<p>To create a subscription with a message selector, you set the <code>selector</code>
header in the STOMP <code>SUBSCRIBE</code> frame to the desired selector. Example:</p>
<pre><code>SUBSCRIBE
id:sub0
selector:type = 'car' AND color = 'blue' AND weight &gt; 2500
destination:/topic/foo
^@</code></pre>
<h3 id = "Destination_Name_Restrictions">Destination Name Restrictions</h3>
<p>Destination names are restricted to using the characters <code>a-z</code>, <code>A-Z</code>, <code>0-9</code>,
<code>_</code>, <code>-</code> <code>%</code>, <code>~</code>, <code>:</code>, ' ', '(', ')' or <code>.</code> in addition to composite separator <code>,</code> and the wild
card <code>*</code>. Any other characters must be UTF-8 and then URL encoded if you wish to
preserve their significance.</p>
<div></div>
</div>
</div>
</body>
</html>