users@jms-spec.java.net

[jms-spec users] [jsr368-experts] Re: JMS 2.0 Errata: JMS_SPEC-158 (JMS 2.0 introduced incompatible changes to Connection.stop and close and Session.close)

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Tue, 06 Jan 2015 18:15:34 +0000

On 06/01/2015 18:11, Nigel Deakin wrote:
> I've been thinking carefully about what the best option is here and have come to the conclusion that the best
> option is to keep the simplified API consistent with the classic API, and allow stop and close to be supported in all
> cases as an alternative to throwing an exception.

And here are the updated changes proposed to the spec and javadoc. As usual, they can also be found in the JIRA issue at
https://java.net/jira/browse/JMS_SPEC-158?focusedCommentId=382772

*Proposed changes*

*Changes to A.1.19 Clarification: use of stop or close from a message listener (JMS_SPEC-48)*

Existing text

   If a MessageListener’s onMessage method calls stop or close on its own
   Connection, close on its own Session, or stop or close on its own JMSContext,
   then the JMS provider must throw a javax.jms.IllegalStateException.

Replacement text


   If a MessageListener’s onMessage method calls stop or close on its own
   Connection, close on its own Session, stop or close on its own JMSContext,
   or stop on a JMSContext which uses the same connection,
   then the stop or close method will either fail and throw a
   javax.jms.IllegalStateException (for methods on Session and Connection)
   or javax.jms.IllegalStateRuntimeException (for methods on JMSContext),
   or it will succeed and stop or close the Connection, Session or
   JMSContext as appropriate.


*Changes to Section 6.1.5 "Pausing delivery of incoming messages"*

Existing text


   If any message listeners are running when stop is invoked, stop must wait
   until all of them have returned before it may return. While these message
   listeners are completing, they must have the full services of the connection
   available to them.

   A message listener must not attempt to stop its own connection as this would
   lead to deadlock. The JMS provider must detect this and throw a
   javax.jms.IllegalStateException.


Replacement text


   If any message listeners are running when stop is invoked, stop must wait
   until all of them have returned before it may return. While these message
   listeners are completing, they must have the full services of the connection
   available to them.

   If the stop method is called from a message listener on its own Connection or
   JMSContext, or on a JMSContext that uses the same connection, then it will
   either fail and throw a javax.jms.IllegalStateException (in the case of
   Connection) or javax.jms.IllegalStateRException (in the case of JMSContext)
   or it will succeed and stop the connection, blocking until all other message
   listeners that may have been running have returned.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling stop from a message listener on its own Connection or
   JMSContext, or on a JMSContext that uses the same connection, because this is
   not portable.


*Changes to Section 6.1.8 "Closing a connection"*

Existing text


   A message listener must not attempt to close its own connection as this would
   lead to deadlock. The JMS provider must detect this and throw a
   javax.jms.IllegalStateException.

   Closing a Connection, QueueConnection or TopicConnection closes its
   constituent sessions, producers, consumers or queue browsers. The connection
   close is sufficient to signal the JMS provider that all resources for the
   connection should be released.

   Closing a JMSContext closes the underlying session and any underlying producers
   and consumers. If there are no other active (not closed) JMSContext objects
   using the underlying connection then this method also closes the underlying
   connection.


Replacement text (the first two paragraphs below are unchanged):


   Closing a Connection, QueueConnection or TopicConnection closes its
   constituent sessions, producers, consumers or queue browsers. The connection
   close is sufficient to signal the JMS provider that all resources for the
   connection should be released.

   Closing a JMSContext closes the underlying session and any underlying producers
   and consumers. If there are no other active (not closed) JMSContext objects
   using the underlying connection then this method also closes the underlying
   connection.

   If a message listener attempts to close its own connection (either by calling
   close on a Connection object or by calling close on a JMSContext object
   which has no other active JMSContext objects using the underlying connection)
   then it will either fail and throw a javax.jms.IllegalStateException (in the
   case of Connection close) or javax.jms.IllegalStateRException (in the case of
   JMSContext close) or it will succeed and close the connection, blocking until
   all other message listeners that may have been running have returned, and all
   pending receive calls have completed. If close succeeds and the acknowledge
   mode of the session is set to AUTO_ACKNOWLEDGE, the current message will still
   be acknowledged automatically when the onMessage call completes.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling close from a message listener on its own Connection
   or JMSContext because this is not portable.


