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]