<p>This example shows you how to define and deal with dead letter messages.</p>
<p>Messages can be delivered unsuccessfully (e.g. if the transacted session used to consume them is rolled back).
Such a message goes back to the JMS destination ready to be redelivered.
However, this means it is possible for a message to be delivered again and again without any success and remain in the destination, clogging the system.</p>
<p>To prevent this, messaging systems define dead letter messages: after a specified unsuccessful delivery attempts, the message is removed from the destination
and instead routed to a <em>dead letter address</em> where they can be consumed for further investigation.
The example will send 1 message to a queue. We will deliver the message 3 times and rollback the session every time.<br/>
On the 4th attempt, there won't be any message to consume: it will have been moved to a <em>dead letter address</em>.<br/>
We will then consume this dead letter message.
</p>
<h2>Example setup</h2>
<p><em>Dead letter addresses</em> and <em>maximum delivery attempts</em> are defined in the configuration file <ahref="src/main/resources/hornetq/server0/hornetq-configuration.xml">hornetq-configuration.xml</a>:</p>
or a <code>Topic</code> by prefixing with <code>jms.topic.</code>.<br/>
In this example, we will use a <code>Queue</code> to hold the dead letter messages.</p>
<p>The maximum attempts of delivery is <code>3</code>. Once this figure is reached, a message is considered a dead letter message and is moved to
the <code>deadLetterQueue</code>.
<p>Since we want to consume messages from this deadLetterQueue, we also need to add a JNDI binding to perform a lookup.
This is configured in <ahref="src/main/resources/hornetq/server0/hornetq-jms.xml">hornetq-jms.xml</a></p>
<preclass="prettyprint">
<code><queue name="deadLetterQueue">
<entry name="/queue/deadLetterQueue"/>
</queue></code>
</pre>
</p>
<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>First 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>
<p>Since the queue was configured to move messages to the <code>deadLetterQueue</code> after <code>3</code> unsuccessful delivery attempts,
the message won't be in the <code>queue</code> anymore</p>
<li>We try to receive a message from the queue for a 4<sup>th</sup>. Since there is none, the call will timeout after 5000ms and <code>messageReceived</code> will be <code>null</code>
<li>The message's destination is the dead letter queue</li>
<preclass="prettyprint">
<code>System.out.println("Destination of the message: " + ((Queue)messageReceived.getJMSDestination()).getQueueName());</code>
</pre>
<li>The <strong>origin destination</strong> is stored in the <code>_HQ_ORIG_ADDRESS</code> property
<preclass="prettyprint">
<code>System.out.println("*Origin destination* of the message: " + messageReceived.getStringProperty("_HQ_ORIG_ADDRESS"));</code>
</pre>
<li>We do not forget to commit the session to acknowledge that we have received the message from the dead letter queue</li>
<preclass="prettyprint">
<code>session.commit();</code>
</pre>
</p>
<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>