*Changes to Section 6.2.15 "Closing a session"*

Existing text


   A message listener must not attempt to close its own session as this would
   lead to deadlock. The JMS provider must detect this and throw a
   javax.jms.IllegalStateException


Replacement text


   If a message listener attempts to close its own session (either by calling
   close on a Session object or by calling close on a JMSContext object)
   then it will either fail and throw a javax.jms.IllegalStateException (in the
   case of Session close) or javax.jms.IllegalStateRException (in the case of
   JMSContext close) or it will succeed and close the session, blocking until
   any pending receive call in progress has completed. If close succeeds and
   the acknowledge mode of the session is set to AUTO_ACKNOWLEDGE, the current
   message will still be acknowledged automatically when the onMessage call
   completes.

   Since two alternative behaviors are permitted in this case, applications
   using the classic and domain-specific APIs should avoid calling close from
   a message listener on its own Session or JMSContext because this is not
   portable.


*Changes to the javadocs for javax/jms/Connection.html#close():*

Existing text:


   When this method is invoked, it should not return until message
   processing has been shut down in an orderly fashion. This means that all
   message listeners that may have been running have returned, and that all
   pending receives have returned.


Replacement text:


   When this method is invoked, it should not return until message
   processing has been shut down in an orderly fashion. This means that all
   message listeners that may have been running have returned, and that all
   pending receives have returned.

   However if the close method is called from a message listener on its own
   connection, then it will either fail and throw a
   javax.jms.IllegalStateException, or it will succeed and close the connection,
   blocking until all other message listeners that may have been running have
   returned, and all pending receive calls have completed. If close succeeds and
   the acknowledge mode of the session is set to AUTO_ACKNOWLEDGE, the current
   message will still be acknowledged automatically when the onMessage() call
   completes.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling close from a message listener on its own
   connection because this is not portable.


Existing text:


   A message listener must not attempt to close its own connection as this
   would lead to deadlock. The JMS provider must detect this and throw a
  IllegalStateException.


Replacement text:


   [Delete this text]


*Changes to the javadocs for javax/jms/Connection.html#stop():*

Existing text:


   This call blocks until receives and/or message listeners in progress have
   completed.


Replacement text:


   [Delete this text]


Existing text:


   A call to stop must not return until delivery of messages
   has paused. This means that a client can rely on the fact that none of
   its message listeners will be called and that all threads of control
   waiting for receive calls to return will not return with a
   message until the connection is restarted. The receive timers for a
   stopped connection continue to advance, so receives may time out while
   the connection is stopped.

   If message listeners are running when stop is invoked, the
   stop call must wait until all of them have returned before
   it may return. While these message listeners are completing, they must
   have the full services of the connection available to them.

   A message listener must not attempt to stop its own connection as this
   would lead to deadlock. The JMS provider must detect this and throw a
   IllegalStateException.


Replacement text:


   This call blocks until receives and/or message listeners in progress have
   completed. A call to stop must not return until delivery of messages
   has paused. This means that a client can rely on the fact that none of
   its message listeners will be called and that all threads of control
   waiting for code calls to return will not return with a
   message until the connection is restarted. The receive timers for a
   stopped connection continue to advance, so receives may time out while
   the connection is stopped.

   However if the stop method is called from a message listener on its own
   connection, then it will either fail and throw a
   javax.jms.IllegalStateException, or it will succeed and stop the connection,
   blocking until all other message listeners that may have been running have
   returned.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling stop from a message listener on its own
   Connection because this is not portable.


*Changes to the javadocs for javax/jms/Session.html#close()*

Existing text:


   This call will block until a receive call or message listener in
   progress has completed.


