<!--
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 JMS Pre-Acknowledge 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 Pre-Acknowledge Example</h1>
<p>Standard JMS supports three acknowledgement modes: AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, and
DUPS_OK_ACKNOWLEDGE. For a full description on these modes please consult the JMS specification, or any
JMS tutorial.</p>
<p>All of these standard modes involve sending acknowledgements from the client to the server. However
in some cases, you really don't mind losing messages in event of failure, so it would make sense
to acknowledge the message on the server <b>before</b> delivering it to the client.</p>
<p>By acknowledging the message before sending to the client, you can avoid extra network traffic and CPU
work done in sending acknowledgements from client to server.</p>
<p>The down-side of acknowledging on the server before delivery, is that if the system crashes after acknowledging
the message, but before the message has been received by the client, then, on recovery, that message
will be lost. This makes pre-acknowledgement not appropriate for all use cases, but it is very useful for some
use-cases when you can cope with such loss of messages<p>
<p>An example of a use-case where it might be a good idea to use pre-acknowledge, is for stock price update
messages. With these messages it might be ok to lose a message in event of crash, since the next price
update message will arrive soon, overriding the previous price.</p>
<p>In order to use pre-acknowledge functionality with ActiveMQ the session has to be created with
a special, ActiveMQ specific acknowledgement mode, given by the value of
<code>ActiveMQJMSConstants.PRE_ACKNOWLEDGE</code>.
<h2>Example step-by-step</h2>
<p><i>To run the example, simply type <code>mvn verify</code> from this directory</i></p>
<ol>
<li>Create an initial context to perform the JNDI lookup.</li>
<pre class="prettyprint">
<code>
initialContext = getContext(0);
</code>
</pre>
<li>Perform the look-ups</li>
<pre class="prettyprint">
<code>
Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
</code>
</pre>
<li>Create a the JMS objects.</li>
<pre class="prettyprint">
<code>
connection = cf.createConnection();
Session session = connection.createSession(false, ActiveMQSession.PRE_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
MessageConsumer messageConsumer = session.createConsumer(queue);
</code>
</pre>
<li>Create and send a message.</li>
<pre class="prettyprint">
<code>
TextMessage message1 = session.createTextMessage("This is a text message 1");
producer.send(message1);
System.out.println("Sent message: " + message1.getText());
</code>
</pre>
<li>Print out the message count of the queue. The queue contains one message as expected
delivery has not yet started on the queue.</li>
<pre class="prettyprint">
<code>
int count = getMessageCount(connection);
System.out.println("Queue message count is " + count);
</code>
</pre>
<li>Start the Connection, delivery will now start. Give a little time for delivery to occur.</li>
<pre class="prettyprint">
<code>
connection.start();
Thread.sleep(1000);
</code>
</pre>
<li>Print out the message count of the queue. It should now be zero, since the message has
already been acknowledged even before the consumer has received it.</li>
<pre class="prettyprint">
<code>
count = getMessageCount(connection);
System.out.println("Queue message count is now " + count);
</code>
</pre>
<li>Finally, receive the message.</li>
<pre class="prettyprint">
<code>
TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
System.out.println("Received message: " + messageReceived.getText());
</code>
</pre>
<li>Be sure to close our resources!</li>
<pre class="prettyprint">
<code>
if (initialContext != null)
{
initialContext.close();
}
if (connection != null)
{
connection.close();
}
</code>
</pre>
</ol>
<h2>More information</h2>
<ul>
<li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#pre-acknowledge">Pre-acknowledgement Mode chapter</a></li>
</ul>
</body>
</html>