This issue concerns the behaviour of the JMS provider when it sends a BytesMessage.
The spec is not clear on what state the body of a BytesMessage is left in after it has been sent. We're talking about the message object in the sending program, not in the receiving program.
A JMS 2.0 vendor has asked for the behaviour to be clarified for async send. However this issue will discuss the behaviour for both async and sync send.
There are three possibilities:
1. The JMS provider leaves the body in write-only mode with the stream positioned at the end. That would allow the application to send a message, append additional data to the message body, and send it a second time. An application which wanted to read the message body would have to call reset.
2. The JMS provider leaves the BytesMessage in read-only with the stream positioned at the start. To achieve this the send method would need to call reset before returning.
3. Leave the behaviour undefined.
This issue applies to both synchronous and asynchronous send. In the sync case the issue is what state the message is left in after the call to send returns. In the async case the issue is what state the message is in when the CompletionListener callback is performed. Let's consider these separately.
Option 1 (leave the body in write-only mode with the stream positioned at the end):
- It is not practically possible for a JMS provider to implement this correctly. This is because of the need to support the case where the JMS provider is used to send a message whose implementation is not its own (as required by JMS 2.0 section 3.12). In that case the JMS provider must use the public API to read the data from the "foreign" message. After it has done so the message would be in read-only mode, with the stream positioned at the end. The only way to change the message to write-only mode would be to call reset, but that would position the stream back at the start.
Option 2 (leave the body in read-only mode with the stream positioned at the start).
- This is the current de facto spec requirement for async send. This is because there is a JMS 2.0 TCK test which sends a BytesMessage asynchronously and which attempts to read the body of the message object passed to the CompletionListener. without calling reset. All existing JMS 2.0 providers will have passed this test.
- There is also a clear use case for this option, since It is expected that a CompletionListener callback method may want to read the message in order to identify the message that was successfully sent.
Option 3 (leave the behaviour undefined).
- This is undesirable because the only things a portable application application could do would be to call reset and read the message, or call clearBody to clear it and re-write it from scratch. If a JMS provider left the body in write-only mode with the stream positioned at the end, and the application took advantage of this to append to the body, then the application would not be portable.
Proposal: It is therefore proposed to update the JMS 2.0 specification to require the behaviour described in option 2: when a BytesMessage is sent asynchronously, the message object that was sent must be set to be read-only with the stream positioned at the start prior to calling the CompletionListener. To achieve this the send method would need to call reset before returning.
JMS 1.1 was not specific about this and different vendors already adopt different behaviour. There are no TCK tests which rely on a specific behaviour. It is therefore probably too late to define more specific behaviour, especially as this has not been reported as an issue by users or vendors.
In practice I would suggest that for a synchronous send there is little reason for a sending application to want to read a the body of a BytesMessage after it has been sent.
Nevertheless, for consistency, we should perhaps change the spec to recommend that when a message is sent synchronously, the provider should call reset before the send() returns. But this will need to remain a recommendation since existing JMS 1.1 providers may have interpreted this differently, making it too late to standardise this.
Proposal It is proposed to update the JMS 2.0 specification to recommend, but not require, that the provider should call reset before the send() returns, and to add a warning that portable applications must not make assumptions about what state the message is in.