Replacement text:


   This call will block until a receive call or message listener in
   progress has completed.

   However if the close method is called from a message listener on its own
   Session, then it will either fail and throw a javax.jms.IllegalStateException,
   or it will succeed and close the session, blocking until any pending receive
   call in progress has completed. If close succeeds and the acknowledge mode
   of the session is set to AUTO_ACKNOWLEDGE, the current message will still
   be acknowledged automatically when the onMessage call completes.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling close from a message listener on its own
   Session because this is not portable.


Existing text:


    A MessageListener must not attempt to close its own
    Session> as this would lead to deadlock. The JMS provider must
    detect this and throw a IllegalStateException.


Replacement text:


    [Delete this text]


*Changes to the javadocs for javax/jms/JMSContext.html#stop():*

Existing text:


   This call blocks until receives and/or message listeners in progress have
   completed.


Replacement text:


   [Delete this text]


Existing text:


   A call to stop must not return until delivery of messages has paused.
   This means that a client can rely on the fact that none of its message
   listeners will be called and that all threads of control waiting for receive
   calls to return will not return with a message until the connection is
   restarted. The receive timers for a stopped connection continue to advance, so
   receives may time out while the connection is stopped.

   If message listeners are running when stop is invoked, the stop call must wait
   until all of them have returned before it may return. While these message
   listeners are completing, they must have the full services of the connection
   available to them.

   A message listener must not attempt to stop its own JMSContext as this would
   lead to deadlock. The JMS provider must detect this and throw a
   IllegalStateRuntimeException


Replacement text:


   This call blocks until receives and/or message listeners in progress have
   completed. A call to stop must not return until delivery of messages has
   paused. This means that a client can rely on the fact that none of its message
   listeners will be called and that all threads of control waiting for receive
   calls to return will not return with a message until the connection is
   restarted. The receive timers for a stopped connection continue to advance,
   so receives may time out while the connection is stopped.

   However if the stop method is called from a message listener on its own
   JMSContext, or any other JMSContext that uses the same connection,
   then it will either fail and throw a javax.jms.IllegalStateRuntimeException,
   or it will succeed and stop the connection, blocking until all other message
   listeners that may have been running have returned.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling stop from a message listener on its own JMSContext, or
   any other JMSContext that uses the same connection, because this is not
   portable.


*Changes to the javadocs for javax/jms/JMSContext.html#close()*

Existing text:


   When this method is invoked, it should not return until message processing has
   been shut down in an orderly fashion. This means that all message listeners
   that may have been running have returned, and that all pending receives have
   returned. A close terminates all pending message receives on the connection's
   sessions' consumers. The receives may return with a message or with null,
   depending on whether there was a message available at the time of the close.
   If one or more of the connection's sessions' message listeners is processing
   a message at the time when connection close is invoked, all the facilities of
   the connection and its sessions must remain available to those listeners until
   they return control to the JMS provider.


Replacement text:


   When this method is invoked, it should not return until message processing has
   been shut down in an orderly fashion. This means that any message listener
   that may have been running has returned, and that any pending receive call has
   returned. A close terminates any pending receive call on the JMSContext's
   consumers. The receive call may return with a message or with null, depending
   on whether there was a message available at the time of the close. If one of
   the JMSContext's message listeners is processing a message at the time when
   close is invoked from another thread, all the facilities of the JMSContext
   must remain available to it until it returns control to the JMS provider.

   However if the close method is called from a message listener on its own
   JMSContext, then it will either fail and throw a
   javax.jms.IllegalStateRuntimeException, or it will succeed and close the
   JMSContext. If close succeeds and the session mode of the JMSContext is set to
   AUTO_ACKNOWLEDGE, the current message will still be acknowledged automatically
   when the onMessage call completes.

   Since two alternative behaviors are permitted in this case, applications
   should avoid calling close from a message listener on its own
   JMSContext because this is not portable.


Existing text:


   A MessageListener must not attempt to close its own JMSContext as this would
   lead to deadlock. The JMS provider must detect this and throw a
   IllegalStateRuntimeException.


Replacement text:


    [Delete this text]