users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: (JMS_SPEC-102) Make JMSConsumer.receivePayload methods consistent with Message.getBody

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Fri, 16 Nov 2012 15:08:28 +0000

I refer to this issue:
http://java.net/jira/browse/JMS_SPEC-102
Make JMSConsumer.receivePayload methods consistent with Message.getBody

In my last email on this topic I proposed some updated API which renamed the JMSConsumer methods receivePayload and
receivePayloadNoWait to receiveBody and receiveBodyNoWait and changed their definition to be consistent with the Message
method getBody.

I received one "+1" on this (thanks, Nick!) and no other comments. I don't think this is a major change so I am going
ahead with these changes.

Whilst drafting the updated API docs I noticed that there was an omission which probably needed clarifying. This was
what happens then a call to JMSConsumer.getBody() or getBodyNowait() fails with a MessageFormatRuntimeException. Is the
message then lost? Is it redelivered?

Since this exception is caused by the application rather than by the provider (in the sense that a CTS test could
predictably cause one to be thrown) it is similar to the case where onMessage() throws an exception. The redelivery
behaviour in that case is defined in section 4.5.2 "Asynchronous delivery". I think the redelivery behaviour for when
JMSConsumer.getBody() and getBodyNowait() throws a MessageFormatRuntimeExceptionshould should be similar.

I would therefore like to propose the following behaviour for this case. This is closely modelled on section 4.5.2
"Asynchronous delivery".

---------------------------------------------------------------------------------------
The result of this method throwing a MessageFormatRuntimeException depends on the session mode:

* AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE: The JMS provider will behave as if the unsuccessful call to receiveBody or
receiveBodyNoWait had not occurred. The message will be delivered again before any subsequent messages.

This is not considered to be redelivery and does not cause the JMSRedelivered message header field to be set or the
JMSXDeliveryCount message property to be incremented.

* CLIENT_ACKNOWLEDGE: The JMS provider will behave as if the call to receiveBody or receiveBodyNoWait had been
successful and will not deliver the message again.

As with any message that is delivered with a session mode of CLIENT_ACKNOWLEDGE, the message will not be acknowledged
until acknowledge is called on the JMSContext. If an application wishes to have the failed message redelivered, it must
call recover on the JMSContext. The redelivered message's JMSRedelivered message header field will be set and its
JMSXDeliveryCount message property will be incremented.

* Transacted session: The JMS provider will behave as if the call to receiveBody or receiveBodyNoWait had been
successful and will not deliver the message again.

As with any message that is delivered in a transacted session, the transaction will remain uncommitted until the
transaction is committed or rolled back by the application. If an application wishes to have the failed message
redelivered, it must roll back the transaction. The redelivered message's JMSRedelivered message header field will be
set and its JMSXDeliveryCount message property will be incremented.
---------------------------------------------------------------------------------------

I have added this to the API docs at
http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/JMSConsumer.html#receiveBody%28java.lang.Class%29

I have also added the same text into an expanded section 11.2.5 "Consuming messages", adding a new subsection 11.2.5.1
"Consuming message bodies synchronously".

Comments welcome!

Nigel