blob: fccdeedbd6991c4c9c6beb6d743640a8b489e105 [file] [log] [blame]
<?xml version="1.0"?>
<!--
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.
-->
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="Java-Broker-Runtime-Handling-Undeliverable-Messages">
<title>Handing Undeliverable Messages</title>
<section role="h2" xml:id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Introduction">
<title>Introduction</title>
<para> Messages that cannot be delivered successfully to a consumer (for instance, because the
client is using a transacted session and rolls-back the transaction) can be made available on
the queue again and then subsequently be redelivered, depending on the precise session
acknowledgement mode and messaging model used by the application. This is normally desirable
behaviour that contributes to the ability of a system to withstand unexpected errors. However, it
leaves open the possibility for a message to be repeatedly redelivered (potentially indefinitely),
consuming system resources and preventing the delivery of other messages. Such undeliverable
messages are sometimes known as poison messages.</para>
<para>For an example, consider a stock ticker application that has been designed to consume prices
contained within JMS TextMessages. What if inadvertently a BytesMessage is placed onto the queue?
As the ticker application does not expect the BytesMessage, its processing might fail and cause it
to roll-back the transaction, however the default behavior of the Broker would mean that the
BytesMessage would be delivered over and over again, preventing the delivery of other legitimate
messages, until an operator intervenes and removes the erroneous message from the queue. </para>
<para>Qpid has maximum delivery count and dead-letter queue (DLQ) features which can be used in
concert to construct a system that automatically handles such a condition. These features are
described in the following sections.</para>
</section>
<section role="h2" xml:id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Maximum-Delivery-Count">
<title>Maximum Delivery Count</title>
<para> Maximum delivery count is a property of a queue. If a consumer application is unable to
process a message more than the specified number of times, then the broker will either route the
message to a dead-letter queue (if one has been defined), or will discard the message. </para>
<para> In order for a maximum delivery count to be enforced, the consuming client
<emphasis>must</emphasis> call <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#rollback()">Session#rollback()</link> (or <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#recover()">Session#recover()</link> if the session is not transacted). It is during the Broker's
processing of Session#rollback() (or Session#recover()) that if a message has been seen
at least the maximum number of times then it will move the message to the DLQ or discard the
message.</para>
<para>If the consuming client fails in another manner, for instance, closes the connection, the
message will not be re-routed and consumer application will see the same poison message again
once it reconnects.</para>
<para> If the consuming application is using AMQP 0-9-1, 0-9, or 0-8 protocols, it is necessary to
set the client system property <varname>qpid.reject.behaviour</varname> or connection or binding
URL option <varname>rejectbehaviour</varname> to the value <literal>server</literal>.</para>
<para>It is possible to determine the number of times a message has been sent to a consumer via
the Management interfaces, but is not possible to determine this information from a message client.
Specifically, the optional JMS message header <property>JMSXDeliveryCount</property> is not
supported.</para>
<para>Maximum Delivery Count can be specified when a new queue is created or using the the
queue declare property <property>x-qpid-maximum-delivery-count</property></para>
</section>
<section role="h2" xml:id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Dead-Letter-Queues">
<title>Dead Letter Queues (DLQ)</title>
<para>A Dead Letter Queue (DLQ) acts as an destination for messages that have somehow exceeded the
normal bounds of processing and is utilised to prevent disruption to flow of other messages. When
a DLQ is enabled for a given queue if a consuming client indicates it no longer wishes the
receive the message (typically by exceeding a Maximum Delivery Count) then the message is moved
onto the DLQ and removed from the original queue. </para>
<para>The DLQ feature causes generation of a Dead Letter Exchange and a Dead Letter Queue. These
are named convention QueueName<emphasis>_DLE</emphasis> and QueueName<emphasis>_DLQ</emphasis>.</para>
<para>DLQs can be enabled when a new queue is created
or using the queue declare property <property>x-qpid-dlq-enabled</property>.</para>
<caution>
<title>Avoid excessive queue depth</title>
<para>Applications making use of DLQs <emphasis>should</emphasis> make provision for the frequent
examination of messages arriving on DLQs so that both corrective actions can be taken to resolve
the underlying cause and organise for their timely removal from the DLQ. Messages on DLQs
consume system resources in the same manner as messages on normal queues so excessive queue
depths should not be permitted to develop.</para>
</caution>
</section>
</section>