jms-spec
  1. jms-spec
  2. JMS_SPEC-125

Define whether a JMS provider should call reset after sending a BytesMessage asynchronously

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0
    • Fix Version/s: JMS 2.0 rev A
    • Labels:
      None

      Description

      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.

      Asynchronous send

      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.

      Synchronous send

      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.

        Issue Links

          Activity

          Hide
          John D. Ament added a comment -

          What is the use case for trying to read data from a BytesMessage that you just sent?

          Show
          John D. Ament added a comment - What is the use case for trying to read data from a BytesMessage that you just sent?
          Hide
          Nigel Deakin added a comment -

          The reason the Message is passed to the CompletionListener is to allow it to determine which message has been sent (e.g. there may be more than one incomplete send). To do that it might need to read the message.

          This is a somewhat obscure use case (though it came up in a TCK test) but we have the opportunity to define the required behaviour here and so should take it.

          Show
          Nigel Deakin added a comment - The reason the Message is passed to the CompletionListener is to allow it to determine which message has been sent (e.g. there may be more than one incomplete send). To do that it might need to read the message. This is a somewhat obscure use case (though it came up in a TCK test) but we have the opportunity to define the required behaviour here and so should take it.
          Hide
          Nigel Deakin added a comment - - edited

          Proposed changes (supersed by updated proposal below)

          javadoc for BytesMessage: Existing text:

          When the message is first created, and when clearBody is called, the body of
          the message is in write-only mode. After the first call to reset has been
          made, the message body is in read-only mode.

          After a message has been sent, the client that sent it can retain and modify
          it without affecting the message that has been sent. The same message object
          can be sent multiple times.

          When a message has been received, the provider has called reset so that the
          message body is in read-only mode for the client.

          Replacement text: (new words marked *thus)

          When the message is first created, and when clearBody is called, the body of
          the message is in write-only mode. After the first call to reset has been
          made, the message body is in read-only mode.

          After a message has been sent synchronously, it is recommended that the
          provider has called reset so that the message body is in read-only mode.

          After a message has been sent asynchronously, the provider must call reset
          prior to invoking the CompletionListener so that the message body is in
          read-only mode. This means that the message passed to the
          CompletionListener may be read without the application needing to call
          reset.

          In both cases, after a message has been sent (a synchronous send has returned
          or an asynchronous send has completed and the CompletionListener has been
          invoked), the client that sent it can retain and modify it without affecting
          the message that has been sent. The same message object can be sent multiple
          times.

          When a message has been received, the provider has called reset so that the
          message body is in read-only mode for the client.

          Show
          Nigel Deakin added a comment - - edited Proposed changes (supersed by updated proposal below) javadoc for BytesMessage: Existing text: When the message is first created, and when clearBody is called, the body of the message is in write-only mode. After the first call to reset has been made, the message body is in read-only mode. After a message has been sent, the client that sent it can retain and modify it without affecting the message that has been sent. The same message object can be sent multiple times. When a message has been received, the provider has called reset so that the message body is in read-only mode for the client. Replacement text: (new words marked *thus) When the message is first created, and when clearBody is called, the body of the message is in write-only mode. After the first call to reset has been made, the message body is in read-only mode. After a message has been sent synchronously, it is recommended that the provider has called reset so that the message body is in read-only mode. After a message has been sent asynchronously, the provider must call reset prior to invoking the CompletionListener so that the message body is in read-only mode. This means that the message passed to the CompletionListener may be read without the application needing to call reset. In both cases, after a message has been sent (a synchronous send has returned or an asynchronous send has completed and the CompletionListener has been invoked) , the client that sent it can retain and modify it without affecting the message that has been sent. The same message object can be sent multiple times. When a message has been received, the provider has called reset so that the message body is in read-only mode for the client.
          Hide
          mbwhite added a comment -

          A side issue this raises is if the message object reference by the completion listener is the same object as referenced by the thread that sending the message.

          Another option would be suggest that the message that is passed to the completion listener be a clone in read-only mode. This would let the main thread retain the message in write-only.

          The implication as well is that behavior with 'foreign' messages is identical to 'own' messages. Reasonable - but would be worth adding in the messaging section.

          Show
          mbwhite added a comment - A side issue this raises is if the message object reference by the completion listener is the same object as referenced by the thread that sending the message. Another option would be suggest that the message that is passed to the completion listener be a clone in read-only mode. This would let the main thread retain the message in write-only. The implication as well is that behavior with 'foreign' messages is identical to 'own' messages. Reasonable - but would be worth adding in the messaging section.
          Hide
          Nigel Deakin added a comment - - edited

          Updated proposal

          Here's an updated proposal, drawn more narrowly. It mentions only async send, and uses wording which would not prevent the message passed to the completion listener being a clone, without explicitly saying that it can be.

          In the javadoc for BytesMessage, insert the following new text after the sentence ending "After the first call to reset has been made, the message body is in read-only mode.":

          Inserted text:

          When a BytesMessage is sent asynchronously, the provider must call reset
          on the BytesMessage passed to the CompletionListener. This means that the
          CompletionListener can read the message body without needing to call
          reset.

          Show
          Nigel Deakin added a comment - - edited Updated proposal Here's an updated proposal, drawn more narrowly. It mentions only async send, and uses wording which would not prevent the message passed to the completion listener being a clone, without explicitly saying that it can be. In the javadoc for BytesMessage, insert the following new text after the sentence ending "After the first call to reset has been made, the message body is in read-only mode.": Inserted text: When a BytesMessage is sent asynchronously, the provider must call reset on the BytesMessage passed to the CompletionListener. This means that the CompletionListener can read the message body without needing to call reset.
          Show
          Nigel Deakin added a comment - Updated source for javax.jms.BytesMessage can be viewed at, and downloaded from, https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/BytesMessage.java?rev=317 Diffs can be viewed at https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/BytesMessage.java?rev1=316&rev2=317
          Hide
          Nigel Deakin added a comment -

          Fixed in the JMS 2.0 rev A maintenance release

          Show
          Nigel Deakin added a comment - Fixed in the JMS 2.0 rev A maintenance release

            People

            • Assignee:
              Nigel Deakin
              Reporter:
              Nigel Deakin
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: