jsr368-experts@jms-spec.java.net

[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: Fri, 19 Dec 2014 19:06:02 +0000

I've now drafted the necessary spec and API changes for this issue (the changes I circulated earlier were incomplete).

You can read a nicely-formatted version (and a summary of the problem and the proposed approach) at
https://java.net/jira/browse/JMS_SPEC-158

Once again these changes apply to the classic API but not to the simplified API since new methods don't have an issue
with compatibility. I'd welcome comments on whether you think it would be a good idea to extend these changes to the
simplified API as well.

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 the JMS provider must throw a javax.jms.IllegalStateException.

Replacement text

     In the simplified API, if a MessageListener’s onMessage method calls stop or
     close on its own JMSContext, then the the JMS provider must throw a
     javax.jms.IllegalStateException.

     In the classic and domain-specific APIs, if a MessageListener’s onMessage
     method calls stop or close on its own Connection or close on its own Session,
     then the stop or close method will either fail and throw a
     javax.jms.IllegalStateException, or it will succeed and close the connection.

Changes to Section 6.1.5 “Pausing delivery of incoming messages”

Existing text

     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

     In the simplified API, if the stop method is called from a message listener
     on its own JMSContext then it must throw a javax.jms.IllegalStateException.

     In the classic and domain-specific APIs, 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
     using the classic and domain-specific APIs should avoid calling stop from
     a message listener on its own Connection because this is not portable.

Changed 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.

Replacement text

     In the simplified API, if the close method is called from a message listener
     on its own JMSContext then it must throw a javax.jms.IllegalStateException.

     In the classic and domain-specific APIs, 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
     using the classic and domain-specific APIs should avoid calling close from
     a message listener on its own Connection 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

     In the simplified API, if the close method is called from a message listener
     on its own JMSContext then it must throw a javax.jms.IllegalStateException.

     In the classic and domain-specific APIs, 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
     using the classic and domain-specific APIs should avoid calling close from
     a message listener on its own Session 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]