Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Won't Fix
-
0.9
-
None
Description
Qpid's handling of RuntimeExceptions (and subclasses) thrown from within a client's MessageListener#onMessage(Message) does not follow the JMS specification. This defect affects only JMS consumers using asynchronous delivery (via an onMessage callback rather than MessageConsumer#receive()) with delivery modes AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE).
Delivery modes CLIENT_ACKNOWLEDGE and SESSION_TRANSACTED are NOT affected.
The JMS specification (Java Message Service, Version 1.1 April 12, 2002) states:
======
4.5.2 Asynchronous Delivery
A client can register an object that implements the JMS MessageListener
interface with a MessageConsumer. As messages arrive for the consumer, the
provider delivers them by calling the listener's onMessage method.
It is possible for a listener to throw a RuntimeException; however, this is
considered a client programming error. Well-behaved listeners should catch
such exceptions and attempt to divert messages causing them to some form of
application-specific 'unprocessable message' destination.
The result of a listener throwing a RuntimeException depends on the session's
acknowledgment mode.
- AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE - the message
will be immediately redelivered. The number of times a JMS provider will
redeliver the same message before giving up is provider-dependent. The
JMSRedelivered message header field will be set for a message redelivered
under these circumstances.
======
Currently, Qpid handles a message that causes onMessage to throw a RuntimeException in the following manner:
1) The exception will be logged to the (client) application log:
Dispatcher-Channel-1 2011-02-03 11:37:43,095 ERROR [apache.qpid.client.BasicMessageConsumer] reNotification : Caught exception (dump follows) - ignoring...
java.lang.RuntimeException: Rejecting message <xxxxx> at org.apache.qpid.client.MessageListenerRuntimeExceptionHandlingTest$1.onMessage(MessageListenerRuntimeExceptionHandlingTest.java:229)
at org.apache.qpid.client.BasicMessageConsumer.notifyMessage(BasicMessageConsumer.java:722)
at org.apache.qpid.client.BasicMessageConsumer_0_10.notifyMessage(BasicMessageConsumer_0_10.java:164)
2) Subsequent messages continue to be delivered as normal.
3) The message that caused the RuntimeException will be not redelivered to the client until the client recreates the MessageConsumer.
4) If the message continues to cause the RuntimeException, the message will be redelivered to the client on every client restart (unless message is expired by its time-to-live, persistence, queue durability etc).