MDB Failure Handling: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 34: Line 34:
=Redelivery=
=Redelivery=


The message redelivery count on failure is ''not'' an attribute of an individual MDB container, as the "" configuration attribute seems to suggest, but of the HornetQ destination.
The message redelivery count on failure is ''not'' an attribute of an individual MDB container, as the "[[MDB#dLQMaxResent|dLQMaxResent]]" configuration attribute seems to suggest, but of the HornetQ destination. In EAP 6.4.10, "[[MDB#dLQMaxResent|dLQMaxResent]]" is ignored. If an MDB fails to process a message in a transactional context, the transaction is rolled back and the message is "put back on the queue". The message will be redelivered by the HornetQ destination, subject to redelivery rules sent on the destination. Upon failure, the message will be redelivered to the same MDB container, if it is the only consumer for that queue, or to a different MDB container if there is more than one MDB container listening to the queue.


=How to Handle Failure in a Non-Transactional Context=
=How to Handle Failure in a Non-Transactional Context=

Revision as of 17:21, 25 April 2017

Internal

Relevance

EAP 6.4.10

Overview

This article addresses failure handling in an MDB context. It was written while experimenting with EAP 6.4 and a HornetQ-based messaging subsystem.

Failure Handling Specification

JSR 318 Enterprise JavaBeans Version 3.1 EJB Core Contract and Requirements, Section 5.4.18 "Dealing with Exceptions" mentions that MDBs should not throw RuntimeExceptions. If a RuntimeExceptions occurs, the container will transition the MDB in the "does not exist" state. The message will not be acknowledged, and if messages arrive to the destination, the container can delegate the message to another MDB instance.

WildFly/HornetQ Behavior on RuntimeException

Message Delivery Occurs in a Container-Managed Transactional Context

If the message delivery occurs in a container-managed transactional context, the HornetQ resource adapter acknowledges the message when it first receives from the HornetQ JMS provider. This behavior can be thought as "removing the message from the queue". The resource adapter attempts to deliver the message in a loop until either it is consumed by an MDB instance or the message is sent to the DLQ. Who loops and Who sends the message to DLQ?

Does this mean that if the JVM fails while the message is processed in the loop, the message is lost?

The current transaction is automatically rolled back. The MDB container's transactional interceptor catches the RuntimeException and rolls back the transaction, by invoking javax.transaction.Transaction.setRollbackOnly().

The MDB instance that triggered the failure is destroyed. The @PreDestroy callback, if exists, is invoked, and the instance is discarded from the pool. Upon re-delivery, if any, a new instance to handle the message will be created.

Message Delivery Occurs in a Non-Transactional Context

How to Handle Failure in a Transactional Context

Redelivery

The message redelivery count on failure is not an attribute of an individual MDB container, as the "dLQMaxResent" configuration attribute seems to suggest, but of the HornetQ destination. In EAP 6.4.10, "dLQMaxResent" is ignored. If an MDB fails to process a message in a transactional context, the transaction is rolled back and the message is "put back on the queue". The message will be redelivered by the HornetQ destination, subject to redelivery rules sent on the destination. Upon failure, the message will be redelivered to the same MDB container, if it is the only consumer for that queue, or to a different MDB container if there is more than one MDB container listening to the queue.

How to Handle Failure in a Non-Transactional Context