<!--
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.
-->
<html>
<head>
<title>ActiveMQ Artemis JMS Request-Reply Example</title>
<link rel="stylesheet" type="text/css" href="../../../common/common.css" />
<link rel="stylesheet" type="text/css" href="../../../common/prettify.css" />
<script type="text/javascript" src="../../../common/prettify.js"></script>
</head>
<body onload="prettyPrint()">
<h1>JMS Request-Reply Example</h1>
<p>This example shows you how to handle a request message and receive a reply. To get a reply message, the requesting client creates a temporary queue. Then it sends out the request message with JMSReplyTo set to the temporary queue. The request message is handled by a SimpleRequestServer, who is listening to the request queue for incoming requests. If a request message has arrived, it extracts the reply queue from the request message by JMSReplyTo header, and sends back a reply message. To let the client know to which request message a reply message is related, the server also set the JMSCorrelationID with the request message's JMSMessageID header to the reply message.</p>
<p>Of course, in a real world example you would re-use the session, producer, consumer and temporary queue and not create a new one for each message!
Or better still use the correlation id, and just store the requests in a map, then you don't need a temporary queue at all
<p>Request/Reply style messaging is supported through standard JMS message headers JMSReplyTo and JMSCorrelationID. This is often used in request-reply style communications between applications.
Whenever a client sends a message that expects a response, it can use this mechanism to implement. please consult the JMS 1.1 specification for full details.</p>
<h2>Example step-by-step</h2>
<p><i>To run the example, simply type <code>mvn verify -Pexample</code> from this directory</i></p>
<ol>
<li>We start the request server</li>
<pre class="prettyprint">
<code>SimpleRequestServer server = new SimpleRequestServer();</code>
<code>server.start();</code>
</pre>
<li>We need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the <code>client-jndi.properties</code> file in the directory <code>../common/config</code></li>
<pre class="prettyprint">
<code>initialContext = getContext();</code>
</pre>
<li>We lookup the queue for sending the request message</li>
<pre class="prettyprint">
<code>Queue requestQueue = (Queue) initialContext.lookup("/queue/exampleQueue");</code>
</pre>
<li>We lookup for the Connection Factory</li>
<pre class="prettyprint">
<code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code>
</pre>
<li>We create a JMS Connection</li>
<pre class="prettyprint">
<code>connection = cf.createConnection();</code>
</pre>
<li>We start the connection</li>
<pre class="prettyprint">
<code>connection.start();</code>
</pre>
<li>We create a JMS Session</li>
<pre class="prettyprint">
<code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
</pre>
<li>We create a JMS Message Producer to send request message</li>
<pre class="prettyprint">
<code>MessageProducer producer = session.createProducer(requestQueue);</code>
</pre>
<li>We create a temporary queue used to send reply message to and receive reply from</li>
<pre class="prettyprint">
<code>TemporaryQueue replyQueue = session.createTemporaryQueue();</code>
</pre>
<li>We create a consumer to receive reply message</li>
<pre class="prettyprint">
<code>MessageConsumer replyConsumer = session.createConsumer(replyQueue);</code>
</pre>
<li>We create a request Text Message</li>
<pre class="prettyprint">
<code>TextMessage requestMsg = session.createTextMessage("A request message");</code>
</pre>
<li>We set the ReplyTo header so that the request receiver knows where to send the reply.</li>
<pre class="prettyprint">
<code>requestMsg.setJMSReplyTo(replyQueue);</code>
</pre>
<li>We sent the request message</li>
<pre class="prettyprint">
<code>producer.send(requestMsg);</code>
</pre>
<li>We put the request message to the map. Later we use it to check out which request message a reply message is for. Here we use the MessageID as the correlation id (JMSCorrelationID). You don't have to use it though. You can use some arbitrary string for example.</li>
<pre class="prettyprint">
<code>requestMap.put(requestMsg.getJMSMessageID(), requestMsg);</code>
</pre>
<li>We receive the reply message</li>
<pre class="prettyprint">
<code>TextMessage replyMessageReceived = (TextMessage)replyConsumer.receive();</code>
</pre>
<li>We check out which request message is this reply message sent for. Here we just have one request message for illustrative purpose. In real world there may be many requests and many replies.</li>
<pre class="prettyprint">
<code>TextMessage matchedMessage = requestMap.get(replyMessageReceived.getJMSCorrelationID());</code>
</pre>
<li>We close the consumer and producer on the replyQueue</li>
<pre class="prettyprint">
<code>replyConsumer.close();</code>
</pre>
<li>We delete the temporary queue</li>
<pre class="prettyprint">
<code>replyQueue.delete();</code>
</pre>
<li>We shutdown the request server</li>
<pre class="prettyprint">
<code>server.shutdown();</code>
</pre>
<li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
<pre class="prettyprint">
<code>finally
{
if (initialContext != null)
{
initialContext.close();
}
if (connection != null)
{
connection.close();
}
}</code>
</pre>
</ol>
Request Messages are handled in SimpleRequestServer.onMessage(),
<ol>
<li>Extract the ReplyTo destination</li>
<pre class="prettyprint">
<code>Destination replyDestination = request.getJMSReplyTo();</code>
</pre>
<li>Create the reply message</li>
<pre class="prettyprint">
<code>TextMessage replyMessage = session.createTextMessage("A reply message");</code>
</pre>
<li>Set the CorrelationID</li>
<pre class="prettyprint">
<code>replyMessage.setJMSCorrelationID(request.getJMSCorrelationID());</code>
</pre>
<li>Send out the reply message</li>
<pre class="prettyprint">
<code>replyProducer.send(replyMessage);</code>
</pre>
</ol>
</body>
</html>