jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: (JMS_SPEC-48) Specify that connection.stop() or close() may not be called from a MessageListener

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Fri, 16 Sep 2011 16:02:20 +0100

On 16/08/2011 15:05, Nigel Deakin wrote:
> I have created this JIRA issue
> http://java.net/jira/browse/JMS_SPEC-48
>
> This issue was raised by Graham. As always, please do give your comments.


I've not received any comments on this. I've now drafted the following changes to the spec and javadocs. I've also added
this to the JIRA issue, which may be easier to read. As usual, if you wish to make any comments, positive or negative,
or offer expressions of approval or otherwise, please do so in the usual way.

Perhaps the main issue I'd like views on is the proposed prohibition on a message listener calling connection.stop(),
connection.close() or session.close(). I'm suggesting that this must throw a javax.jms.IllegalStateException. Although
I'm suggesting that this is never valid, should we make it mandatory for the provider to detect it and throw an exception?

Section 4.3.4 "Pausing Delivery of Incoming Messages"
-----------------------------------------------------

After:

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

Append:

However a MessageListeners must not call the connection's stop() method as this would lead to deadlock. The JMS provider
must throw a javax.jms.IllegalStateException if Connection.stop() is called from the onMessage method of a
javax.jms.MessageListener.

Section 4.3.5 "Closing a Connection"
------------------------------------

After:

If one or more of the connection’s session’s message listeners is processing a message at the point 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.

Append:

However a message listener must not call the connection's close() method, or the session's close() method, as this
would lead to deadlock. The JMS provider must throw a javax.jms.IllegalStateException if Connection.close() is called
from the onMessage method of a javax.jms.MessageListener.

Section 4.4.1 "Closing a Session"
---------------------------------

After:

When session close is invoked, it should not return until its message processing has been shut down in an orderly
fashion. This means that none of its message listeners are running, and that if there is a pending receive, it has
returned with either null or a message.

Append:

A message listener must not call the connection's close() method, or the session's close() method, as this would lead
to deadlock. The JMS provider must throw a javax.jms.IllegalStateException if Session.stop() is called from the
onMessage method of a javax.jms.MessageListener.

Javadoc for Connection.stop()
-----------------------------

After:

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.

Insert:

However a message listener must not call the connection's stop() method, as this would lead to deadlock. The JMS
provider must throw a javax.jms.IllegalStateException if Connection.stop() is called from the onMessage method of a
javax.jms.MessageListener.

Javadoc for Connection.close()
------------------------------

After:

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.

Append:

However a message listener must not call the connection's close() method, or the session's close() method, as this
would lead to deadlock. The JMS provider must throw a javax.jms.IllegalStateException if Connection.close() is called
from the onMessage method of a javax.jms.MessageListener.

Javadoc for Session.close()
---------------------------

After:

This call will block until a receive call or message listener in progress has completed. A blocked message consumer
receive call returns null when this session is closed.

Append:

A message listener must not call the connection's close() method, or the session's close() method, as this would lead
to deadlock. The JMS provider must throw a javax.jms.IllegalStateException if Session.close() is called from the
onMessage method of a javax.jms.MessageListener.





Nigel

>
> Please
>
> Possible deadlock when calling connection.stop()
> -----------------------------------------------
>
> If the javax.jms.MessageListener method onMessage calls Connection.stop() then, according to the JMS 1.1 specification,
> deadlock may result.
>
> Section 4.3.4 "Pausing Delivery of Incoming Messages" states:
>
> "If MessageListeners are running when stop is invoked, stop must wait until all of them have returned before it may
> return. While these MessageListeners are completing, they must have the full services of the connection available to them."
>
> This means that if a MessageListener calls Connection.stop() then the call to stop() will block forever, waiting for the
> onMessage() method which is calling it to return.
>
> To avoid the possibility of applications causing deadlock, the JMS specification needs to be clarified to state that a
> MessageListener must not call connection.stop().
>
> The section above states that a MessageListener must have "the full services of the connection" available to it. The
> meaning of the term "full services" is not defined, but it needs to be made clear that this does not include the ability
> to call Connection.stop().
>
> Possible deadlock when calling connection.close()
> ------------------------------------------------
>
> A similar issue exists for Connection.close(). If the javax.jms.MessageListener method onMessage calls
> Connection.close() then, according to the JMS 1.1 specification, deadlock may result.
>
> Section 4.3.5 "Closing a connection" states:
>
> "If one or more of the connection's session's message listeners is processing a message at the point 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.
>
> "When connection close 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."
>
> Again, this means that if a MessageListener calls Connection.close() then the call to close() will block forever,
> waiting for the onMessage() method which is calling it to return.
>
> To avoid the possibility of applications causing deadlock, the JMS specification needs similarly to be clarified to
> state that a MessageListener must not call connection.close().
>
> The section above states that a MessageListener must have "all the facilities of the connection" available to it. The
> meaning of the term "all the facilities" is again not defined, but it needs to be made clear that those does not include
> the ability to call Connection.close().
>
> Enforcement
> -----------
>
> JMS provider should be required to throw a javax.jms.IllegalStateException if Connection.stop() or Connection.close() is
> called from the onMessage method of a javax.jms.MessageListener.
>
>