[JMS_SPEC-4] Properties on Messages should follow builder pattern. Created: 11/May/11  Updated: 10/Apr/12  Resolved: 10/Apr/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Won't Fix Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Currently, methods such as javax.jms.Message.setBoolean return void. However, in recent years the builder pattern has grown in adoption, allowing developers to chain method calls by having the method return the object that the method was performed upon. If the property methods return these objects, then the code would look much cleaner.



 Comments   
Comment by abien [ 18/Jun/11 ]

I would change the syntax and use a withBoolean, instead of setBoolean in general. setters in Java do imply void return type.
The final call of the method build() could verify the consistency of all set values and message.

Comment by Nigel Deakin [ 28/Feb/12 ]

Are you referring to the methods for setting message properties, such as setBooleanProperty(String name, boolean value)?

I'll raise this with the expert group. Tagging for review prior to the public draft.

This is an issue of API style, but my inclination is to avoid changing this long-established API.

It might be argued that if a method such as setBooleanProperty(String name, boolean value) was to return a value, it should return the previous value of the property, just like the equivalent methods on java.util.Map and java.util.Property.

Nigel

Comment by Nigel Deakin [ 10/Apr/12 ]

Although the builder pattern is an established design pattern, the JMS API was defined a long time ago and adding new methods at this stage would simply be undesirable bloat.

I am therefore closing this issue as "won't fix".





[JMS_SPEC-61] Selector on JMS body Created: 17/Nov/11  Updated: 08/Jan/13  Resolved: 10/Apr/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: koen.serneels Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

It would be a very nice feature to apply selectors on the message body.
Possibly using regexp, or XPath in case of TextMessages.
The same for key/value pairs of MapMessage.



 Comments   
Comment by rdohna [ 21/Nov/11 ]

There may be use-cases, but I doubt that this is a good path to follow. It would add a lot of complexity to the spec, and the performance will probably be terrible, as providers can create something similar to an index on all properties, but not on the payload. And the message would have to be unpacked by every filter around, while it's not so easy to see if there could be messages that slip through all of your selectors... or be matched by more than one!

Take it from a different perspective: You suggest regex and/or XPath. What if the content is JSON, or POJOs, or Byte-Arrays, or streamed messages, or ... You'd open up a can of worms where every use-case would require a change to the spec. So you'd have to find a generic form - some kind of filter SAM type seems a good option here. I put such filters exclusively into a content based router, i.e. it does not invoke the business code directly, but forwards the messages to several more specific destinations. This keeps the routing logic in one place where it's easier to make sure that there is no gap or overlap in your logic; and every message would have to be unpacked exactly two times, not up to n times with n selectors.

Comment by Nigel Deakin [ 09/Dec/11 ]

As the previous comment said, we need to be wary of introducing features which are impossible for the JMS provider to implement efficiently. Message properties were invented to allow the provider to handle selectors on a limited amount of information without the need to unmarshall/uncompress/index the entire message payload.

I'll raise it with the expert group after the early draft to see what views there are, especially from the representatives of JMS vendors. If you have any particular priorities please state them (and give as much justification as you can).

Nigel

Comment by Nigel Deakin [ 10/Apr/12 ]

Following a discussion with the JSR 343 expert group, I am rejecting this proposal as it would be contrary to the way in which JMS is designed. Currently message selectors can be used to filter messages on the basis of application-defined message properties. JMS supports message properties expressly to avoid the need for the message selector mechanism to examine the message body, which might be inefficient.

Closing this issue with a resolution of "Won't fix"

Comment by axel_podehl [ 08/Jan/13 ]

I agree with closing this issue.

The implementation of regexp or XPath filtering should be implemented by JMS providers, but can't be defined by the JMS standard. There are too many ways to define these filters and each regex or Xpath package used would have slight differences in syntax.

Also, there's nothing preventing JMS providers to extend the notion of a JMS selector.
In addition to supporting the standard JMS selector, a JMS provider can extend the notion of this selector.

For example to apply the JMS selectors also on the properties of a MapMessages, there's an open source package: http://jamsel.sourceforge.net/

In another product, you can use these types of JMS selector strings:

::regex::.trader=peter.
::xpath::/trade[trader='peter']
::request::fromTime=2002-12-31T14:15:16.123456





[JMS_SPEC-56] Enhance the EJB specification to support the delivery of messages in batches to MDBs Created: 08/Nov/11  Updated: 01/May/12  Resolved: 01/May/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JMS_SPEC-36 Allow messages to be delivered asynch... Open
depends on EJB_SPEC-44 Enhance the EJB specification to supp... Resolved
Tags: eg, jms20-jsr345

 Description   

This is a request for changes to the EJB specification to support the asynchronous delivery of messages to a message-driven bean in batches.

This new feature is described in JMS_SPEC-36. To support this there will be a new listener interface javax.jms.BatchMessageListener, which provides the method onMessages(Message[] messages).

Where batch delivery is not required, the existing javax.jms.MessageListener interface and its method onMessage(Message message) will continue to be used as before.

The following changes to the EJB specification are suggested (references are to the EJB 3.1 specification)

Section 5.4.2 "The Required Message Listener Interface"


Change: "The message-driven bean class's implementation of the javax.jms.MessageListenerinterface distinguishes the message-driven bean as a JMS message-driven bean."

To: "The message-driven bean class's implementation of the javax.jms.MessageListener or javax.jms.BatchMessageListener interface distinguishes the message-driven bean as a JMS message-driven bean."

An additional node should be added to state that a JMS message-driven bean may implement either of these interfaces or both.

5.6.2 "Message-Driven Bean Class"


Change: "In the case of JMS, this is the javax.jms.MessageListener interface."

To: "In the case of JMS, this is either the javax.jms.MessageListener or javax.jms.BatchMessageListener interface."

13.6.3.2 "REQUIRED£


In all four places change: "onMessage method"

to: "onMessage or onMessages method"

21.3.5 "JMS 1.1 Requirements"


Change name of section to: "JMS 2.0 Requirements"

Change: "An implementation requiring the full EJB 3.1 API must include the JMS 1.1 extension"

To: "An implementation requiring the full EJB 3.2 API must include JMS 2.0"

In the fourth paragraph,

Change: "Enterprise beans must not call the javax.jms.MessageConsumer.setMessageListener or javax.jms.MessageConsumer.getMessageListener method."

To: "Enterprise beans must not call the javax.jms.MessageConsumer.setMessageListener, javax.jms.MessageConsumer.setBatchMessageListener, javax.jms.MessageConsumer.getMessageListener or javax.jms.MessageConsumer.getBatchMessageListener methods."

5.4.14 "Activation Configuration Properties"


This section introduces a list of activation configuration properties for JMS message-driven beans. An additional section should be inserted which describes the additional properties needed for batch delivery:

Insert new section: 5.4.<n> "Batch delivery" as follows:

If the JMS Message-driven bean implements the javax.jms.BatchMessageListener interface then the following activation configuration properties may be used to configure batch delivery:

  • batchSize: If set to greater than zero, messages will be delivered by calling the onMessages(Message[] messages) method. The bean class must implement javax.jms.BatchMessageListener. Messages will be delivered in batches of up to batchSize messages. The actual batch size used may be any value between one and the specified batchSize. It is invalid to specify a value greater than zero if the bean class does not implement javax.jms.BatchMessageListener.
  • batchTimeout: If batch delivery is used, this specifies the maximum number of milliseconds that the JMS provider may defer message delivery for in order to assemble a batch of messages that is as large as possible but no larger than the batch size.


 Comments   
Comment by Nigel Deakin [ 23/Nov/11 ]

This issue has now been forwarded to the EJB 3.2 expert group as EJB_SPEC-44. Please make further comments there, not here.

Comment by Nigel Deakin [ 01/May/12 ]

Following the decision to defer JMS_SPEC-36 (Allow messages to be delivered asynchronously in batches) I am going to close this issue. If changes are needed to the MDB specification in the future a new issue will be logged.

Comment by Nigel Deakin [ 01/May/12 ]

Closing as "Won'tFix" because that's the nearest resolution I can see to "withdrawn".





[JMS_SPEC-10] Support for Cloud Services Created: 18/May/11  Updated: 10/May/13  Resolved: 02/Mar/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: fribeiro Assignee: Nigel Deakin
Resolution: Invalid Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

In addition to the vendors of on-premises software, we should hear from vendors of cloud services (like StormMQ) about any changes to the API that they think would make it easier to implement it.



 Comments   
Comment by abien [ 18/Jun/11 ]

What is the point of your suggestion? Just vendor involvement?

Comment by fribeiro [ 02/Jan/12 ]

Yes, I think it would be hear from them, as well as from the on-premises vendors already on board.

Comment by Nigel Deakin [ 02/Mar/12 ]

The JSR 343 expert group is open to suggestions for new features which will assist could services. Feel free to contact specific organisations and encourage them to get involved.

Since this isn't a specific requirement, I'm going to close this issue. However specific proposals remain welcome. If you'd simply like to discuss an issue, please raise it on the user alias.

Nigel

Comment by fribeiro [ 10/May/13 ]

You may want to go ahead and close the issue.





[JMS_SPEC-8] Add Reference to URI Scheme Created: 17/May/11  Updated: 10/May/13  Resolved: 10/May/13

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: fribeiro Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

The IETF has published an "official" URI scheme for JMS that should probably be referred to by the next release of the spec.



 Comments   
Comment by fribeiro [ 17/May/11 ]

http://www.rfc-editor.org/rfc/rfc6167.txt

Comment by Nigel Deakin [ 12/Mar/12 ]

I'm not sure this is needed, or even appropriate given that this is a completely separate specification. However this will be raised with the expert group for possible inclusion in the JMS 2.0 public draft.

Comment by fribeiro [ 10/May/13 ]

You may want to go ahead and close the issue.

Comment by Nigel Deakin [ 10/May/13 ]

Closed at request of submitter.





[JMS_SPEC-6] Add Reference to SOAP Binding Created: 17/May/11  Updated: 10/May/13  Resolved: 10/May/13

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: fribeiro Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

The W3C has developed an "official" SOAP binding for JMS that should probably be referred to by the next release of the spec.



 Comments   
Comment by John D. Ament [ 17/May/11 ]

Can you link to this SOAP binding?

Comment by fribeiro [ 17/May/11 ]

http://www.w3.org/TR/soapjms/

Comment by Nigel Deakin [ 02/Mar/12 ]

What would you like to see added to the JMS spec? It's not obvious that any change is needed; the document referred to is dependent on JMS, not the other way round.

I'll raise this with the expert group (which includes representatives of the organisations that proposed that document).

Comment by fribeiro [ 10/May/13 ]

You may want to go ahead and close the issue.

Comment by Nigel Deakin [ 10/May/13 ]

Closed at request of submitter. Marking as "won't fix".





[JMS_SPEC-19] Support for Multi-Part Messages Created: 24/May/11  Updated: 10/May/13  Resolved: 10/May/13

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: fribeiro Assignee: Unassigned
Resolution: Invalid Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-forreview-vague

 Description   

Has it ever considered by the EG to add support to multi-part messages?



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 ]

Can you please provide more information about what you are suggesting? This is too vague a description to be able to review.

Nigel

Comment by fribeiro [ 10/May/13 ]

You may want to go ahead and close the issue.

Comment by Nigel Deakin [ 10/May/13 ]

Closed as requested by submitter, and because there isn't enough information to review this issue.





[JMS_SPEC-17] Durable subscription iterator Created: 24/May/11  Updated: 09/Mar/12  Resolved: 09/Mar/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: colincrist Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-18 Standard set of server JMX MBeans Open
duplicates JMS_SPEC-59 Basic metadata/management via JMS Open

 Description   

As a monitoring client I would like to list all the durable subscriptions the login is permissioned to see., i.e. the clientID, durableName and any selector.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 ]

I'm merging this proposal with two more general proposals:

JMS_SPEC-59 - which covers general non-JMX metadata queries
JMS_SPEC-18 - which covers general JMX facilities

I'm going to close this issue as a duplicate of those. Feel free to contribute comments to those issues.





[JMS_SPEC-16] Depth of messages for a durable subscription Created: 24/May/11  Updated: 09/Mar/12  Resolved: 09/Mar/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: colincrist Assignee: Unassigned
Resolution: Duplicate Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-18 Standard set of server JMX MBeans Open
duplicates JMS_SPEC-59 Basic metadata/management via JMS Open

 Description   

As a client I would like to get the current approximate number of pending messages for a durable subscription. All existing providers give this information via a custom API or JMX at present.



 Comments   
Comment by fribeiro [ 24/May/11 ]

My first comment on JMS_SPEC-15 also applies here.

Comment by Nigel Deakin [ 09/Mar/12 ]

I'm merging this proposal with two more general proposals:

JMS_SPEC-59 - which covers general non-JMX metadata queries
JMS_SPEC-18 - which covers general JMX facilities

I'm going to close this issue as a duplicate of those. Feel free to contribute comments to those issues.





[JMS_SPEC-158] JMS 2.0 introduced incompatible changes to Connection.stop and close and Session.close Created: 22/Sep/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks JMS_SPEC-159 Allow stop and close to be called fro... Open
Tags: jms20-errata

 Description   

Background: JMS 1.1

The JMS 1.1 specification stated that the stop method on Connection, and the close methods on Connection, Session and MessageConsumer must not return until any message listeners have returned.

This had the unfortunate consequence of requiring that if these methods were called from a message listener on its own Connection, Session or MessageConsumer then deadlock would occur and these methods would never return.

This error in JMS 1.1 was well-known to developers of JMS 1.1 implementations. Some vendors decided (many years ago) that it was unacceptable to cause customer applications to block for ever and so took the decision to ignore the requirement that these methods block for ever when called from a message listener on its own Connection, Session or MessageConsumer.

Changes in JMS 2.0

The JMS 2.0 specification (JMS_SPEC-48) addressed this error by amending the required behaviour to avoid the possibility of deadlock. It did so in two different ways.

  • In the case of the stop method on Connection, and the close methods on Connection and Session, the requirement to block for ever when these methods were called from a message listener (on its own Connection or Session) was replaced by the requirement to throw a javax.jms.IllegalStateException.
  • However in the case of the close method on MessageConsumer, the requirement to block for ever when this method was called from a message listener (on its own MessageConsumer) was removed by allowing the close method to return normally.

The problem

The change introduced in JMS 2.0 replaces the requirement to block for ever with the requirement to throw an exception. The expert group considered that this was not an incompatible change since the old behaviour was clearly unacceptable and no application would rely on it.

However this change does force an incompatible change on those JMS vendors which, many years ago, took the unilateral decision to ignore the erroneous requirement in JMS 1.1. The new requirements of JMS 2.0 means that existing applications which called stop and close from within a message listener, and which previously worked just fine, will now encounter an exception and fail.

Although, strictly speaking, JMS vendors that ignored the original JMS 1.1 requirement were violating the specification, this was not an unreasonable thing to do given that JMS 1.1 was clearly erroneous and that no further versions of JMS were developed until JMS 2.0 over a decade later.

This means that, even though the change in JMS 2.0 was technically valid, in practice it has introduced an incompatible change for some JMS vendors which would force them to break existing applications.

The solution

It is proposed an errata be added to JMS 2.0 to state that the requirement to throw an exception is optional. JMS vendors would be allowed to decide whether these methods should throw an exception or return normally. This would allow vendors which have long allowed these methods to return normally to continue to do so, and avoid breaking existing applications.

Existing JMS 2.0 implementations would not need to change.

Since this would mean that some vendors would throw an exception and some would not, applications which relied on these methods being called from a message listener would not be portable, and the specification would need to warn of this.

(In the longer term, this lack of portability could be resolved by removing the option to throw an exception. That is the subject of a separate issue JMS_SPEC-159).



 Comments   
Comment by Nigel Deakin [ 19/Dec/14 ]

(These proposals are now superseded by these updated proposals)

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]

Comment by Nigel Deakin [ 19/Dec/14 ]

Views are also invited on whether the same changes should be made to the new JMS 2.0 methods JMSContext#stop and JMSContext#close. The current proposal is to leave these methods unchanged since there is no need to change them, and it is better to stick with the current, unambiguous, definition.

However there is one reason why we might want to keep the simplified API consistent with the classic API, and allow stop and close to be called in the simplified API as well as in the classic API. This is if we decided that it is actually better to allow stop and close to be called than throw an exception (i.e. requiring an exception was a mistake).

If we decided that, then in JMS 2.1 we could remove the option to throw an exception (which we could reasonably argue wasn't an incompatible change to applications).

I'm attracted by this, as I've received complaints that requiring an exception to be thrown has made it harder to write applications, but unless there is clear support for this we should stick to the more limited proposals above.

Comment by chris.barrow [ 06/Jan/15 ]

I am strongly in favor of this suggestion (keep the simplified API consistent with the classic API, and allow stop and close to be called in the simplified API as well as in the classic API), for several reasons:

  1. consistency is always better
  2. the ability to call stop and close from within a message listener is a useful feature for flow control purposes (as Matthew pointed out in an e-mail discussion), or to allow remote control of an application.
  3. as a general principle we should avoid imposing unnecessary restrictions on API usage, to improve usability. I do not see any compelling reason to forbid calling Connection.stop or start from within a MessageListener, since by definition JMS implementations are in control of listener execution, so can avoid deadlocks.

Then for 2.1 we can remove the option to throw an exception.

Comment by Nigel Deakin [ 06/Jan/15 ]

Further to my comment here, and in response to feedback here, on the community mailing list, and directly to me, I'm now proposing to allow stop and close to be called in the simplified API as well as in the classic API. Here are the updated changes:

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.IllegalStateRuntimeException (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) or javax.jms.IllegalStateRuntimeException (in the case of
JMSContext), 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) or javax.jms.IllegalStateRuntimeException (in the case of
JMSContext), 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
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:

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: (the first paragraph below is unchanged)

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.

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. A blocked message consumer receive call returns null when this session is closed.

Replacement text: (the first paragraph below is unchanged)

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.

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:

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: (the first paragraph below is unchanged)

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.

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: (the first paragraph below is unchanged)

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]

Comment by chris.barrow [ 06/Jan/15 ]

This looks fine. Just one thing, in a few places in the replacement texts there is mention of javax.jms.IllegalStateRException. I presume that is intended to read javax.jms.IllegalStateRuntimeException.

Comment by Nigel Deakin [ 07/Jan/15 ]

Thanks for reporting this typo. I've corrected the proposed changes to say javax.jms.IllegalStateRuntimeException

Comment by Nigel Deakin [ 08/Jan/15 ]

Draft spec now updated.
PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=312.
Latest PDF at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf

Updated source for javax.jms.Connection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Connection.java?rev=312
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Connection.java?rev1=311&rev2=312

Updated source for javax.jms.Session can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Session.java?rev=312
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Session.java?rev1=311&rev2=312

Updated source for javax.jms.JMSContext can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev=312
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev1=311&rev2=312

Comment by chris.barrow [ 08/Jan/15 ]

I have reviewed the draft spec (PDF) and the changes look fine to me.

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-163] Javadoc for JMSContext#setClientID contains obsolete MessageContext reference Created: 01/Dec/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The javadoc for JMSContext#setClientID contains an obsolete mention of MessageContext. This should be changed to JMSContext



 Comments   
Comment by Nigel Deakin [ 01/Dec/14 ]

Changes to javadoc for JMSContext#setClientID

Existing text:

Alternatively, a client can set the client identifier for the MessageContext's connection
using a provider-specific value.

Replacement text:

Alternatively, a client can set the client identifier for the JMSContext's connection
using a provider-specific value.

Comment by Nigel Deakin [ 07/Jan/15 ]

Updated source for javax.jms.JMSContext can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev=310
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev1=309&rev2=310

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-162] Typos in section 7.3 "Asynchronous send" Created: 01/Dec/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

There are two minor typos in the JMS 2.0 specification, section 7.2 "Asynchronous send".

In the third bullet point, change "synchronously" to "asynchronously using"

In the fourth bullet point, change "synchronously" to "asynchronously".



 Comments   
Comment by Nigel Deakin [ 01/Dec/14 ]

Changes to section 7.3. Asynchronous send

Existing text:

  • In the domain-specific API for point-to-point messaging a QueueSender may be used to send a message synchronously any of the methods inherited from MessageProducer and listed above.
  • In the domain-specific API for pub/sub messaging a TopicPublisher may be used to send a message synchronously using any of the methods inherited from MessageProducer and listed above.

Replacement text:

  • In the domain-specific API for point-to-point messaging a QueueSender may be used to send a message asynchronously using any of the methods inherited from MessageProducer and listed above.
  • In the domain-specific API for pub/sub messaging a TopicPublisher may be used to send a message asynchronously using any of the methods inherited from MessageProducer and listed above.
Comment by Nigel Deakin [ 07/Jan/15 ]

Draft spec now updated.
PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=311.
Latest PDF at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-161] serialVersionUID of JMSException has changed from JMS 1.1 to JMS 2.0 Created: 19/Nov/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to MQ-359 serialVersionUID of JMSException has ... Open
Tags: jms20-errata

 Description   

The serialVersionUID of javax.jms.JMSException has changed from JMS 1.1 to JMS 2.0, which means that if an instance of this exception is serialized using JMS 1.1 it cannot be deserialized using JMS 2.0 or vice versa.



 Comments   
Comment by Nigel Deakin [ 19/Nov/14 ]

Although these classes are defined in the JMS specification, their implementation is, strictly speaking, part of the RI. Fixing this issue will not require a revision to the spec.

Comment by Nigel Deakin [ 25/Nov/14 ]

Now fixed in the reference implementation. See MQ-359 for fix details.

This issue will be updated when the new API jar is released.

Comment by Nigel Deakin [ 09/Dec/14 ]

A new JMS 2.0 API jar containing this fix has been released to Maven Central at
http://search.maven.org/#artifactdetails%7Cjavax.jms%7Cjavax.jms-api%7C2.0.1-b01%7Cjar
This is a release candidate (hence the b01 suffix), for the purposes of testing.

The final release of this jar will occur at the same time as the JMS 2.0 errata release.

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the release of the JMS 2.0.1 API jar that accompanied the JMS 2.0 rev A maintenance release





[JMS_SPEC-165] Error in javadoc for Connection#stop and JMSContext#stop Created: 08/Jan/15  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1, 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The JMS 1.1 javadocs for Connection#stop contains the following text:

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

The same text is found in the JMS 2.0 javadocs for Connection#stop and for JMSContext#stop.

This text is incorrect because it suggests that the call to stop is required to block until all calls to receive have returned. There is no mention of this requirement in the specification itself and it is contradicted by the text that follows it in the javadocs for Connection#stop:

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.

This means that:

  • a call to stop does not force all pending receives to return prematurely.
  • a call to stop is not required to block until all pending receives reach their timeout period (especially as that might be infinite)
  • after the call to stop has returned, pending receives will continue to block until they either (1) reach their timeout and return null or (2) the connection is restarted and a message becomes available, whichever occurs first.

It is suggested that, to keep things simple, we don't try to completely rewrite this but simply delete the incorrect sentence. Note that the requirement to block until message listeners have returned is already covered by the sentence:

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.



 Comments   
Comment by Nigel Deakin [ 08/Jan/15 ]

Proposed change to Javadocs for Connection#stop

Existing text:

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

Proposed text:

[Delete this text]

Proposed change to Javadocs for JMSContext#stop

Existing text:

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

Proposed text:

[Delete this text]

Comment by Nigel Deakin [ 09/Jan/15 ]

Updated source for javax.jms.Connection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Connection.java?rev=314
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Connection.java?rev1=313&rev2=314

Updated source for javax.jms.JMSContext can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev=314
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/JMSContext.java?rev1=313&rev2=314

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-164] Typos in section 7.3.5 and 12.2: Change Session to MessageProducer Created: 02/Jan/15  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

JMS 2.0 section 7.3.5. "Restrictions on usage in Java EE" and section 12.2 "Restrictions on the use of JMS API in the Java EE web or EJB container" contain references to various send methods. The spec states that these are on javax.jms.Session when they are actually on javax.jms.MessageProducer.

Changes to 7.3.5. "Restrictions on usage in Java EE"

Existing text

  • javax.jms.Session method send(Message message, CompletionListener completionListener)
  • javax.jms.Session method send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)
  • javax.jms.Session method send(Destination destination, Message message, CompletionListener completionListener)
  • javax.jms.Session method send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)

Replacement text

  • javax.jms.MessageProducer method send(Message message, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Destination destination, Message message, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)

Changes to 12.2 "Restrictions on the use of JMS API in the Java EE web or EJB container"

Existing text

  • javax.jms.Session method send(Message message, CompletionListener completionListener)
  • javax.jms.Session method send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)
  • javax.jms.Session method send(Destination destination, Message message, CompletionListener completionListener)
  • javax.jms.Session method send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)

Replacement text

  • javax.jms.MessageProducer method send(Message message, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Destination destination, Message message, CompletionListener completionListener)
  • javax.jms.MessageProducer method send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener)


 Comments   
Comment by Nigel Deakin [ 07/Jan/15 ]

Draft spec now updated.
PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=309.
Latest PDF at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-160] JMS API source contains self-closing HTML tags Created: 17/Nov/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The JMS API source contains self-closing HTML tags in its javadoc comments. For example, the source of javax.jms.Message contains the tag <br/>.

To reproduce the issue, simply run the javadoc command on the API source using the Java 8 version of javadoc.

Self-closing tags are not valid HTML and they cause the Java 8 version of javadoc to fail (unless a flag has been set to suppress this).

It looks as if this incorrect HTML was added in JMS 2.0.



 Comments   
Comment by Nigel Deakin [ 01/Dec/14 ]

Changes to javadoc for Message

Change <br/> to <br> in 12 places.

Changes to javadoc for JMSConsumer

Change <br/> to <br> in 15 places.

Comment by Nigel Deakin [ 07/Jan/15 ]

Source code now updated.

Updated source for javax.jms.Message can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Message.java?rev=303
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Message.java?rev1=302&rev2=303

Updated source for javax.jms.JMSConsumer can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/JMSConsumer.java?rev=303
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/JMSConsumer.java?rev1=302&rev2=303

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-157] JMS 2.0 introduced an incompatible restriction on creating two sessions per connection in Java EE Created: 02/Sep/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The background

Prior to JMS 2.0, a number of requirements for the behaviour of the JMS API in Java EE applications were defined in the Java EE 6 platform specification, but were not mentioned in the JMS specification or javadocs. This was confusing for users. To remedy this, JMS 2.0 was extended to incorporate these requirements.

Those extensions to JMS 2.0 were intended to be a rearrangement and clarification of existing requirements and were not intended to introduce changes which were incompatible with Java EE 6 or which would require changes to existing applications.

However it appears that JMS 2.0 has inadvertently introduced an incompatible change related to the use of the Connection method createSession in a Java EE web or EJB application when a session already exists for that connection.

The problem

In the Java EE 6 specification, section EE 6.7 "Java Message Service (JMS) 1.1 Requirements" states that

Application components in the web and EJB containers must not attempt to create more than one active (not closed) Session object per connection. An attempt to use the Connection object’s createSession method when an active Session object exists for that connection should be prohibited by the container. The container may throw a JMSException if the application component violates this restriction. Application client containers must support the creation of multiple sessions for each connection.

This wording states that applications "must" not attempt to create more than one session per connection in the Java EE web or EJB containers. However it only says that the container "should" prohibit this, and that it "may" throw an exception. In accordance with the generally-accepted interpretations of the words "should" and "may", this means that it is optional whether or not the createSession method throws an exception.

When this requirement was incorporated into the JMS 2.0 specification, it became the following text in JMS 2.0 section 12.2.

Applications running in the Java EE web and EJB containers must not attempt to create more than one active (not closed) Session object per connection.

If an application attempts to use the Connection object’s createSession method when an active Session object exists for that connection then a JMSException should be thrown.

If an application attempts to use the JMSContext object’s createContext method then a JMSRuntimeException should be thrown, since the first JMSContext already contains a connection and session and this method would create a second session on the same connection.

This wording continues to use the word "should" which keeps it optional whether or not the createSession method (or createContext method) throws an exception.

In addition to this change, the javadoc for these methods was also updated. Unfortunately the wording used was inconsistent with that in section 12.2.

The javadoc for createSession states that:

Applications running in the Java EE web and EJB containers must not attempt to create more than one active (not closed) Session object per connection. If this method is called in a Java EE web or EJB container when an active Session object already exists for this connection then a JMSException will be thrown.

The words "will be thrown" make it obligatory for the createSession method to throw an exception. This introduces an additional restriction which was not in Java EE 6 (and is not in JMS 2.0 section 12.2) and inadvertently introduces an incompatible change which may cause existing applications to fail.

The corresponding javadoc for createContext contains a similar wording:

This method must not be used by applications running in the Java EE web or EJB containers because doing so would violate the restriction that such an application must not attempt to create more than one active (not closed) Session object per connection. If this method is called in a Java EE web or EJB container then a JMSRuntimeException will be thrown.

This method is new in JMS 2.0 so there is no compatibility issue. Nevertheless the words "will be thrown" make it obligatory for the createContext method to throw an exception, which is inconsistent with the wording in JMS 2.0 section 12.2 which implies that throwing an exception is optional.



 Comments   
Comment by Nigel Deakin [ 02/Dec/14 ]

Proposed changes (superseded by updated proposals below)

JMS specification section 12.2 "Restrictions on the use of JMS API in the Java EE web or EJB container": No changes are proposed.

JMS specification section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container". Existing text:

The following method to create a JMSContext from an existing JMSContext is
not permitted in a Java EE web or EJB container because it would create a
second session on an existing connection, which is not permitted in a Java EE
web or EJB container.

Replacement text:

The JMS API defines the following method to create a JMSContext from an
existing JMSContext. Applications must not call this method in a Java EE
web or EJB container. See section 12.2 "Restrictions on the use of JMS API
in the Java EE web or EJB container".

JMS specification section 2.8.2. "Key features of the simplified API": Existing text

Applications running in the Java EE web and EJB containers are not permitted
to create more than one active session on a connection...

Modified text: (changed words thus)

Applications running in the Java EE web and EJB containers must not
create more than one active session on a connection...

It is proposed that the javadoc for the Connection object’s three createSession methods be changed to make it consistent with the Java EE 6 specification and with JMS 2.0 section 12.2.

Javadoc for Connection.html#createSession(): Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException will be thrown.

Replacement text: (changed word thus)

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException may be thrown.

Javadoc for Connection.html#createSession(int): Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException will be thrown.

Replacement text: (changed word thus)

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException may be thrown.

Javadoc for Connection.html#createSession(boolean, int): Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException will be thrown.

Replacement text: (changed word thus)

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If this
method is called in a Java EE web or EJB container when an active Session object
already exists for this connection then a JMSException may be thrown.

It is also proposed to make the same change to the JMSContext object’s createContext method to to make it consistent with JMS 2.0 section 12.2.

Javadoc for JMSContext.html: Existing text

Applications running in the Java EE web and EJB containers are not permitted to
create more than one active session on a connection so combining them in a single
object takes advantage of this restriction to offer a simpler API.

However applications running in a Java SE environment or in the Java EE application
client container are permitted to create multiple active sessions on the same connection.

Replacement text: (changed words thus)

Applications running in the Java EE web and EJB containers must not
create more than one active session on a connection so combining them in a single
object takes advantage of this restriction to offer a simpler API.

However applications running in a Java SE environment or in the Java EE application
client container may create multiple active sessions on the same connection.

Javadoc for JMSContext.html#createContext(int): Existing text

This method must not be used by applications running in the Java EE web or EJB containers
because doing so would violate the restriction that such an application must not attempt
to create more than one active (not closed) Session object per connection. If this method
is called in a Java EE web or EJB container then a JMSRuntimeException will be thrown.

Replacement text: (changed word thus)

This method must not be used by applications running in the Java EE web or EJB containers
because doing so would violate the restriction that such an application must not attempt
to create more than one active (not closed) Session object per connection. If this method
is called in a Java EE web or EJB container then a JMSRuntimeException may be thrown.

Comment by Nigel Deakin [ 18/Dec/14 ]

Here is an updated proposal for this issue. As with the previous proposal, this would relax from must to should the requirement for the three createSession methods to throw an exception if the application tries to create two sessions for the same connection in a Java EE web or EJB application. This change is necessary to maintain the less strict wording in the Java EE 6 specification and avoid introducing an incompatible change to createSession(boolean, int).

However this proposal leaves unchanged the requirement for the simplified API to throw an exception in the same circumstances. This requirement is already in the javadocs (and enforced by CTS). However the text in section 12.2 of the specification is inconsistent so I am proposing to change it to match the javadocs.

In both cases, the spec will continue to say that the application must not do these things, since this is the wording used in Java EE 6. Note that this is an obligation on the application, and not on the JMS implementation.

JMS specification section 12.2 "Restrictions on the use of JMS API in the Java EE web or EJB container"

Existing text:

Applications running in the Java EE web and EJB containers must not attempt
to create more than one active (not closed) Session object per connection.

  • If an application attempts to use the Connection object’s createSession
    method when an active Session object exists for that connection then a
    JMSException should be thrown.
  • If an application attempts to use the JMSContext object’s createContext
    method then a JMSRuntimeException should be thrown, since the first
    JMSContext already contains a connection and session and this method would
    create a second session on the same connection.

Replacement text (changed words thus)

Applications running in the Java EE web and EJB containers must not attempt
to create more than one active (not closed) Session object per connection.

  • If an application attempts to use the Connection object’s createSession
    method when an active Session object exists for that connection then a
    JMSException should be thrown.
  • If an application attempts to use the JMSContext object’s createContext
    method then a JMSRuntimeException must be thrown, since the first
    JMSContext already contains a connection and session and this method would
    create a second session on the same connection.

JMS specification section 2.8.2. "Key features of the simplified API"

Existing text

Applications running in the Java EE web and EJB containers are not permitted
to create more than one active session on a connection...

Modified text: (changed words thus)

Applications running in the Java EE web and EJB containers must not
create more than one active session on a connection...

Javadoc for Connection.html#createSession()

Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException will be thrown.

Replacement text:

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException may be thrown.

Javadoc for Connection.html#createSession(int)

Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException will be thrown.

Replacement text:

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException may be thrown.

Javadoc for Connection.html#createSession(boolean, int)

Existing text

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException will be thrown.

Replacement text:

Applications running in the Java EE web and EJB containers must not attempt to
create more than one active (not closed) Session object per connection. If
this method is called in a Java EE web or EJB container when an active Session
object already exists for this connection then a JMSException may be thrown.

Comment by Nigel Deakin [ 09/Jan/15 ]

Draft spec now updated.
PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=313.
Latest PDF at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf

Updated source for javax.jms.Connection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Connection.java?rev=313
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Connection.java?rev1=312&rev2=313

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-155] JMS 2.0 introduced incompatible changes to createSession(bool,int) Created: 16/Jul/14  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The background

Prior to JMS 2.0, a number of requirements for the behaviour of the JMS API in Java EE applications were defined in the Java EE 6 platform specification and in the EJB 3.1 specification, but were not mentioned in the JMS specification or javadocs. This was confusing for users. To remedy this, JMS 2.0 was extended to incorporate these requirements.

Those extensions to JMS 2.0 were intended to be a rearrangement and clarification of existing requirements and were not intended to introduce changes which were incompatible with Java EE 6 and EJB 3.1 or which would require changes to existing applications.

However it appears that JMS 2.0 may have introduced a number incompatible changes related to the behaviour of the ConnectionFactory method createSession(boolean transacted, int acknowledgeMode) in a Java EE web or EJB application in the case where there is no active JTA transaction in progress and the application has specified the parameter values (true, SESSION_TRANSACTED) or (false,CLIENT_ACKNOWLEDGE).

In the EJB 3.1 specification, section 13.3.5 states

"The Bean Provider should not use the JMS acknowledge method either within a transaction or within an unspecified transaction context. Message acknowledgment in an unspecified transaction context is handled by the container."

The term "unspecified transaction context" is explained in EJB 3.1 section 13.6.5. Although it does not say so explicitly, it is understood to mean those cases where there is there is no active container-managed transaction in progress or where bean-managed transactions are specified but there is no active UserTransaction in progress.

When this requirement was incorporated into the JMS specification, it became the following text in JMS 2.0 section 12.3:

"When an application creates a Session or JMSContext in a Java EE web or EJB container, and there is no active JTA transaction in progress, then the session that is created will be non-transacted and will be automatically-acknowledged. The use of local transactions or client acknowledgement is still not permitted. Parameters may be specified when creating the Session or JMSContext to specify whether the acknowledgement mode should be AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE. If any other session parameter values are specified they will be ignored and an acknowledgement mode of AUTO_ACKNOWLEDGE used."

The problem

Although the JMS 2.0 specification clearly conveys the intent of the EJB 3.1 specification, the requirement given in the EJB specification was loosely worded:

  • EJB 3.1 uses the phrase "should not use the JMS acknowledge method" rather than "must not use the JMS acknowledge method"
  • EJB 3.1 uses the phrase "Message acknowledgment...is handled by the container" without explicitly stating what would happen if the application tries to use client-acknowledgement or local transactions.

It therefore appears (with hindsight) that JMS 2.0 has introduced some additional requirements which are additional to EJB 3.1. In particular it has introduced the requirement that if the application specifies the session parameters as (true, SESSION_TRANSACTED) or (false, CLIENT_ACKNOWLEDGE) then they will be ignored and an acknowledgement mode of AUTO_ACKNOWLEDGE used.

The "Backwards compatibility requirements for Java EE specifications" can be found at
https://java.net/projects/javaee-spec/pages/CompatibilityRequirements

It could be argued that this change does not violate these compatibility requirements. The compatibility requirements state that "Where behavior was undefined or optional in the previous version of the specification then it is permissible to define more explicit behavior in a later version.", which would appear to allow this change (treating EJB 3.1 as the "previous version").

The compatibility requirements also require that "applications that change to using the new version of the specification do not see changes to behaviour that were mandated by the previous version of the specification.". Again, it could be argued that JMS 2.0 did not change behaviour that was mandated by the previous version of the specification" (again (treating EJB 3.1 as the "previous version").

However it has been discovered that at least one JMS vendor has interpreted the EJB 3.1 specification as allowing both client-acknowledgement and local transactions to be used in a Java EE web or EJB application in the case where there is no active JTA transaction.

Given that the EJB 3.1 specification is loosely worded, and that there were no CTS tests to require otherwise, it would appear that this was valid. Therefore, introducing the requirements added in JMS 2.0 would change the behaviour of existing applications, which is contrary to the intent of the backwards compatibility requirements for Java EE specifications.

The proposal

To avoid forcing JMS vendors to change the the behaviour of existing applications, it is proposed to revise section 12.3 of the JMS 2.0 specification, and the corresponding javadocs, as follows:

  • to recommend (rather than require) that applications do not call createSession with the parameters (true, SESSION_TRANSACTED) or (false,CLIENT_ACKNOWLEDGE) when in a Java EE EJB or web application and there is no active JTA transaction, and warn that applications which specify these parameter values may not be portable,
  • to allow JMS providers to choose the behaviour they provide if the application specifies the parameters (true, SESSION_TRANSACTED) when in a Java EE EJB or web application and there is no active JTA transaction from the following options:
    • the JMS provider is recommended but not required to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session.

    • the JMS provider may alternatively provide a local transacted session.
  • to allow JMS providers to choose the behaviour they provide if the application specifies the parameters (false,CLIENT_ACKNOWLEDGE) when in a Java EE EJB or web application and there is no active JTA transaction from the following options:
    • the JMS provider is recommended but not required to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session.

    • the JMS provider may alternatively provide a non-transacted session with client acknowledgement.

Change related new methods to stay consistent

Although the issue of backwards compatibility applies only to the following existing methods:

  • Connection method createSession(boolean transacted, int acknowledgeMode)
  • QueueConnection method createQueueSession(boolean transacted, int acknowledgeMode)
  • TopicConnection method createTopicSession(boolean transacted, int acknowledgeMode)

it is proposed that for consistency the same changes are also made to the following methods added in JMS 2.0:

  • Connection method createSession(int sessionMode)
  • ConnectionFactory method createContext(int sessionMode).


 Comments   
Comment by Nigel Deakin [ 03/Dec/14 ]

(Superseded by updated proposals below)

Proposed changes to JMS specification section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container"

Existing text:

When an application creates a Session or JMSContext in a Java EE web
or EJB container, and there is no active JTA transaction in progress,
then the session that is created will be non-transacted and will be
automatically-acknowledged. The use of local transactions or client
acknowledgement is still not permitted. Parameters may be specified
when creating the Session or JMSContext to specify whether the
acknowledgement mode should be AUTO_ACKNOWLEDGE or
DUPS_OK_ACKNOWLEDGE. If any other session parameter values are
specified they will be ignored and an acknowledgement mode of
AUTO_ACKNOWLEDGE used.

The use of local transactions or client acknowledgement is not
permitted in a Java EE web or EJB container even if there is no active
JTA transaction because this would require applications to be written
differently depending on whether there was a JTA transaction or not.

The JMS API provides the following methods to create a session which
allow the session to be defined using either the two parameters
transacted and acknowledgeMode or by the single parameter
sessionMode. If these methods are called in a Java EE web or EJB
container then these parameters will be overridden as described above.

[4 methods]

It is recommended that applications that run in the Java EE web or EJB
container create a session using the following method which does not
specify a parameter:

[1 method]

The JMS API provides the following methods to create a JMSContext
which allow the session to be defined using the single parameter
sessionMode. If these methods are called in a Java EE web or EJB
container then this parameter will be overridden as described above.

[2 methods]

The following method to create a JMSContext from an existing
JMSContext is not permitted in a Java EE web or EJB container because
it would create a second session on an existing connection, which is
not permitted in a java EE web or EJB container.]

[1 method]

It is recommended that applications that run in the Java EE web or EJB
container creates a JMSContext using one of the following methods
which do not specify a sessionMode:

[2 methods]

Replacement text:

When an application creates a Session or JMSContext in a Java EE web
or EJB container, and there is no active JTA transaction in progress,
then:

  • If the session parameters specify that the session should be
    non-transacted with an acknowledgement mode of AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE then the session will be non-transacted and messages
    will be acknowledged according to the specified acknowledgement mode.
  • If the session parameters specify that the session should be
    non-transacted with an acknowledgement mode of CLIENT_ACKNOWLEDGE then the
    JMS provider is recommended to ignore the specified parameters and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a non-transacted session with client
    acknowledgement.
  • If the session parameters specify that the session should be transacted,
    then the JMS provider is recommended to ignore the specified parameters and
    instead provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a local transacted session.
  • Applications running in a Java EE web or EJB container are recommended to
    specify no session parameters or to specify that the session be
    non-transacted with an acknowledgement mode of AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE.
  • It is not recommended that applications specify client acknowledgement
    or a local transaction since applications may not be portable. Furthermore
    if the JMS provider does support the use of client acknowledgement
    and local transactions when there is no JTA transaction, the application
    would need to be written differently dependent on whether there was a JTA
    transaction or not.
Comment by Nigel Deakin [ 03/Dec/14 ]

Proposed changes to Javadocs for Connection.html#createSession(boolean, int):

Existing text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • The argument transacted is ignored. The session will always be
    non-transacted, using one of the two acknowledgement modes
    AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE.
  • The argument acknowledgeMode is used to specify how messages
    received by this session will be acknowledged. The only permitted
    values in this case are Session.AUTO_ACKNOWLEDGE and
    Session.DUPS_OK_ACKNOWLEDGE. The value Session.CLIENT_ACKNOWLEDGE
    may not be used. For a definition of the meaning of these
    acknowledgement modes see the links below.

Replacement text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • If transacted is set to false and acknowledgeMode is set to
    JMSContext.AUTO_ACKNOWLEDGE or JMSContext.DUPS_OK_ACKNOWLEDGE then the
    session will be non-transacted and messages will be acknowledged according
    to the value of acknowledgeMode.
  • If transacted is set to false and acknowledgeMode is set to
    JMSContext.CLIENT_ACKNOWLEDGE then the JMS provider is recommended to
    ignore the specified parameters and instead provide a non-transacted,
    auto-acknowledged session. However the JMS provider may alternatively
    provide a non-transacted session with client acknowledgement.
  • If transacted is set to true, then the JMS provider is recommended to
    ignore the specified parameters and instead provide a non-transacted,
    auto-acknowledged session. However the JMS provider may alternatively
    provide a local transacted session.
  • Applications are recommended to set transacted to false and
    acknowledgeMode to JMSContext.AUTO_ACKNOWLEDGE or
    JMSContext.DUPS_OK_ACKNOWLEDGE since since applications which set
    transacted to false and set acknowledgeMode to
    JMSContext.CLIENT_ACKNOWLEDGE, or which set transacted to true, may not be
    portable.

Existing text:

Parameters:

transacted - indicates whether the session will use a local transaction.
If this method is called in the Java EE web or EJB container then this
argument is ignored.

acknowledgeMode - indicates how messages received by the session will be
acknowledged.

  • If this method is called in a Java SE environment or in the Java EE
    application client container, the permitted values are
    Session.CLIENT_ACKNOWLEDGE, Session.AUTO_ACKNOWLEDGE and
    Session.DUPS_OK_ACKNOWLEDGE.
  • If this method is called in the Java EE web or EJB container when
    there is an active JTA transaction in progress then this argument is
    ignored.
  • If this method is called in the Java EE web or EJB container when
    there is no active JTA transaction in progress, the permitted values
    are Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE. In this
    case Session.CLIENT_ACKNOWLEDGE is not permitted.

Replacement text:

Parameters:

transacted - indicates whether the session will use a local transaction,
except in the cases described above when this value is ignored.

acknowledgeMode - when transacted is false, indicates how messages received
by the session will be acknowledged, except in the cases described above
when this value is ignored.

Comment by Nigel Deakin [ 03/Dec/14 ]

Proposed changes to Javadocs for Connection.html#createSession(int):

Existing text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • The argument acknowledgeMode must be set to either of
    Session.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE. The session will
    be non-transacted and messages received by this session will be
    acknowledged automatically according to the value of acknowledgeMode. For
    a definition of the meaning of these acknowledgement modes see the links
    below. The values Session.SESSION_TRANSACTED and Session.CLIENT_ACKNOWLEDGE
    may not be used.

Replacement text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • If sessionMode is set to Session.AUTO_ACKNOWLEDGE or
    Session.DUPS_OK_ACKNOWLEDGE then the session will be
    non-transacted and messages will be acknowledged according to the value
    of sessionMode.
  • If sessionMode is set to Session.CLIENT_ACKNOWLEDGE then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a non-transacted session with
    client acknowledgement.
  • If sessionMode is set to Session.SESSION_TRANSACTED, then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a local transacted session.
  • Applications are recommended to use only the values
    Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE
    since applications which use Session.CLIENT_ACKNOWLEDGE or
    Session.SESSION_TRANSACTED may not be portable.

Existing text:

Parameters:

sessionMode - indicates which of four possible session modes will be used.

  • If this method is called in a Java SE environment or in the Java EE
    application client container, the permitted values are
    Session.SESSION_TRANSACTED, Session.CLIENT_ACKNOWLEDGE,
    Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE.
  • If this method is called in the Java EE web or EJB container when there
    is an active JTA transaction in progress then this argument is ignored.
  • If this method is called in the Java EE web or EJB container when there
    is no active JTA transaction in progress, the permitted values are
    Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE. In this case
    the values Session.TRANSACTED and Session.CLIENT_ACKNOWLEDGE are not permitted.

Replacement text:

Parameters:

sessionMode - specifies the session mode that will be used, except in the
cases described above when this value is ignored. Legal values are
JMSContext.SESSION_TRANSACTED, JMSContext.CLIENT_ACKNOWLEDGE,
JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE.

Comment by Nigel Deakin [ 03/Dec/14 ]

(This proposal has now been dropped. See updated proposals below)

Proposed changes to Javadocs for ConnectionFactory.html.createContext(int):

Existing text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • The argument acknowledgeMode must be set to either of
    JMSContext.AUTO_ACKNOWLEDGE or JMSContext.DUPS_OK_ACKNOWLEDGE. The
    session will be non-transacted and messages received by this session
    will be acknowledged automatically according to the value of
    acknowledgeMode. For a definition of the meaning of these
    acknowledgement modes see the links below. The values
    JMSContext.SESSION_TRANSACTED and JMSContext.CLIENT_ACKNOWLEDGE may
    not be used.

Replacement text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • If sessionMode is set to JMSContext.AUTO_ACKNOWLEDGE or
    JMSContext.DUPS_OK_ACKNOWLEDGE then the session will be
    non-transacted and messages will be acknowledged according to the value
    of sessionMode.
  • If sessionMode is set to JMSContext.CLIENT_ACKNOWLEDGE then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a non-transacted session with
    client acknowledgement.
  • If sessionMode is set to JMSContext.SESSION_TRANSACTED, then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a local transacted session.
  • Applications are recommended to use only the values
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE
    since applications which use JMSContext.CLIENT_ACKNOWLEDGE or
    JMSContext.SESSION_TRANSACTED may not be portable.

Existing text:

Parameters:

sessionMode - indicates which of four possible session modes will be used.

  • If this method is called in a Java SE environment or in the Java EE
    application client container, the permitted values are
    JMSContext.SESSION_TRANSACTED, JMSContext.CLIENT_ACKNOWLEDGE,
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE.
  • If this method is called in the Java EE web or EJB container when there
    is an active JTA transaction in progress then this argument is ignored.
  • If this method is called in the Java EE web or EJB container when there
    is no active JTA transaction in progress, the permitted values are
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE. In this case
    the values JMSContext.TRANSACTED and JMSContext.CLIENT_ACKNOWLEDGE are not
    permitted.

Replacement text:

Parameters:

sessionMode - specifies the session mode that will be used, except in the
cases described above when this value is ignored. Legal values are
JMSContext.SESSION_TRANSACTED, JMSContext.CLIENT_ACKNOWLEDGE,
JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE.

Comment by Nigel Deakin [ 03/Dec/14 ]

(This proposal has now been dropped. See updated proposals below)

Proposed changes to Javadocs for ConnectionFactory.html.createContext(String, String, int):

Existing text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • The argument acknowledgeMode must be set to either of
    JMSContext.AUTO_ACKNOWLEDGE or JMSContext.DUPS_OK_ACKNOWLEDGE. The session
    will be non-transacted and messages received by this session will be
    acknowledged automatically according to the value of acknowledgeMode.
    For a definition of the meaning of these acknowledgement modes see the
    links below. The values JMSContext.SESSION_TRANSACTED and
    JMSContext.CLIENT_ACKNOWLEDGE may not be used.

Replacement text:

In the Java EE web or EJB container, when there is no active JTA
transaction in progress:

  • If sessionMode is set to JMSContext.AUTO_ACKNOWLEDGE or
    JMSContext.DUPS_OK_ACKNOWLEDGE then the session will be
    non-transacted and messages will be acknowledged according to the value
    of sessionMode.
  • If sessionMode is set to JMSContext.CLIENT_ACKNOWLEDGE then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a non-transacted session with
    client acknowledgement.
  • If sessionMode is set to JMSContext.SESSION_TRANSACTED, then the JMS
    provider is recommended to ignore the specified parameter and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a local transacted session.
  • Applications are recommended to use only the values
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE
    since applications which use JMSContext.CLIENT_ACKNOWLEDGE or
    JMSContext.SESSION_TRANSACTED may not be portable.

Existing text:

Parameters:

userName - the caller's user name

password - the caller's password

sessionMode - indicates which of four possible session modes will be used.

  • If this method is called in a Java SE environment or in the Java EE
    application client container, the permitted values are
    JMSContext.SESSION_TRANSACTED, JMSContext.CLIENT_ACKNOWLEDGE,
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE.
  • If this method is called in the Java EE web or EJB container when there
    is an active JTA transaction in progress then this argument is ignored.
  • If this method is called in the Java EE web or EJB container when there
    is no active JTA transaction in progress, the permitted values are
    JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE. In this
    case the values JMSContext.TRANSACTED and JMSContext.CLIENT_ACKNOWLEDGE
    are not permitted.

Replacement text:

Parameters:

userName - the caller's user name

password - the caller's password

sessionMode - specifies the session mode that will be used, except in the
cases described above when this value is ignored. Legal values are
JMSContext.SESSION_TRANSACTED, JMSContext.CLIENT_ACKNOWLEDGE,
JMSContext.AUTO_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE.

Comment by Nigel Deakin [ 17/Dec/14 ]

Updated proposal

Here is an updated proposal which would update the specification and javadocs for the classic API (createSession methods) only but make no changes to the simplified API (createContext methods) on the grounds these new methods do not break backward compatibility and so don't need to be changed.

The following javadoc changes would still be needed:

The changed originally proposed to JMS specification section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" would be replaced by the following:

Existing text

12.3 "Behaviour of JMS sessions in the Java EE web or EJB container"

The behaviour of a JMS session in respect of transactions and message
acknowledgement is different for applications which run in a Java EE
web or EJB container than it is for applications which run in a normal
Java SE environment or in the Java EE application client container.

These differences also apply to JMSContext objects, since these
incorporate a JMS session.

When an application creates a Session or JMSContext in a Java EE web
or EJB container, and there is an active JTA transaction in progress,
then the session that is created will participate in the JTA
transaction and will be committed or rolled back when the JTA
transaction is committed or rolled back. Any session parameters that
are specified when creating the Session or JMSContext are ignored. The
use of local transactions or client acknowledgement is not permitted.

This applies irrespective of whether the JTA transaction is demarcated
automatically by the container or programmatically using methods on
javax.transaction.UserTransaction.

The term “session parameters” here refers to the arguments that may be
passed into a call to the createSession or createContext methods to
specify whether the session should use a local transaction and, if the
session is non-transacted, what the acknowledgement mode should be.

When an application creates a Session or JMSContext in a Java EE web
or EJB container, and there is no active JTA transaction in progress,
then the session that is created will be non-transacted and will be
automatically-acknowledged. The use of local transactions or client
acknowledgement is still not permitted. Parameters may be specified
when creating the Session or JMSContext to specify whether the
acknowledgement mode should be AUTO_ACKNOWLEDGE or
DUPS_OK_ACKNOWLEDGE. If any other session parameter values are
specified they will be ignored and an acknowledgement mode of
AUTO_ACKNOWLEDGE used.

The use of local transactions or client acknowledgement is not
permitted in a Java EE web or EJB container even if there is no active
JTA transaction because this would require applications to be written
differently depending on whether there was a JTA transaction or not.

The JMS API provides the following methods to create a session which
allow the session to be defined using either the two parameters
transacted and acknowledgeMode or by the single parameter sessionMode.
If these methods are called in a Java EE web or EJB container then
these parameters will be overridden as described above.

(4 methods)

It is recommended that applications that run in the Java EE web or EJB
container create a session using the following method which does not
specify a parameter:

(1 method)

The JMS API provides the following methods to create a JMSContext
which allow the session to be defined using the single parameter
sessionMode. If these methods are called in a Java EE web or EJB
container then this parameter will be overridden as described above.

(2 methods)

The following method to create a JMSContext from an existing
JMSContext is not permitted in a Java EE web or EJB container because
it would create a second session on an existing connection, which is
not permitted in a java EE web or EJB container.]

(1 method)

It is recommended that applications that run in the Java EE web or EJB
container creates a JMSContext using one of the following methods
which do not specify a sessionMode:

(2 methods)

Replacement text

The behaviour of JMS Session and JMSContext objects in respect of
transactions and message acknowledgement is different for applications
which run in a Java EE web or EJB container than it is for applications
which run in a normal Java SE environment or in the Java EE application
client container.

When an application creates a Session or JMSContext in a Java EE web
or EJB container, and there is an active JTA transaction in progress,
then the session that is created will participate in the JTA
transaction and will be committed or rolled back when the JTA
transaction is committed or rolled back. Any session parameters that
are specified when creating the Session or JMSContext are ignored. The
use of local transactions or client acknowledgement is not permitted.

This applies irrespective of whether the JTA transaction is demarcated
automatically by the container or programmatically using methods on
javax.transaction.UserTransaction.

The term “session parameters” here refers to the arguments that may be
passed into a call to the createSession or createContext methods to
specify whether the session should use a local transaction and, if the
session is non-transacted, what the acknowledgement mode should be.

When an application uses one of the createSession methods to create
a Session, and there is no active JTA transaction in progress,
then:

  • If the session parameters specify that the session should be
    non-transacted with an acknowledgement mode of AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE then the session will be non-transacted and messages
    will be acknowledged according to the specified acknowledgement mode.
  • If the session parameters specify that the session should be
    non-transacted with an acknowledgement mode of CLIENT_ACKNOWLEDGE then the
    JMS provider is recommended to ignore the specified parameters and instead
    provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a non-transacted session with client
    acknowledgement.
  • If the session parameters specify that the session should be transacted,
    then the JMS provider is recommended to ignore the specified parameters and
    instead provide a non-transacted, auto-acknowledged session. However the JMS
    provider may alternatively provide a local transacted session.
  • Applications running in a Java EE web or EJB container are recommended to
    specify no session parameters or to specify that the session be
    non-transacted with an acknowledgement mode of AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE.
  • It is not recommended that applications specify client acknowledgement
    or a local transaction since applications may not be portable. Furthermore
    if the JMS provider does support the use of client acknowledgement
    and local transactions when there is no JTA transaction, the application
    would need to be written differently dependent on whether there was a JTA
    transaction or not.

When an application uses one of the createContext methods to create
a JMSContext, and there is no active JTA transaction in progress,
then:

  • If the specified session mode is AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE then the session will be non-transacted and messages
    will be acknowledged according to the specified acknowledgement mode.
  • If the specified session mode is CLIENT_ACKNOWLEDGE or SESSION_TRANSACTED
    then it will be ignored and a session mode of AUTO_ACKNOWLEDGE used.
  • Applications running in a Java EE web or EJB container are recommended to
    specify no session parameters or to specify that the session be
    non-transacted with an acknowledgement mode of AUTO_ACKNOWLEDGE or
    DUPS_OK_ACKNOWLEDGE.
  • The use of local transactions or client acknowledgement is not
    permitted in a Java EE web or EJB container even if there is no active
    JTA transaction because this would require applications to be written
    differently depending on whether there was a JTA transaction or not.
Comment by Nigel Deakin [ 09/Jan/15 ]

Draft spec now updated.
PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=315.
Latest PDF at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf

Updated source for javax.jms.Connection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Connection.java?rev=315
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Connection.java?rev1=314&rev2=315

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-133] Update javadoc comments for QueueConnection#createQueueSession and TopicConnection#createTopicSession Created: 19/Aug/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The javadoc comments for QueueConnection#createQueueSession and TopicConnection#createTopicSession should be updated to match those for Connection#createSession (mutatis mutandis), by describing the required behaviour in the various Java EE containers etc.



 Comments   
Comment by Nigel Deakin [ 22/Dec/14 ]

Here are the proposed changes.

javadoc for QueueConnection#createQueueSession

It is proposed the existing javadoc for this method is replaced by a copy of the javadoc for Connection#createSession (after applying the changes for JMS_SPEC-155 and JMS_SPEC-157), with the following modifications

  • The first paragraph "This method has been superseded by...instead of this one" is omitted.
  • "Creates a Session object" is changed to "Creates a QueueSession object"
  • "Returns: a newly created queue session" is changed to "Returns: a newly created QueueSession"
  • "if the Connection object fails to create a session" is changed to "if the QueueConnection object fails to create a QueueSession"
  • In the section "See Also:", the references to createSession(int), createSession() are omitted.

Existing text:

Creates a QueueSession object.

Parameters:

transacted - indicates whether the session is transacted

acknowledgeMode - indicates whether the consumer or the client will acknowledge any messages it receives; ignored if the session is transacted. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Returns:

a newly created queue session

Throws:

JMSException - if the QueueConnection object fails to create a session due to some internal error or lack of support for the specific transaction and acknowledgement mode.

See Also:

Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE

Replacement text:

Creates a QueueSession object, specifying transacted and acknowledgeMode.

The effect of setting the transacted and acknowledgeMode arguments depends on whether this method is called in a Java SE environment, in the Java EE application client container, or in the Java EE web or EJB container. If this method is called in the Java EE web or EJB container then the effect of setting the transacted} and acknowledgeMode arguments also depends on whether or not there is an active JTA transaction in progress.

In a Java SE environment or in the Java EE application client container:

  • If transacted is set to true then the session will use a local transaction which may subsequently be committed or rolled back by calling the session's commit or rollback methods. The argument acknowledgeMode is ignored.
  • If transacted is set to false then the session will be non-transacted. In this case the argument acknowledgeMode is used to specify how messages received by this session will be acknowledged. The permitted values are Session.CLIENT_ACKNOWLEDGE, Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE. For a definition of the meaning of these acknowledgement modes see the links below.

In a Java EE web or EJB container, when there is an active JTA transaction in progress:

  • Both arguments transacted and acknowledgeMode are ignored. The session will participate in the JTA transaction and will be committed or rolled back when that transaction is committed or rolled back, not by calling the session's commit or rollback methods. Since both arguments are ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

In the Java EE web or EJB container, when there is no active JTA transaction in progress:

  • If transacted is set to false and acknowledgeMode is set to JMSContext.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE then the session will be non-transacted and messages will be acknowledged according to the value of acknowledgeMode.
  • If transacted is set to false and acknowledgeMode is set to JMSContext.CLIENT_ACKNOWLEDGE then the JMS provider is recommended to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session. However the JMS provider may alternatively provide a non-transacted session with client acknowledgement.
  • If transacted is set to true, then the JMS provider is recommended to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session. However the JMS provider may alternatively provide a local transacted session.
  • Applications are recommended to set transacted to false and acknowledgeMode to JMSContext.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE since since applications which set transacted to false and set acknowledgeMode to JMSContext.CLIENT_ACKNOWLEDGE, or which set transacted to true, may not be portable.

Applications running in the Java EE web and EJB containers must not attempt to create more than one active (not closed) Session object per connection. If this method is called in a Java EE web or EJB container when an active Session object already exists for this connection then a JMSException may be thrown.

Parameters:

transacted - indicates whether the session will use a local transaction, except in the cases described above when this value is ignored.

acknowledgeMode - when transacted is false, indicates how messages received by the session will be acknowledged, except in the cases described above when this value is ignored.

Returns:

a newly created QueueSession

Throws:

JMSException - if the QueueConnection object fails to create a QueueSession due to some internal error, lack of support for the specific transaction and acknowledgement mode, or because this method is being called in a Java EE web or EJB application and an active session already exists for this connection.

Since:

JMS 1.1

See Also:

Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE

javadoc for TopicConnection#createTopicSession

It is proposed the existing javadoc for this method is replaced by a copy of the javadoc for Connection#createSession (after applying the changes for JMS_SPEC-155 and JMS_SPEC-157), with the following modifications

  • The first paragraph "This method has been superseded by...instead of this one" is omitted.
  • "Creates a Session object" is changed to "Creates a TopicSession object"
  • "Returns: a newly created topic session" is changed to "Returns: a newly created TopicSession "
  • "if the Connection object fails to create a session" is changed to "if the TopicConnection object fails to create a TopicSession"
  • In the section "See Also:", the references to createSession(int), createSession() are omitted.

Existing text:

Creates a TopicSession object.

Parameters:

transacted - indicates whether the session is transacted

acknowledgeMode - indicates whether the consumer or the client will acknowledge any messages it receives; ignored if the session is transacted. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Returns:

a newly created topic session

Throws:

JMSException - if the TopicConnection object fails to create a session due to some internal error or lack of support for the specific transaction and acknowledgement mode.

See Also:

Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE

Replacement text:

Creates a TopicSession object, specifying transacted and acknowledgeMode.

The effect of setting the transacted and acknowledgeMode arguments depends on whether this method is called in a Java SE environment, in the Java EE application client container, or in the Java EE web or EJB container. If this method is called in the Java EE web or EJB container then the effect of setting the transacted} and acknowledgeMode arguments also depends on whether or not there is an active JTA transaction in progress.

In a Java SE environment or in the Java EE application client container:

  • If transacted is set to true then the session will use a local transaction which may subsequently be committed or rolled back by calling the session's commit or rollback methods. The argument acknowledgeMode is ignored.
  • If transacted is set to false then the session will be non-transacted. In this case the argument acknowledgeMode is used to specify how messages received by this session will be acknowledged. The permitted values are Session.CLIENT_ACKNOWLEDGE, Session.AUTO_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE. For a definition of the meaning of these acknowledgement modes see the links below.

In a Java EE web or EJB container, when there is an active JTA transaction in progress:

  • Both arguments transacted and acknowledgeMode are ignored. The session will participate in the JTA transaction and will be committed or rolled back when that transaction is committed or rolled back, not by calling the session's commit or rollback methods. Since both arguments are ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

In the Java EE web or EJB container, when there is no active JTA transaction in progress:

  • If transacted is set to false and acknowledgeMode is set to JMSContext.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE then the session will be non-transacted and messages will be acknowledged according to the value of acknowledgeMode.
  • If transacted is set to false and acknowledgeMode is set to JMSContext.CLIENT_ACKNOWLEDGE then the JMS provider is recommended to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session. However the JMS provider may alternatively provide a non-transacted session with client acknowledgement.
  • If transacted is set to true, then the JMS provider is recommended to ignore the specified parameters and instead provide a non-transacted, auto-acknowledged session. However the JMS provider may alternatively provide a local transacted session.
  • Applications are recommended to set transacted to false and acknowledgeMode to JMSContext.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE since since applications which set transacted to false and set acknowledgeMode to JMSContext.CLIENT_ACKNOWLEDGE, or which set transacted to true, may not be portable.

Applications running in the Java EE web and EJB containers must not attempt to create more than one active (not closed) Session object per connection. If this method is called in a Java EE web or EJB container when an active Session object already exists for this connection then a JMSException may be thrown.

Parameters:

transacted - indicates whether the session will use a local transaction, except in the cases described above when this value is ignored.

acknowledgeMode - when transacted is false, indicates how messages received by the session will be acknowledged, except in the cases described above when this value is ignored.

Returns:

a newly created TopicSession

Throws:

JMSException - if the TopicConnection object fails to create a TopicSession due to some internal error, lack of support for the specific transaction and acknowledgement mode, or because this method is being called in a Java EE web or EJB application and an active session already exists for this connection.

Since:

JMS 1.1

See Also:

Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE

Comment by Nigel Deakin [ 09/Jan/15 ]

Updated source for javax.jms.QueueConnection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/QueueConnection.java?rev=316
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/QueueConnection.java?rev1=315&rev2=316

Updated source for javax.jms.TopicConnection can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/TopicConnection.java?rev=316
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/TopicConnection.java?rev1=315&rev2=316

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-140] Assumptions over Destination name within TCK Created: 05/Nov/13  Updated: 05/Nov/13  Resolved: 05/Nov/13

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: mbwhite Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

When running the tck



 Description   

The Session object for example has createQueue() and createTopic() methods - both taking a string 'name' that provider-specific. The Queue and Topic objects both have methods that can get this name.

The TCK includes a check that gets this and confirms that what is passed in on create is the same as what is got. Not unreasonable; however the TCK has made an assumption of the format of the string used to set. This might not be valid.



 Comments   
Comment by Nigel Deakin [ 05/Nov/13 ]

Sounds a fair comment, particularly if this is a new test in JMS 2.0.

Sorry to be bureaucratic, but if you think the TCK is incorrect can you please take this up directly with the organisation which supplied you with the TCK? You should have the necessary contact details at Java partner Engineering (part of Oracle). You don't need to log these in JIRA first. Email me directly if you need help finding the right contact. nigel.deakin@oracle.com

Comment by mbwhite [ 05/Nov/13 ]

Thanks for the comment - wanted to raise that to see if it sounded reasonable. In this case the TCK supplies something like "QueueNameOne" - and a provider may just say sorry that isn't valid for various reasons.. It could then have to treat it as 'shorthand' or abbreviation. Therefore the string returned could be different but in valid 'providerSyntax'...

No you're right to be bureaucratic - this should be a TCK issue.

Comment by mbwhite [ 05/Nov/13 ]

As commented by Nigel this should raised as TCK issue.





[JMS_SPEC-122] Typos in javadocs for ConnectionFactory.createContext Created: 08/May/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

1. There's a typo in the javadocs for ConnectionFactory.createContext(int sessionMode)

In the paragraph "In a Java EE web or EJB container, when there is an active JTA transaction in progress: ", change:

Since the argument is ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

to:

Since the argument is ignored, developers are recommended to use createContext(), which has no arguments, instead of this method.

2. There's a typo in the javadocs for ConectionFactory.createContext(String userName, String password, int sessionMode):

In the paragraph "In a Java EE web or EJB container, when there is an active JTA transaction in progress: ", change:

Since the argument is ignored, developers are recommended to use createSession(), which has no sessionMode parameter, instead of this method.

to:

Since the argument is ignored, developers are recommended to use createContext(String userName, String password), which has no sessionMode parameter, instead of this method.



 Comments   
Comment by Nigel Deakin [ 12/Jan/15 ]

Proposed changes to ConnectionFactory#createContext(int sessionMode):

Existing text

Since the argument is ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

Replacement text

Since the argument is ignored, developers are recommended to use createContext() instead of this method.

Proposed changes to ConnectionFactory#createContext(String userName, String password, int sessionMode):

Existing text

Since the argument is ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

Replacement text

Since the argument is ignored, developers are recommended to use createContext(String userName, String password) instead of this method.

Comment by Nigel Deakin [ 12/Jan/15 ]

Updated source for javax.jms.JMSContext can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/ConnectionFactory.java?rev=319
Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/ConnectionFactory.java?rev1=317&rev2=319

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-128] Typo in section 4.1.4 "Queue" Created: 06/Jun/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

There's a typo in section 4.1.4 "Queue":

The sentence

See Section 0 "<new page>Administered objects" for more information...

contains an incorrect section number and a spurious page throw.



 Comments   
Comment by Nigel Deakin [ 01/Dec/14 ]

Draft spec now updated. PDF (with change bar) at https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/specification/word/JMS20.pdf?rev=305

Comment by Nigel Deakin [ 19/Dec/14 ]

Proposed changes to JMS specification section 4.1.4 "Queue"

Existing text

See Section 0 "<new page>Administered objects" for more information...

(where <new page> means that the subsequent text was on the next page)

Replacement text

See Section 5 "Administered objects" for more information...

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-125] Define whether a JMS provider should call reset after sending a BytesMessage asynchronously Created: 17/May/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-166 Define that the JMS provider should c... Open
Tags: jms20-errata

 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.



 Comments   
Comment by John D. Ament [ 21/May/13 ]

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

Comment by Nigel Deakin [ 22/May/13 ]

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.

Comment by Nigel Deakin [ 09/Dec/14 ]

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.

Comment by mbwhite [ 09/Dec/14 ]

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.

Comment by Nigel Deakin [ 19/Dec/14 ]

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.

Comment by Nigel Deakin [ 09/Jan/15 ]

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

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-103] A JMS 2.0 resource adapter needs to be able to include cluster name in a generated subscription name Created: 29/Oct/12  Updated: 14/Nov/12  Resolved: 14/Nov/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0PD
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JMS_SPEC-73 Define how messages from a topic are ... Open
blocks MQ-230 Enhance JMSRA to include cluster name... Closed
Tags: pd20-forreview-minor

 Description   

The draft JMS 2.0 specification, chapter 12.1. "ActivationSpec properties" states that:

If a durable subscription is specified but subscriptionName is not specified then the resource adapter will set the name of the durable subscription to be a name which is unique to the deployed MDB.

The intention of this feature is to allow the resource adapter to automatically generate a subscription name automatically which will be different for each deployed MDB but the same for each instance in the cluster. This instances of the same deployed MDB across the whole cluster to share the work of processing messages from the same subscription.

However if the same JMS provider is being used by two different application server clusters, and the two clusters are using the same MDB name, then this would cause the two clusters to share the same subscription which is undesirable.

To avoid this, the subscription name generated by the resource adapter should be composed of (1) a name which uniquely identifies the deployed MDB within thin the cluster as well as (2) a name which uniquely identifies the application server cluster.

The JMS specification needs to be extended to cover (2)



 Comments   
Comment by Nigel Deakin [ 29/Oct/12 ]

This will also require a change to the EJB 3.2 specification which contains a similar definition of what the container does it the subscriptionName property is not set.

Implementing this will require a change to the Java EE specification to make the name of the cluster available.

Comment by Nigel Deakin [ 29/Oct/12 ]

This is an extension of issue JMS_SPEC-73

Comment by Nigel Deakin [ 14/Nov/12 ]

I'm closing this issue as a duplicate of JMS_SPEC-73 because that issue is still open and it is best to keep this as a single open issue.





[JMS_SPEC-102] Make JMSConsumer.receivePayload methods consistent with Message.getBody Created: 26/Oct/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0PD
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JMS_SPEC-101 New methods Message.getBody(Class<T> ... Resolved
blocks MQ-228 Implement new name and behaviour for ... Closed
Tags: pd20-added

 Description   

JMS_SPEC_64 introduced a new interface JMSConsumer for JMS 2.0. This has methods receivePayload(Class<T> c), receivePayload(Class<T> c, long timeout) and receivePayloadNoWait(Class<T> c).

JMS_SPEC-101 will introduce a new method getBody(Class<T> c).

If JMS_SPEC-101 is agreed then the definition of receivePayload(Class<T> c), receivePayload(Class<T> c, long timeout) and receivePayloadNoWait(Class<T> c) should be amended to make it consistent with the definition of getBody(Class<T> c). Specifically, these methods should allow the specified class to be any type to which the message payload can be assigned. In addition, these methods should throw a MessageFormatException rather than a ClassCastException if the message payload cannot be assigned.

In addition, the name of these method should be changed to receiveBody(Class<T> c), receiveBody(Class<T> c, long timeout) and receiveBodyNoWait(Class<T> c) since the word "payload" is inconsistent with the term "body" which is used in JMS 1.1.



 Comments   
Comment by Nigel Deakin [ 26/Oct/12 ]

In addition, all references to "payload" which were introduced in the JMS 2.0 spec should be changed to "body". (The JMS 1.1 spec does not use the word "payload", but uses the word "body" consistently, including in the names of methods such as clearBody().

Comment by Nigel Deakin [ 30/Oct/12 ]

Please also consider whether to simply change the names of these methods to just "receive", since there would be no clash with the existing receive methods.

Comment by nwright [ 12/Nov/12 ]

I like JMSConsumer.receiveBodyX(Class<T> c).

RE changing these methods to just "receive": I do not think we should move to JMSConsumer.receiveX(Class<T> c) as this is potentially confusing - it looks to me as if the whole message including headers would be delivered with this method. Better to keep the 'Body' in the method name.

Comment by Nigel Deakin [ 16/Nov/12 ]

The API and specification have now been updated with these changes. The new method names are receiveBody(Class<T> c), receiveBody(Class<T> c, long timeout) and receiveBodyNoWait(Class<T> c). Please see the JMS 2.0 API docs for details.





[JMS_SPEC-99] Define annotations for Java EE 7 resource configuration Created: 22/Aug/12  Updated: 10/Sep/12  Resolved: 10/Sep/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

In the Java EE 7 specification:

Section EE.5.17.4 "JMS Connection Factory Resource Definition" states that "A JMS ConnectionFactory resource may also be defined using the JMSConnectionFactoryDefinition annotation

Section EE.5.17.5 "JMS Destination Definition" states that "A JMS Destination resource may also be defined using the JMSDestinationDefinition annotation".

These annotations need to be defined in the javax.jms package as part of JMS 2.0.



 Comments   
Comment by Nigel Deakin [ 10/Sep/12 ]

This is a duplicate of JMS_SPEC-96 and JMS_SPEC-97





[JMS_SPEC-120] Typo: in example, change .class() to .class Created: 26/Apr/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The JMS spec contains the following code in an example:

StockObject stockObject = message.getBody(StockObject.class());

This is incorrect. It should be changed to

StockObject stockObject = message.getBody(StockObject.class);

i.e. class should not be followed by ().



 Comments   
Comment by Nigel Deakin [ 02/Dec/14 ]

JMS specification section 14.4.10 "Unpacking an ObjectMessage": Existing text:

StockObject stockObject = message.getBody(StockObject.class());

Replacement text

StockObject stockObject = message.getBody(StockObject.class);
Comment by Nigel Deakin [ 02/Dec/14 ]

I have updated the specification in the source code repository. PDF may be downloaded here.

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-119] Remove reference to password alias Created: 26/Apr/13  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The JMS 2.0 specification, section 12.4.3 "Injection syntax" includes an example of the use of password aliases in Java EE. Although password aliases were discussed for Java EE they were not included in the final release, so the example should be removed.



 Comments   
Comment by Nigel Deakin [ 02/Dec/14 ]

Proposed change

In the JMS 2.0 specification, section 12.4.3 "Injection syntax", delete the following text:

Since it is undesirable to hardcode clear text passwords in an application, the password may be specified as an alias:

@Inject
@JMSPasswordCredential(
   username="admin",
   password="${ALIAS=myAdminPassword}")
private JMSContext context;

The use of a password alias allows the password to be defined in a secure manner separately from the application. See the Java EE 7 platform specification for more information on password aliases.

Comment by Nigel Deakin [ 02/Dec/14 ]

I have updated the specification in the source code repository. PDF may be downloaded here.

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-46] Define standard API to create and configure a ConnectionFactory Created: 11/Aug/11  Updated: 27/Mar/12  Resolved: 27/Mar/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Won't Fix Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

This is a proposal to extend the JMS specification to define a standard way of instantiating and configuring connection factory objects.

Background

A connection factory is an example of an administered object. The JMS 1.1 specification establishes the convention whereby administered objects (connection factories and destinations) are not created in application code. Instead they are created by an administrator using tools specific to the JMS provider and stored in JNDI. The application code then looks up the connection factory or destination from JNDI and uses them in accordance with the JMS API.

The purpose of this is clearly stated in the specification: it is to allow everything that is non-standard and specific to a particular JMS provider to be kept out of the code itself. (See Relevant sections of the JMS 1.1 Specification below).

In the case of connection factories, this means that the application doesn't have to contain any information about how to connect to the JMS provider. For example, if the JMS provider is running on some remote server, the application doesn't contain any information about the location of the server or the protocol used to connect to it. All this information is defined when the connection factory is created by an administrator, separate from the application itself.

However the JMS specification says nothing about how the connection factory itself is created or configured, other than saying that it is done by "provider-specific facilities". All it says is that:

  • it must implement javax.jms.ConnectionFactory,
  • it must implement javax.naming.Referenceable and java.io.Serializable, so it can be stored in all JNDI naming contexts (section 4.2)
  • it is recommended that implementations "follow the JavaBeans design patterns"
  • it allows client identifier to be set (section 4.3.2)

However the specification does not define:

  • how a connection factory is instantiated
  • how the location of the server is defined
  • how client identifier is set
  • how other properties are set

Now although this omission from the JMS 1.1 specification is no doubt deliberate, it does cause some difficulties:

  • it is not possible to develop standard tools for creating connection factories (and binding them in JNDI) which work with multiple JMS providers
  • in a Java EE environment, there is no standard way of configuring the JMS requirements of a particular application
  • it is inconsistent with way in which a JDBC DataSource objects is defined, both in a Java SE and a Java EE environment. This is discussed more in How JDBC DataSource objects are configured.

Proposals

It is proposed that the way that a ConnectionFactory is created and configured be partially standardised in a manner similar to JDBC DataSource objects, as follows:

  • A ConnectionFactory implementation is a JavaBean, and may be instantiated by executing the no-arg constructor of its implementation class. For example:
ConnectionFactory cf = Class.forName("com.sun.messaging.ConnectionFactory") 
  • The JMS specification will define a set of properties which may be used to identify and describe a ConnectionFactory implementation.
Property name Type Description
description String description of this connection factory
user String user name (may be overridden when createConnection is called)
password String password corresponding to user name may be overridden when createConnection is called)
networkProtocol String network protocol used to communicate with the JMS provider
serverName String server name of the JMS provider
portNumber String port number of the JMS provider
networkProtocols String[] array of network protocols used to communicate with the JMS provider
serverNames String[] array of server names of the JMS provider
portNumbers String[] array of port numbers of the JMS provider
url String Opaque string which defines how to connect to the JMS provider
clientId String JMS client identifier
  • ConnectionFactory properties follow the convention specified for properties of JavaBeans components in the JavaBeans 1.01 Specification. ConnectionFactory implementations may augment this set with implementation-specific properties. If new properties are added, they must be given names that do not conflict with the
    standard property names.
  • ConnectionFactory implementations must provide "getter" and "setter" methods for each property they support. These properties typically are intended to be initialized before the object is bound in JNDI for subsequent use by an application.
  • ConnectionFactory properties are not intended to be directly accessible by JMS clients. This design is reinforced by defining the access methods on the implementation class rather than on the public DataSource interface used by applications. Furthermore, the object that the client manipulates can be a wrapper that only
    implements the ConnectionFactory interface. The setter and getter methods for the properties need not be exposed to the client.
  • Management tools that need to manipulate the properties of a ConnectionFactory implementation can access those properties using introspection.

Note that this gives three alternative ways to define how the connection factory should communicate with the server:

  • an opaque URL string
  • a tuple of (networkProtocol, serverName, portNumber), where networkProtocol may be omitted
  • an array of such tuples, represented here as three separate arrays

A JMS provider may support all, some or none of these alternatives.

  • If both URL and one of the other forms are supported and both are supplied, the URL is used.
  • If the single tuple (networkProtocol, serverName, portNumber) is supported, then a single-element array of tuples will also be supported

(Much of the wording above is based on section 9.4.1 DataSource properties of the JDBC 4.0 specification.)

Please also see the following additional information which has been added as separate notes below:

  • How JDBC DataSource objects are configured
  • Relevant sections of the JMS 1.1 Specification


 Comments   
Comment by Nigel Deakin [ 11/Aug/11 ]

How JDBC DataSource objects are configured

This section describes how, although JDBC DataSource objects are similar in concept to JMS ConnectionFactory objects, the JDBC and Java EE specifications define in much more detail how DataSource objects are created and configured than the JMS specification defines for ConnectionFactory objects.

A JMS ConnectionFactory is a factory for creating connections to a JMS provider, using the createConnection method. In JDBC, a javax.jdbc.DataSource fulfils a similar role as a factory for creating connections to a JDBC database, using the getConnection method.

Section 9.4.2 recommends that javax.jdbc.DataSource objects are stored in JNDI to allow database-specific configuration to be kept separate from the application. This much is similar to JMS.

However the JNDI specification differs from JMS in providing a lot of guidance on how to create a DataSource. Section 9.4.1 contains a whole list of standard data source properties which may be supported:

  • databaseName
  • dataSourceName
  • description
  • networkProtocol
  • password
  • portNumber
  • roleName
  • serverName
  • user

Although the specification suggests that not all DataSource implementations support all properties, it does define names for these most common properties, and specifies that when supported, they must be configurable using standard JavaBeans "setters and getters".

In addition, a DataSource may be instantiated by invoking its no-arg constructor. This isn't stated explicitly in the spec (if the DataSource were a JavaBean then a no-arg constructor would be mandatory, but the spec only states that its properties follow the conventions specified for properties of JavaBeans, not that a DataSource is itself a JavaBean) but in practice the convention that it can is well-established.

This means that a DataSource may be instantiated, given the name of the implementation class as a String, using code of the following form:

DataSource ds = Class.forName("oracle.jdbc.pool.OracleDataSource") 

Meanwhile, the Java EE 6 specification defines a DataSourceDefinition annotation and a corresponding <data-source> element which defines the following properties of a DataSource:

  • className (required)
  • name (required)
  • databaseName
  • description
  • initialPoolSize
  • isolationLevel
  • loginTimeout
  • maxIdleTime
  • maxPoolSize
  • maxStatements
  • minPoolSize
  • password
  • portNumber
  • properties
  • serverName
  • transactional
  • url
  • user

This is a longer list than is defined in JDBC, partly because the JDBC spec is older, but also because it also includes pooling properties. Perhaps of the most interest is the url property, which may be provided as an alternative to serverName and port.

Comment by Nigel Deakin [ 11/Aug/11 ]

Relevant sections of the JMS 1.1 Specification

The relevant sections of the JMS specification are given below:

Section 2.3 Administration

It is expected that JMS providers will differ significantly in their underlying messaging technology. It is also expected there will be major differences in how a provider’s system is installed and administered.

If JMS clients are to be portable, they must be isolated from these proprietary aspects of a provider. This is done by defining JMS administered objects that are created and customized by a provider's administrator and later used by clients. The client uses them through JMS interfaces that are portable. The administrator creates them using provider-specific facilities.

There are two types of JMS administered objects:

• ConnectionFactory - This is the object a client uses to create a connection with a provider.
• Destination - This is the object a client uses to specify the destination of messages it is sending and the source of messages it receives.

Administered objects are placed in a JNDI namespace by an administrator. A JMS client typically notes in its documentation the JMS administered objects it requires and how the JNDI names of these objects should be provided to it.

Section 4.2 Administered Objects

JMS administered objects are objects containing JMS configuration information that are created by a JMS administrator and later used by JMS clients. They make it practical to administer JMS applications in the enterprise.

Although the interfaces for administered objects do not explicitly depend on JNDI, JMS establishes the convention that JMS clients find them by looking them up in a namespace using JNDI.

An administrator can place an administered object anywhere in a namespace. JMS does not define a naming policy.

This strategy of partitioning JMS and administration provides several benefits:

• It hides provider-specific configuration details from JMS clients.
• It abstracts JMS administrative information into Java objects that are easily organized and administered from a common management console.
• Since there will be JNDI providers for all popular naming services, this means JMS providers can deliver one implementation of administered objects that will run everywhere.

An administered object should not hold on to any remote resources. Its lookup should not use remote resources other than those used by JNDI itself.

Clients should think of administered objects as local Java objects. Looking them up should not have any hidden side effects or use surprising amounts of local resources.

JMS defines two administered objects, Destination and ConnectionFactory.

It is expected that JMS providers will provide the tools an administrator needs to create and configure administered objects in a JNDI namespace. JMS provider implementations of administered objects should be both javax.naming.Referenceable and java.io.Serializable so that they can be stored in all JNDI naming contexts. In addition, it is recommended that these implementations follow the JavaBeans design patterns.

Section 1.4.6 Java Naming and Directory InterfaceTM (JNDI) API

JMS clients look up configured JMS objects using the JNDI API. JMS administrators use provider-specific facilities for creating and configuring these objects.

This division of work maximizes the portability of clients by delegating provider-specific work to the administrator. It also leads to more administrable applications because clients do not need to embed administrative values in
their code.

Section 4.3.2 Client Identifier

The preferred way to assign a client’s client identifier is for it to be configured in a client-specific ConnectionFactory and transparently assigned to the connection it creates.

Comment by Nigel Deakin [ 27/Mar/12 ]

I am withdrawing this proposal in favour of a simpler alternative. To avoid confusion I have logged this as a separate issue, JMS_SPEC-89





[JMS_SPEC-23] Allow and specify clustered durable subscribers Created: 04/Jul/11  Updated: 09/Mar/12  Resolved: 09/Mar/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: F.Degenaar Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-40 Allow multiple consumers to be create... Resolved

 Description   

The current specification arguably disallows clustering durable subscibers by the following wording: "Only one session at a time can have a TopicSubscriber for a particular durable subscription."

At least one JMS provider (WebSphereMQ) allows multiple TopicSubscribers to the same durable subscription. The subscribers themselves basically act like receivers for a queue.

This feature helps avoiding a single point of failure.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 ]

Thank you for raising this. This is a good idea which others have proposed as well and is being considered by the expert group for inclusion in the JMS 2.0 early draft. There's a separate (subsequent) JIRA issue which contains the current proposals: JMS_SPEC-40.

I'm going to close this issue as it is a duplicate of that one. Please feel free to comment on that other issue, which will be updated as it is considered in more detail.





[JMS_SPEC-38] Allow JMS clients to specify whether a message is compressed in transit Created: 05/Aug/11  Updated: 06/Jan/12  Resolved: 06/Jan/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

This issue was raised by a member of the JSR 343 Expert Group and is logged here to allow the issue to be discussed and tracked.

This is a request to allow JMS clients to define whether a message is compressed in transit, perhaps on a per-message basis or more globally.

JMS providers are currently free to decide for themselves whether to compress a message, and many do, so the question here is whether it is desirable to allow clients to control this via the API rather than via provider configuration features.



 Comments   
Comment by colincrist [ 12/Sep/11 ]

I'd say this is an administrative configuration in the provider and out of the scope of the API. Allowing each endpoint to choose makes administering a large install a headache as you need a code change to enable compression.

Better for the provider to be configured centrally to make a client compress based on username/clientID/queue/topic/wildcard

Comment by Nigel Deakin [ 06/Jan/12 ]

I don't think there's a need for this. Many providers already offer message compression. The JMS spec deliberately doesn't define the wire format of a message and so providers are free to compress messages in transit if they wish to.

In my view, message compression is best configured using global settings in the provider rather than on a per-message basis. This is because whether message compression is needed for a given message depends on the performance characteristics of the provider itself: there is a trade-off between the extra time needed to compress and decompress a large message and the time saved in sending a smaller message down the wire. This trade-off will vary from provider to provider, and so allowing the application code to directly configure whether a message is compressed would reduce its portability.

A further reason for keeping message compression as a provider-specific configuration option rather than as part of the JMS API is that it allows providers to decide for themselves what configuration options they want to provider. Some providers may not support message compression at all. Others may offer a global switch to allow message compression to be switched on or off. Others may allow message compression to be defined on a per-destination basis. Other may allow the administrator to define a size threshold above which messages will be compressed. Finally, some providers may allow the administrator to configure what compression algorithm is used. I feel this is an area where it is beneficial to allow providers to differ and offer whatever features that they believe provide best performance.

Comment by Nigel Deakin [ 06/Jan/12 ]

We've discussed this on the JSR 343 expert group and the original proposer and decided not to proceed with this proposal. I'm therefore closing this issue with a resolution of "won't fix"





[JMS_SPEC-35] Remove the use of unchecked exceptions from the JMS API as far as possible Created: 29/Jul/11  Updated: 06/Jan/12  Resolved: 06/Jan/12

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

In JMS 1.1, almost every method in the JMS API throws a javax.jms.JMSException, which is a checked exception and so needs to be caught and handled by the application.

In practice the developer rarely knows what to do in such circumstances, and provides some generic exception handling that is not specific to JMSException. The result is to clutter the application code with boilerplate exception handling which adds little value.

In addition, the fact that so many API methods throw this checked exception makes it more difficult to construct frameworks on top of the JMS API.

It is therefore proposed that the JSR 343 Expert Group consider whether they should change the JMS API to throw unchecked rather than checked exceptions as much as possible. One simple way of achieving this would be to change javax.jms.JMSException to extend java.lang.RuntimeException instead of java.lang.Exception.

Existing applications which explicitly catch JMSException would not need to be changed.



 Comments   
Comment by rdohna [ 30/Aug/11 ]

fixed typos

Comment by Nigel Deakin [ 20/Oct/11 ]

The Java Tutorial contains the following useful discussion of when an exception should be checked or unchecked.
http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

This includes the advice:

If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

Given that in most cases a client cannot recover from a JMSException (which is why they tend to log the exception and rethrow it), making it an unchecked exception seems appropriate in this case.

Comment by Nigel Deakin [ 20/Oct/11 ]

I've received this comment:

try {
   a{};
} catch (RuntimeException rte){
   b{};
} catch (MyException e) {
   c();
}

In JMS 1.1, if a JMSException in throw in a(), then c() will be called. However if JMSException is changed as proposed above, b() will be called. Also, the above code will not compile because c() is unreachable.

This means that we cannot guarantee that this change will never require code changes.

Comment by Nigel Deakin [ 06/Jan/12 ]

Unfortunately, as noted in the previous comment, to simply make JMSException a subtype of RuntimeException would be an incompatible change as defined in the Java EE compatibility requirements:
http://java.net/projects/javaee-spec/pages/CompatibilityRequirements
This means that this change is not allowed.

There is no reason why new exception classes cannot be defined which are subtypes of RuntimeException and which are thrown by any new methods that are added to JMS. This has been done in the proposed simplified JMS API: http://java.net/jira/browse/JMS_SPEC-64

Comment by Nigel Deakin [ 06/Jan/12 ]

Since this proposal cannot be implemented (for existing methods) without breaking Java EE compatibility requirements, it will be closed with a resolution of "won't fix".





[JMS_SPEC-167] JMS 2.0: Session javadoc should mention consumer.close is allowed outside thread of control Created: 22/Jan/15  Updated: 14/May/15  Resolved: 14/May/15

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: JMS 2.0 rev A

Type: Bug Priority: Minor
Reporter: chris.barrow Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-errata

 Description   

The class level javadoc for Session contains the following paragraph (my bolding):

Once a connection has been started, any session with one or more registered message listeners is dedicated to the thread of control that delivers messages to it. It is erroneous for client code to use this session or any of its constituent objects from another thread of control. The only exception to this rule is the use of the session or connection close method.

The last sentence should be augmented to include message consumer close since from JMS 2.0 that method is now explicitly allowed to be called from another thread (see JMS_SPEC-48 and MessageConsumer.close javadoc). Moreover, it should not really mention connection close because that is irrelevant (the connection is not a constituent object of the Session). Suggested rewording for the last sentence:

The only exceptions to this rule are the use of the session and message consumer close methods

.



 Comments   
Comment by Nigel Deakin [ 22/Jan/15 ]

I don't think the spec says that you are allowed to call MessageConsumer#close from outside the thread of control, though perhaps it should.

JMS_SPEC-48 and MessageConsumer.close javadoc say you can call this method from a message listener on its own consumer, but in that case it would still be called from the thread of control.

I suppose the connection close method is mentioned because it implicitly closes the session(s), and so could be considered to be "using this session".

Comment by Nigel Deakin [ 22/Jan/15 ]

Added to the list for JMS 2.1

Comment by chris.barrow [ 27/Jan/15 ]

My remark about being allowed to call MessageConsumer#close from any thread is based on the following:

  • from the javadoc:

    This method is the only {@code MessageConsumer} method that can be called concurrently.

  • from a comment in MS_SPEC-48 saying

    The JMS EG has agreed to revise the behaviour of consumer close to:...Allowing a consumer to be closed from any thread, even if it isn't the thread of control

Did I misunderstand?

Comment by Nigel Deakin [ 27/Jan/15 ]

Updated: Thanks for the follow-up. Looks like it was me who misunderstood. I agree with your proposal for the following reasons:

1. JMS 2.0 section 8.8 "closing a consumer" already says

close is the only method on a consumer that may be invoked from a thread of control separate from the one which is currently controlling the session.

So this change simply updates the javadocs for Session to say the same thing.

2. MessageConsumer.close contains the words words "This method is the only MessageConsumer method that can be called concurrently" in, which were added in JMS 2.0.

That sentence isn't very clear, but Session.close, has had identical wording since JMS 1.1, and I believe it is intended to mean that the method doesn't have to be called from the "thread of control".

3. Closing a session implicitly closes all consumers, so if session close can be called from outside the "thread of control" then it is reasonable to expect the same for consumer close.

So I agree with your proposal to amend the Session javadoc.

I'll see if we can fit it into the JMS 2.0 errata.

Comment by chris.barrow [ 27/Jan/15 ]

OK thanks.

Comment by Nigel Deakin [ 12/Feb/15 ]

Proposed changes to the class javadoc for Session

Existing text:

Once a connection has been started, any session with one or more registered message listeners is dedicated to the thread of control that delivers messages to it. It is erroneous for client code to use this session or any of its constituent objects from another thread of control. The only exception to this rule is the use of the session or connection close method.

Replacement text:

Once a connection has been started, any session with one or more registered message listeners is dedicated to the thread of control that delivers messages to it. It is erroneous for client code to use this session or any of its constituent objects from another thread of control. The only exception to this rule is the use of the session or message consumer close method.

Comment by Nigel Deakin [ 12/Feb/15 ]

Updated source

The draft JMS 2.0 javadocs can be viewed at
https://jms-spec.java.net/2.0RevA-SNAPSHOT/apidocs/index.html

Updated source for javax.jms.Session can be viewed at, and downloaded from,
https://java.net/projects/jms-spec/sources/repository/content/jms2.0a/src/main/java/javax/jms/Session.java?rev=328

Diffs can be viewed at
https://java.net/projects/jms-spec/sources/repository/diff/jms2.0a/src/main/java/javax/jms/Session.java?rev1=327&rev2=328

Comment by chris.barrow [ 12/Feb/15 ]

Thanks, looks good.

Comment by Nigel Deakin [ 14/May/15 ]

Fixed in the JMS 2.0 rev A maintenance release





[JMS_SPEC-60] Obscurity setting special JMSHeaders Created: 17/Nov/11  Updated: 22/Nov/11  Resolved: 22/Nov/11

Status: Closed
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Minor
Reporter: koen.serneels Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by JMS_SPEC-34 Calling setJMSDeliveryMode or setJMSP... Resolved

 Description   

Currently it is specced that some headers can only set by "send or publish" method.
This is very confusing. For example someone not knowing about this might be tempted to set JMSPriority on a message.
This will not trigger any exception, but in the end be completely ignored if send by he regular send method (.send(message)) instead of the overloaded send(message, deliveryMode, priority, timeToLive).
The question is; why are these headers mutable on the javax.jms.Message in the first place?



 Comments   
Comment by rdohna [ 21/Nov/11 ]

We assume that the setters are there for cross-provider posting, i.e. a client consumes a message from a destination bound to one JMS provider (say Glassfish MQ) and resends it to a destination bound to another JMS provider (say Active MQ). The outgoing provider may want to set the priority of that message object, while it doesn't know which implementation it is.

But you are right: It's very confusing.

Comment by Nigel Deakin [ 22/Nov/11 ]

Changing Issue Type to "Improvement"
Changing priority to "Low priority"

Comment by Nigel Deakin [ 22/Nov/11 ]

This issue is a duplicate of JMS_SPEC-34

I've added some additional information to JMS_SPEC-34 which explains why these methods are needed and confirms that the javadoc will be clarified.

I'll close this issue as a duplicate. Feel free to continue any discussion on JMS_SPEC-34

Comment by Nigel Deakin [ 22/Nov/11 ]

Corrected "Affects version" to 1.1.





[JMS_SPEC-27] Clarify the relationship between the JMS and other Java EE specifications Created: 06/Jul/11  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Critical
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: ed20-added

 Description   

Summary

We need to clarify the relationship between the JMS and other Java EE specifications. This is mainly a documentation exercise, especially for those methods which are forbidden or modified in a EJB or Web container, but there are some ambiguities, especially when the transaction context is undefined.

More detail

If you want use the JMS API in a Java EE application such as a EJB or servlet you soon discover that much of the JMS spec (including the JMS javadocs) does not apply, at least in the EJB and web containers. For example, you aren't allowed to create message listeners, you need to defined MDBs instead. You aren't allowed to create local transactions, you need to use CMT or BMT transactions instead. You aren't allowed to set clientID on a connection. You aren't allowed to perform client acknowledgement. Essentially, in a Java EE container, the JMS API is simply different. However this is not explained in the JMS spec but is described in other specs, notably the EJB and Java EE platform specs.

Some of this information of necessity in other specs, but the absence of any mention of it in the JMS spec or javadocs is confusing to users.

I would like the JMS expert group to review what it says about JMS in other specs and consider whether this material should be moved to the JMS spec, duplicated in the JMS spec, or cross-referenced from the JMS spec. In addition the javadocs need to be clarified to mention that some API is not allowed, or has a different effect, in a Java EE web or EJB container.

I see this mainly as a documentation exercise. However this analysis will inevitably identify that some areas of behaviour are not well defined. For example, the EJB spec states explicitly that in an "undefined transactional context" it is not defined how the JMS provider should handle transactions. This means that vendors may behave differently which reduces the portability of application. If possible this should be resolved.



 Comments   
Comment by Nigel Deakin [ 26/Jan/12 ]

I've now updated the API, javadocs and the draft spec.
The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

I've written a completely new section to add to the new chapter 12 "Use of JMS API in Java EE applications" which was added for JMS_SPEC-45. This is intended to simply restate what is already defined in the EJB 3.1 and Java EE 6 platform specs, though I have extended it to cover the simplified API. here it is:

12.2. Restrictions on the use of JMS API in the Java EE web or EJB container

JMS applications which run in the Java EE web or EJB container are subject to a number of restrictions in the way the JMS API may be used. These restrictions are necessary for the following reasons:

  • In a Java EE web or EJB container, a JMS provider operates as a transactional resource manager which must participate in JTA transactions as defined in the Java EE platform specification. This overrides the behaviour of JMS sessions as defined elsewhere in the JMS specification. For more details see section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container".
  • The Java EE web or EJB containers need to be able to manage the threads used to run applications.
  • The Java EE web and EJB containers perform connection management which may include the pooling of JMS connections.

The restrictions described in this section do not apply to the Java EE application client container.
Applications running in the Java EE web and EJB containers must not attempt to create more than one active (not closed) Session object per connection.

  • If an application attempts to use the Connection object’s createSession method when an active Session object exists for that connection then a JMSException should be thrown.
  • If an application attempts to use the MessagingContext object's createMessagingContext method then a JMS{{RuntimeException}} should be thrown, since the first messaging context already contains a connection and session and this method would create a second session on the same connection.

The following methods are intended for use by the application server and their use by applications running in the Java EE web or EJB container may interfere with the container's ability to properly manage the threads used in the runtime environment. They must therefore not be called by applications running in the Java EE web or EJB container:

  • javax.jms.Session method setMessageListener
  • javax.jms.Session method getMessageListener
  • javax.jms.Session method setBatchMessageListener
  • javax.jms.Session method getBatchMessageListener
  • javax.jms.Session method run
  • javax.jms.Connection method createConnectionConsumer
  • javax.jms.Connection method createDurableConnectionConsumer

The following methods may interfere with the container's ability to properly manage the threads used in the runtime environment and must not be used by applications running in the Java EE web or EJB container:

  • javax.jms.MessageConsumer method setMessageListener
  • javax.jms.MessageConsumer method getMessageListener
  • javax.jms.MessageConsumer method setBatchMessageListener
  • javax.jms.MessageConsumer method getBatchMessageListener
  • javax.jms.MessagingContext method setMessageListener
  • javax.jms.MessagingContext method getMessageListener
  • javax.jms.MessagingContext method setBatchMessageListener
  • javax.jms.MessagingContext method getBatchMessageListener

This restriction means that applications running in the Java EE web or EJB container which need to receive messages asynchronously may only do so using message-driven beans.

The following methods may interfere with the container's management of connections and must not be used by applications running in the Java EE web or EJB container:

  • javax.jms.Connection method setClientID
  • javax.jms.Connection method stop
  • javax.jms.Connection method setExceptionListener
  • javax.jms.MessagingContext method setClientID
  • javax.jms.MessagingContext method stop
  • javax.jms.MessagingContext method setExceptionListener

Applications which need to use a specific client identifier must set it on the connection factory, as described in section 4.3.2 "Client Identifier"

All the methods listed in this section may throw a javax.jms.JMSException (if allowed by the method) or a javax.jms.JMSRuntimeException (if not) when called by an application running in the Java EE web or EJB container. This is recommended but not required.

Comment by Nigel Deakin [ 26/Jan/12 ]

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The javadocs for all the methods listed above which are not permitted in a Java EE web or Java EE container now include the following statement:

* This method must not be used in a Java EE web or EJB application. 
* Doing so may cause a <code>JMSException</code> to be thrown though this is not guaranteed.

In addition, the list of exceptions for these methods now states that they may throw a JMSException (or JMSRuntimeException if called in a Java EE web or EJB container, together with the caveat that "it is not guaranteed that an exception is thrown in this case"

The three Connection methods createSession now include the statement:

* Applications running in the Java EE web and EJB containers must not attempt 
* to create more than one active (not closed) <code>Session</code> object per connection. 
* If this method is called in a Java EE web or EJB container when an active
* <code>Session</code> object already exists for this connection 
* then a <code>JMSException</code> will be thrown.

The list of exceptions for these methods states that they will (must) throw a JMSException if "this method is being called in a Java EE web or EJB application and an active session already exists for this connection."

The MessageConsumer method createMessagingContext now includes the statement:

* This method is for use in a Java SE environment or in the Java EE application client container only. 
* It may not be used in a Java EE environment because this would violate
* the Java EE restriction that a connection may have only one session.

The list of exceptions for this method now states that it will (must) throw an exception if "this method is being called in a Java EE web or EJB application"

Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-33] Improving the JMS API with API simplifications, annotations and CDI Created: 21/Jul/11  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0PD, 2.0

Type: Improvement Priority: Critical
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JMS_SPEC-64 Define simplified JMS API Resolved
depends on JMS_SPEC-70 Define annotations for injecting Mess... Resolved
Tags: ed20-added

 Description   

We should provide a modern, easier-to-use API, probably using annotations and CDI. There seemed to be a variety of ideas of how we might do this, and we will need to explore these in detail. Whilst I think we mostly see this as a feature for Java EE containers, there seems to be interest in offering features to those using a Java SE environment as well.

(This issue is a placeholder for discussion on the JSR 343 EG. More information will be added later)



 Comments   
Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-30] Define mandatory activation config properties clientId and subscriptionName Created: 14/Jul/11  Updated: 20/Mar/13  Resolved: 07/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Critical
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on EJB_SPEC-41 Define mandatory activation config pr... Resolved
blocks MQ-251 Implement JMSRA activation properties... Closed
Related
is related to JMS_SPEC-54 Define a standard way to configure th... Resolved
Tags: jms20-jsr345, pd20-added

 Description   

This is a request for the JMS and/or EJB specifications to define additional mandatory activation config properties for JMS MDBs. Although MDBs are specified in the EJB specification, this request should be considered first by the JMS 2.0 expert group who may then want to raise it with the EJB 3.2 expert group.

The EJB 3.1 spec is distinctly vague about how a MDB is defined. The relevant sections are 5.4.15, 5.4.16 and 5.4.17.1. The only activation config properties defined are acknowledgeMode (only used when transactions are bean-managed, and which must be either Auto-acknowledge or Dups-ok-acknowledge), messageSelector, destinationType (which must be must be either javax.jms.Queue or javax.jms.Topic) and subscriptionDurability (which must be either Durable or NonDurable). But it doesn't specify how the destination is defined or, when subscriptionDurability is Durable, how the subscription name and client identifier are defined.

The JCA 1.6 spec has some additional guidance, at least for MDBs that use a resource adapter. Section B2 states that providers are "strongly encouraged" to provide the properties mentioned above and also destination, subscriptionName and clientId, with destination and destinationType as "required" properties.

Whatever else we do, there seems to be a clear need to make these mandatory for JMS MDBs, whether or not they use JCA.

The JMS 2.0 and EJB 3.2 expert groups should also decide whether the EJB spec is the best place to list such JMS-specific details. Although MDBs (which are not just for JMS) should remain in the EJB spec, perhaps any additional specification for JMS MDBs should be in the JMS spec.



 Comments   
Comment by Nigel Deakin [ 15/Sep/11 ]

Following discussions, it is proposed that changes are sought to the EJB 3.2 spec to add additional activation configuration properties clientId and subscriptionName for JMS message-driven beans as follows:

Section 5.4 of the EJB 3.1 spec currently defines the the following activation configuration properties for JMS message-driven beans:
acknowledgeMode (optional, default is AUTO_ACKNOWLEDGE)
messageSelector (default is an empty String)
destinationType (optional, no default)
subscriptionDurability (default is NonDurable)

This should be extended to define the following additional activation configuration properties:

clientId
subscriptionName

These property names match those recommended in JCA 1.6.

If set, clientId would be used to set clientId for the connection used by the MDB, and must be unique in accordance with JMS 1.1. There would be no default value. JMS 1.1 states that clientId must be set if a durable subscription is being used. However in JMS 2.0 JMS_SPEC-39 proposes that this requirement would be removed and clientId would always be optional.

If a durable subscription is being used, then JMS requires that subscriptionName be set. In the case of a MDB the subscriptionName is normally given a name unique to the MDB, to distinguish it from other MDBs and other applications subscribed to the same topic. It is therefore proposed that the EJB specification state that if the subscription is durable and subscriptionName is not set then the container will automatically set subscriptionName to the name of the MDB.

As with the existing activation configuration properties for JMS message-driven beans defined in the EJB specification, clientId and subscriptionName could be specified either using the MessageDriven annotation

@MessageDriven(activationConfig =  {
    @ActivationConfigProperty(propertyName = "subscriptionDurability.", propertyValue = "Durable"),
    @ActivationConfigProperty(propertyName = "clientId", propertyValue = "MyMDB"),
    @ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "MySub")
})

or in ejb-jar.xml:

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>test.MyMDB</ejb-name>
      <activation-config>
         <activation-config-property>
            <activation-config-property-name>subscriptionDurability</activation-config-property-name>
            <activation-config-property-value>Durable</activation-config-property-value>
         </activation-config-property>
         <activation-config-property>
            <activation-config-property-name>clientId</activation-config-property-name>
            <activation-config-property-value>MyMDB</activation-config-property-value>
         </activation-config-property>
         <activation-config-property>
            <activation-config-property-name>subscriptionName</activation-config-property-name>
            <activation-config-property-value>MySub</activation-config-property-value>
         </activation-config-property>                  
      </activation-config>
    </message-driven>
  </enterprise-beans>
</ejb-jar>

Note: The issue of how to define the destination on which a JMS message-driven bean listens for messages will be considered separately, as this is a more complex topic.

Comment by Nigel Deakin [ 07/Nov/11 ]

Added tag jsr345 to identify that this issue requires changes to the EJB spec, not the JMS spec

Comment by Nigel Deakin [ 05/Dec/12 ]

Renaming issue to reflect the fact that this issue covers the activation config properties clientId and subscriptionName only.

Comment by Nigel Deakin [ 07/Feb/13 ]

The activation properties clientId and subscriptionName are now defined in the JMS 2.0 specification, section 13.1 "MDB activation properties" as follows:

Activation property Description
clientId This property may be used to specify the client identifier that will be used when connecting to the JMS provider from which the endpoint (message-driven bean) is to receive messages.

Setting this property is always optional.
subscriptionName This property only applies to endpoints (message-driven beans) that receive messages published to a topic. It may be used to specify the name of the durable or non-durable subscription.

The EJB 3.2 specification has also been updated with a consistent definition.

Now that this feature has been added to the JMS 2.0 and EJB 3.2 specifications, this issue can be marked as resolved.





[JMS_SPEC-80] Error in example 9.3.3.2 "Reconnect to a topic using a durable subscription" Created: 21/Feb/12  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: 2.0PD, 2.0

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-added

 Description   

Section 9.3.3.2 "Reconnect to a topic using a durable subscription" of the JMS 1.1 specification gives an example of how a client can reconnect to an existing durable subscription. It says:

there are some important restrictions to be aware of:

  • The client must be attached to the same Connection.
  • The Destination and subscription name must be the same.
  • If a message selector was specified, it must also be the same.
    If these conditions are not met, then the durable subscription is deleted, and a new subscription is created.

The first of these points is incorrect. The Connection need not be the same. However the client identifier must be the same as was used when creating the durable subscription originally.



 Comments   
Comment by Nigel Deakin [ 14/May/12 ]

In the JMS 1.1 specification, the whole of this section is

9.3.3.2. Reconnecting to a topic using a durable subscription

To re-connect to a topic that has an existing durable subscription, the client program can simply call session.CreateDurableSubscriber again, using the same parameters that it previously used. A client program may be intermittently connected. Using durable subscriptions allows messages to still be available to a client program that consumes from a topic, even though the client program was not continuously connected.

/* Reconnect to a durable subscription */
session.createDurableSubscriber(newsFeedTopic,"mySubscription");

This reconnects the client program to the topic, and any messages that arrived while the client was disconnected are delivered.

However, there are some important restrictions to be aware of:

• The client must be attached to the same Connection.
• The Destination and subscription name must be the same.
• If a message selector was specified, it must also be the same.

If these conditions are not met, then the durable subscription is deleted, and a new subscription is created.

Comment by Nigel Deakin [ 14/May/12 ]

I've now updated the draft spec with the following updated text, which corrects this error and also updates it to reflect the fact that a durable subscription may have more than one consumer, and to make a more accurate distinction between topic, durable subscription and consumer.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

Here is the new text:

9.3.3.2. Creating a consumer on an existing durable subscription

Once a durable subscription has been created it will continue to accumulate messages until the subscription is deleted using the Session method unsubscribe, even if the original consumer is closed leaving no consumer on the durable subscription.

A client application may create a consumer on an existing durable subscription by calling one of the Session methods createDurableConsumer or createDurableSubscriber, supplying the same parameters that were specified when the durable subscription was first created.

/* Create a consumer on an existing durable subscription */
session.createDurableConsumer(newsFeedTopic, "mySubscription");

If there were no consumers on the durable subscription prior to calling this method then any messages which were added to the subscription whilst it had no consumers will be delivered.

A durable subscription may have more than one active consumer (this was not permitted prior to JMS 2.0). Each message from the subscription will be delivered to only one of the consumers on that subscription.

When creating a consumer on an existing durable subscription there are some important restrictions to be aware of:

• The Destination and subscription name must be the same as when the durable subscription was first created.

• If the connection's client identifier was set when the durable subscription was first created then the same client identifier must be set when subsequently creating a consumer on it.

• If a message selector was specified when the durable subscription was first created then the same message selector must be specified when subsequently creating a consumer on it.

The change log has been updated to add the following new section:

B.5.19 Correction: Reconnecting to a durable subscription (JMS_SPEC-80)

In the JMS 1.1 specification, section 9.3.3.2 "Reconnect to a topic using a durable subscription" stated that "the client must be attached to the same Connection". This was incorrect and has been corrected to state that the client must use a connection with the same client identifier.

In addition this section has been renamed 9.3.3.2 "Creating a consumer on an existing durable subscription" and rewritten to make it clearer.





[JMS_SPEC-81] Remove Change History for previous versions from the specification Created: 21/Feb/12  Updated: 20/Mar/13  Resolved: 14/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fd20-doc-added

 Description   

The JMS 1.1 specification contains in chapter 11 a detailed list of changes that were introduced in version 1.0.1, 1.0.2, 1.0.2b and 1.1. These all relate to changes made a decade ago. They are of interest only to historians of JMS, and have no value in the JMS 2.0 specification other than to clutter up the spec. They should be removed.

This information will remain in the JMS 1.1 specification for the benefit of future historians.

(For the avoidance of doubt, the JMS 2.0 spec should of course contain a list of changes made between 1.1 and 2.0)



 Comments   
Comment by Nigel Deakin [ 14/Feb/13 ]

Now done in the JMS 2.0 proposed final draft.





[JMS_SPEC-78] JMS implementation of QueueRequestor and TopicRequestor doesn't throw correct exception when destination is null Created: 16/Feb/12  Updated: 20/Mar/13  Resolved: 04/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-197 JMS TCK test queueRequestorExceptionT... Closed
Tags: pd20-added

 Description   

The javadocs for the constructor methods QueueRequestor(session,queue) and TopicRequestor(session,topic) state that a InvalidDestinationException should be thrown if an invalid queue/topic is specified.

http://docs.oracle.com/javaee/6/api/javax/jms/QueueRequestor.html
http://docs.oracle.com/javaee/6/api/javax/jms/TopicRequestor.html

However if a value of null is supplied no exception is thrown, despite this not being valid.

These classes are supplied with JMS rather than by implementations, which is why this is being logged here rather than with any particular JMS provider.

If you look at the implementation:

    public
    QueueRequestor(QueueSession session, Queue queue) throws JMSException {
        this.session = session;
        this.queue   = queue;
        tempQueue    = session.createTemporaryQueue();
        sender       = session.createSender(queue);
        receiver     = session.createReceiver(tempQueue);
    }

you can see why it doesn't throw an exception. Calling createQueue(null) is valid as it creates an anonymous producer. However although this is valid in general it isn't valid here. An explicit check for null needs to be added which should cause a InvalidDestinationException to be thrown.



 Comments   
Comment by Nigel Deakin [ 04/Sep/12 ]

Now fixed.

Note that the implementation of these classes is actually part of the RI.





[JMS_SPEC-70] Define annotations for injecting MessagingContext objects Created: 03/Feb/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JMS_SPEC-64 Define simplified JMS API Resolved
blocks MQ-177 Implement injection of JMSContext obj... Closed
blocks JMS_SPEC-33 Improving the JMS API with API simpli... Resolved
Tags: pd20-added

 Description   

The simplified API (JMS_SPEC-64) defines a single object, javax.jms.MessagingContext, which provides methods for sending and receiving messages.

It is proposed that the JMS API define some standard annotations that can be used to inject MessagingContext objects into application code.

  • The injection point should allow the application define the two parameters needed to create a MessagingContext: JNDI name (of the connection factory) and sessionMode. Both should be optional with suitable defaults.
  • The implementation should ideally be implemented using CDI and have behaviour consistent with it. However this is not essential.
  • It must be possible to use injection in Java EE applications. It is desirable but not essential to be able to use injection in Java SE applications.
  • Injected MessagingContexts must have an appropriate scope and must be automatically closed when they fall out of scope.


 Comments   
Comment by Nigel Deakin [ 08/Feb/12 ]

Here is the proposed text to be added to the JMS spec:

This section relates to application classes which run in the Java EE web, EJB or application client containers and which support injection. Section EE.5 of the Java EE specification lists the application classes that support injection.

Applications may declare a field of type javax.jms.MessagingContext and annotate it with the javax.inject.Inject annotation:

@Inject
private MessagingContext context;

The container will inject a MessagingContext. It will have request scope and will be automatically closed when the request ends. However, unlike a normal CDI request-scoped object, a separate MessagingContext instance will be injected for every injection point.

The annotation javax.jms.JMSConnectionFactory may be used to specify the JNDI lookup name of the ConnectionFactory used to create the messaging context. For example:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
private MessagingContext context;

If no lookup name is specified or the JMSConnectionFactory annotation is omitted then the platform default JMS connection factory will be used.

The annotation javax.jms.JMSSessionMode may be used to specify the session mode of the messaging context:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
@JMSSessionMode(MessagingContext.AUTO_ACKNOWLEDGE)
private MessagingContext context;

The meaning and possible values of session mode are the same as for the ConnectionFactory method createMessagingContext(int sessionMode):

  • In the Java EE application client container, session mode may be set to any of MessagingContext.SESSION_TRANSACTED, MessagingContext.CLIENT_ACKNOWLEDGE, MessagingContext.AUTO_ACKNOWLEDGE or MessagingContext.DUPS_OK_ACKNOWLEDGE. If no session mode is specified or the JMSSessionMode annotation is omitted a session mode of MessagingContext.AUTO_ACKNOWLEDGE will be used.
  • In a Java EE web or EJB container, when there is an active JTA transaction in progress, session mode is ignored and the JMSSessionMode annotation is unnecessary.
  • In a Java EE web or EJB container, when there is no active JTA transaction in progress, session mode may be set to either of MessagingContext.AUTO_ACKNOWLEDGE or MessagingContext.DUPS_OK_ACKNOWLEDGE. If no session mode is specified or the JMSSessionMode annotation is omitted a session mode of MessagingContext.AUTO_ACKNOWLEDGE will be used.

For more information about the use of session mode when creating a messaging context, see section 10.3 of the JMS 2.0 Early Draft, "Behaviour of JMS sessions in the Java EE web or EJB container" and the API documentation for the ConnectionFactory method createMessagingContext(int sessionMode).

Comment by Nigel Deakin [ 08/Feb/12 ]

The proposed new annotations are as follows:

New annotation javax.jms.JMSConnectionFactory:

package javax.jms;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * This optional annotation may be used to specify the JNDI lookup name of a <code>javax.jms.ConnectionFactory</code>
 * to be used when injecting a <code>javax.jms.MessagingContext</code> object.
 */
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface JMSConnectionFactory {
    /**
     * (Optional) Specifies the JNDI lookup name of a <code>javax.jms.ConnectionFactory</code>
     * to be used when injecting a <code>javax.jms.MessagingContext</code> object.
     */
    String value() default "";
}

New annotation javax.jms.JMSSession:

package javax.jms;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * This optional annotation may be used to specify the session mode
 * to be used when injecting a <code>javax.jms.MessagingContext</code> object.
 * The meaning and possible values of session mode are the same as for the 
 * <code>ConnectionFactory</code> method <code>createMessagingContext(int sessionMode)</code>.
 * 
 * @see javax.jms.MessagingContext#createMessagingContext(int) 
 */
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface JMSSessionMode {
    /**
     * (Optional) Specifies the session mode used when injecting a <code>javax.jms.MessagingContext</code> object.
     */
    int value() default MessagingContext.AUTO_ACKNOWLEDGE;
}
Comment by Nigel Deakin [ 10/Feb/12 ]

I've now updated the API, javadocs and the draft spec in accordance with the proposals made above.

The updated API and Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The only changes are the two annotations javax.jms.JMSConnectionFactory and javax.jms.JMSSession.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

See particularly the new section 13.3 "Injection of MessagingContext objects" and a full set of examples in section 11.4 "Examples using the simplified API". The change log for the simplified API, section B.5.12 has also been updated.

Comment by Nigel Deakin [ 17/Feb/12 ]

I've updated the API, javadocs and the draft spec in accordance with the following changes.

The updated API and Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

A new annotation has been added to allow the application to specify the user and password to be used when injecting a MessagingContext:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
@JMSPasswordCredential(userName="admin",password="mypassword")
private MessagingContext context;

A new annotation has been added to allow the application to configure whether the connection is automatically started when a consumer is created:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
@JMSSessionMode(MessagingContext.AUTO_ACKNOWLEDGE)
@JMSAutoStart(false)
private MessagingContext context;
Comment by Nigel Deakin [ 21/Sep/12 ]

This feature has been further revised: an up-to-date description may be found in section 11.3 "Injection of JMSContext objects" in the JMS 2.0 public draft.

11.3. Injection of JMSContext objects

Comment by Nigel Deakin [ 26/Oct/12 ]

This issue is now closed as a full definition of how JMSContext objects may be injected will be included in the JMS 2.0 public draft.





[JMS_SPEC-69] Clarify that QueueRequestor and TopicRequestor only work in a non-transacted session with auto or dups-ok ack Created: 30/Jan/12  Updated: 20/Mar/13  Resolved: 11/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fd20-doc-added

 Description   

The javadocs for QueueRequestor and TopicRequestor state that "This implementation assumes the session parameter to be non-transacted, with a delivery mode of either AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE".

  • There is no mention of this in the spec in section 5.10 "QueueRequestor" or 6.14 "TopicRequestor". This should be clarified.
  • In addition, the class comment should also mention this restriction.

There is no reason why a user could not implement a modified version of this class which uses client-ack. However there is a more general issue regarding the use of transactions with request-reply messaging:

  • It would also be worth mentioning the general point that if an application implements request/reply messaging, the request message must not be sent within the same transaction as the reply is received.
  • It would also be worth mentioning that this means that a QueueRequestor and TopicRequestor cannot be used in a Java EE web or EJB container when there is an active JTA transaction.
  • The following text copied from the EJB spec might be worth including in a modified form somewhere in the spec (in the 2.0 Early Draft it has been added to Section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" but since this isn't specific to Java EE it should be moved somewhere more appropriate)

The Bean Provider should not make use of the JMS request/reply paradigm (sending of a JMS message, followed by the synchronous receipt of a reply to that message) within a single transaction. Because a JMS message is typically not delivered to its final destination until the transaction commits, the receipt of the reply within the same transaction will not take place.



 Comments   
Comment by Nigel Deakin [ 11/Feb/13 ]

The JMS 2.0 proposed final draft has been amended to say:

4.1.6 QueueRequestor

The legacy domain-specific API for point-to-point messaging provides a QueueRequestor helper class to simplify making service requests.

The QueueRequestor constructor is given a non-transacted QueueSession and a destination queue. It creates a TemporaryQueue for the responses and provides a request method that sends the request message and waits for its reply.

This is a very basic request/reply abstraction which assumes the session is non-transacted with a delivery mode of either AUTO_ACKNOWLEDGE}] or {{DUPS_OK_ACKNOWLEDGE. It is expected that most applications will create less basic implementations.

There is no equivalent to this class for the classic or simplified APIs. Applications using these APIs are expected to create their own implementations.

The Javadoc for QueueRequestor has been modified to say the same thing:

/** The {@code QueueRequestor} helper class simplifies
  * making service requests.
  *
  * <P>The {@code QueueRequestor} constructor is given a non-transacted 
  * {@code QueueSession} and a destination {@code Queue}. It creates a
  * {@code TemporaryQueue} for the responses and provides a 
  * {@code request} method that sends the request message and waits 
  * for its reply.
  * <p>
  * This is a very basic request/reply abstraction which assumes the session 
  * is non-transacted with a delivery mode of either AUTO_ACKNOWLEDGE or 
  * DUPS_OK_ACKNOWLEDGE. It is expected that most applications will create 
  * less basic implementations.
  *
  * @version 2.0
  * @since 1.0
  * @see javax.jms.TopicRequestor
  */

4.2.10 TopicRequestor

The legacy domain-specific API for pub/sub messaging provides a TopicRequestor helper class to simplify making service requests.

The TopicRequestor constructor is given a non-transacted TopicSession and a destination topic. It creates a TemporaryTopic for the responses and provides a request method that sends the request message and waits for its reply.

This is a very basic request/reply abstraction which assumes the session is non-transacted with a delivery mode of either AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE. It is expected that most applications will create less basic implementations.

There is no equivalent to this class for the classic or simplified APIs. Applications using these APIs are expected to create their own implementations.

The Javadoc for TopicRequestor has been modified to say the same thing:

/** The {@code TopicRequestor} helper class simplifies
  * making service requests.
  *
  * <P>The {@code TopicRequestor} constructor is given a non-transacted 
  * {@code TopicSession} and a destination {@code Topic}. It creates a 
  * {@code TemporaryTopic} for the responses and provides a 
  * {@code request} method that sends the request message and waits 
  * for its reply.
  * <p>
  * This is a very basic request/reply abstraction which assumes the session 
  * is non-transacted with a delivery mode of either AUTO_ACKNOWLEDGE or 
  * DUPS_OK_ACKNOWLEDGE. It is expected that most applications will create 
  * less basic implementations.
  *
  * @version 2.0
  * @since 1.0
  * @see javax.jms.QueueRequestor
  */
Comment by Nigel Deakin [ 11/Feb/13 ]

Resolved in the JMS 2.0 final draft.





[JMS_SPEC-65] Clarify use of NoLocal arg when using createDurableSubscriber Created: 22/Dec/11  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-168 Implement clarified behaviour of noLo... Closed
Tags: ed20-added

 Description   

This issue relates to the following method on javax.jms.Session:

TopicSubscriber createDurableSubscriber(Topic topic,
                                        java.lang.String name,
                                        java.lang.String messageSelector,
                                        boolean noLocal)
                                        throws JMSException

What does noLocal mean in this context? The javadoc states that this method "Creates a durable subscriber to the specified topic, using a message selector and specifying whether messages published by its own connection should be delivered to it". However it is ambiguous whether "it" refers to the durable subscription in the JMS provider or the TopicSubscriber object.

Does noLocal mean
(1) that messages published by this connection should not be added to the durable subscription, or that
(2) messages published by this connection should not be delivered to this particular TopicSubscriber? These do not mean the same thing, since in the latter case the messages might be saved in the subscription and delivered at some later stage.

This should be clarified.



 Comments   
Comment by Nigel Deakin [ 22/Dec/11 ]

The suggested interpretation is that it means (1): that messages published by its own connection should not be added to the durable subscription.

Comment by Hiram Chirino [ 22/Dec/11 ]

Agree it should be (1). Otherwise you will get an inconsistent behavior once a consumer reconnects, and lets face it folks hate inconsistencies.

Comment by Nigel Deakin [ 09/Jan/12 ]

I've now updated the draft spec and javadocs with details of this new feature (these changes are additive, so those docs include other changes).

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

Section 6.11 "TopicSubscriber" has been reworded to state that "When a non-durable subscription is created on a topic, the noLocal argument may be used to specify that the subscriber must not receive messages published to the topic by its own connection."

Section 6.11.1 "Durable TopicSubscriber" has been reworded to state that "When a durable subscription is created on a topic, the noLocal argument may be used to specify that messages published to the topic by its own connection must not be added to the durable subscription."

These changes are also listed in the change log, section 11.5.13.

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

I've clarified the javadocs for the existing methods on Session that create both durable and non-durable subscribers:

Change to javadoc comment for Session.createConsumer(destination, messageSelector, NoLocal), which returns a MessageConsumer. This is used for non-durable topic subscriptions and for queues.

Old comment:

     /** Creates <CODE>MessageConsumer</CODE> for the specified destination, using a
      * message selector. This method can specify whether messages published by
      * its own connection should be delivered to it, if the destination is a
      * topic.

      . . .

      * <P>In some cases, a connection may both publish and subscribe to a
      * topic. The consumer <CODE>NoLocal</CODE> attribute allows a consumer
      * to inhibit the delivery of messages published by its own connection.
      * The default value for this attribute is False. The <CODE>noLocal</CODE>
      * value must be supported by destinations that are topics.

      . . .

      * @param NoLocal  - if true, and the destination is a topic,
      *                   inhibits the delivery of messages published
      *                   by its own connection.  The behavior for
      *                   <CODE>NoLocal</CODE> is
      *                   not specified if the destination is a queue.

New comment:

     /** Creates <CODE>MessageConsumer</CODE> for the specified destination, using a
      * message selector. This method can specify whether messages published by
      * its own connection should be delivered to it, if the destination is a
      * topic.

      . . .

      * <P>The <code>NoLocal</code> argument is for use when the
      * destination is a topic and the session's connection
      * is also being used to publish messages to that topic.
      * If <code>NoLocal</code> is set to true then the
      * <code>MessageConsumer</code> will not receive messages published
      * to the topic by its own connection. The default value of this
      * argument is false. If the destination is a queue
      * then the effect of setting <code>NoLocal</code>
      * to true is not specified.

      . . .

      * @param NoLocal  - if true, and the destination is a topic,
      *                   then the <code>MessageConsumer</code> will
      *                   not receive messages published to the topic
      *                   by its own connection.

Change to javadoc comment for Session.createDurableSubscriber(topic, name, messageSelector, noLocal), which returns a TopicSubscriber. This is used for durable topic subscriptions.

Old comment:

   /** Creates a durable subscriber to the specified topic,
        using a message selector and specifying whether messages
        published by its own connection should be delivered to it.

       . . .

     * @param noLocal if set, inhibits the delivery of messages published
     * by its own connection

New comment:

    /** Creates a durable subscription with the specified name on the
     * specified topic, and creates a <code>TopicSubscriber</code>
     * on that durable subscription, specifying a message
     * selector and whether messages published by its
     * own connection should be added to the durable subscription.

     . . .

     * <P>The <code>NoLocal</code> argument is for use when the session's
     * connection is also being used to publish messages to the topic.
     * If <code>NoLocal</code> is set to true then messages published
     * to the topic by its own connection will not be added to the
     * durable subscription. The default value of this
     * argument is false.

     . . .

     * @param noLocal if true, messages published by its own connection
     * will not be added to the durable subscription.

I've also updated the javadoc comment for Session.createDurableConsumer(topic, name, messageSelector, noLocal), which returns a MessageConsumer. This is proposed to satisfy JMS_SPEC-51 and is further modified here:

     /** Creates a durable subscription with the specified name on the
      * specified topic, and creates a <code>MessageConsumer</code>
      * on that durable subscription, specifying a message
      * selector and whether messages published by its
      * own connection should be added to the durable subscription.

      . . .

     * <P>The <code>NoLocal</code> argument is for use when the session's
     * connection is also being used to publish messages to the topic.
     * If <code>NoLocal</code> is set to true then messages published
     * to the topic by its own connection will not be added to the
     * durable subscription. The default value of this
     * argument is false.
      . . .

      * @param noLocal if true, messages published by its own connection
      * will not be added to the durable subscription.

In addition, I've updated all the relevant methods on the JMSContext interface proposed in http://java.net/jira/browse/JMS_SPEC64:

Updated javadoc comment for JMSContext.createConsumer(destination, messageSelector, NoLocal), which returns a JMSConsumer. This is proposed to satisfy JMS_SPEC-64 and is further modified here.

/**
 * Creates a <CODE>JMSConsumer</CODE> for the specified destination, using
 * a message selector. This method can specify whether messages published by
 * its own connection should be delivered to it, if the destination is a
 * topic.

 . . .

 * The <code>noLocal</code> argument is for use when the
 * destination is a topic and the JMSContext's connection
 * is also being used to publish messages to that topic.
 * If <code>noLocal</code> is set to true then the
 * <code>JMSConsumer</code> will not receive messages published
 * to the topic by its own connection. The default value of this
 * argument is false. If the destination is a queue
 * then the effect of setting <code>noLocal</code>
 * to true is not specified.
  
 . . .

 * @param noLocal  if true, and the destination is a topic,
 *                 then the <code>JMSConsumer</code> will
 *                 not receive messages published to the topic
 *                 by its own connection
 * 

Updated javadoc comment for JMSContext.createDurableConsumer(topic, name, messageSelector, noLocal), which returns a JMSConsumer.

/** Creates a durable subscription with the specified name on the
 * specified topic, and creates a <code>JMSConsumer</code> 
 * on that durable subscription, specifying a message selector and 
 * whether messages published by its own connection should be added to 
 * the durable subscription.  

   . . .

 * The <code>noLocal</code> argument is for use when the JMSContext's 
 * connection is also being used to publish messages to the topic. 
 * If <code>noLocal</code> is set to true then messages published
 * to the topic by its own connection will not be added to the
 * durable subscription. The default value of this 
 * argument is false. 

   . . .

 * @param noLocal if true, messages published by its own connection
 * will not be added to the durable subscription.

Updated 15 May 2012 to reflect the rename of MessagingContext to JMSContext and other changes to that interface.

Comment by Nigel Deakin [ 15/May/12 ]

This issue was discussed and agreed some time ago before the early draft, but I'd like to re-open it for discussion of a possible clarification.

You will remember that this issue is about the purpose of the noLocal parameter when creating a durable subscription.

The JMS 1.1 javadocs simply states that this flag "inhibits the delivery of messages published by its own connection".
(http://docs.oracle.com/javaee/6/api/javax/jms/Session.html#createDurableSubscriber%28javax.jms.Topic,%20java.lang.String,%20java.lang.String,%20boolean%29)

For JMS 2.0 we have already agreed to clarify this to state that if this flag is set "messages published by its own connection will not be added to the durable subscription."
(See comments above or at http://java.net/jira/browse/JMS_SPEC-65#action_328549)

However it has been pointed out to me that further clarification may be needed.

Let's review this in stages.

Case 1

Consider the simplest case. A client creates a connection and calls createDurableSubscriber with noLocal=true. This returns a TopicSubscriber. It then uses the same connection to create a MessageProducer and uses it to send a message to the topic. The client then uses the TopicSubscriber to try to receive the message.

String clientID = "foo";
String subscriptionName = "bar";
boolean noLocal=true;
String messageSelector=null;
ConnectionFactory connectionFactory = ... // lookup connection factory
Topic topic = ...                         // lookup topic
Connection connection = connectionFactory.createConnection();
connection.setClientID(clientID);
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber = session.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
MessageProducer messageProducer = session.createProducer(topic);
messageProducer.send(session.createTextMessage("Hello"));
			
connection.start();
Message message = subscriber.receive(1000));
// is a message received or not?
connection.close();

What happens? JMS 1.1 states that the noLocal flag "inhibits the delivery of messages published by its own connection". We're using the same connection to send and receive messages, so clearly no message is received.

Case 2

After the previous case is run, the client now creates a second connection with the same clientID as before and calls createDurableSubscriber with identical arguments as before. This returns a second TopicSubscriber. The client then uses the second TopicSubscriber to try to receive the message.

Here's the complete case:

String clientID = "foo";
String subscriptionName = "bar";
boolean noLocal=true;
String messageSelector=null;
ConnectionFactory connectionFactory = ... // lookup connection factory
Topic topic = ...                         // lookup topic

// Step 1
Connection connection = connectionFactory.createConnection();
connection.setClientID(clientID);
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber = session.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
MessageProducer messageProducer = session.createProducer(topic);
messageProducer.send(session.createTextMessage("Hello"));
			
connection.start();
Message message = subscriber.receive(1000));
// message is null
connection.close();


// Step 2
Connection connection2 = connectionFactory.createConnection();
connection2.setClientID(clientID);
Session session2 = connection2.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber2 = session2.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
connection2.start();
Message message2 = subscriber2.receive(1000));
// is a message received or not?
connection2.close();

What happens? JMS 1.1 simply states that the noLocal flag "inhibits the delivery of messages published by its own connection". But in this case the message was published by a different connection. Should it be delivered?

However we've already taken the decision in JMS 2.0 to clarify the effect of the noLocal flag to state that "messages published by its own connection will not be added to the durable subscription." In this case, the message was published using the same connection as was used to create the durable subscription. So in accordance with this new wording, the message is not added to the durable subscription and so will never be delivered, even to a subsequent consumer that uses a different connection.

Case 3

So far so good. But now let's consider a third case: what if this second connection is also used to send a second message to the topic? Is it added to the durable subscription or not?

Here's the complete case:

String clientID = "foo";
String subscriptionName = "bar";
boolean noLocal=true;
String messageSelector=null;
ConnectionFactory connectionFactory = ... // lookup connection factory
Topic topic = ...                        // lookup topic

// Step 1
Connection connection = connectionFactory.createConnection();
connection.setClientID(clientID);
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber = session.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
MessageProducer messageProducer = session.createProducer(topic);
messageProducer.send(session.createTextMessage("Hello"));
			
connection.start();
Message message = subscriber.receive(1000));
// message is null
connection.close();


// Step 2
Connection connection2 = connectionFactory.createConnection();
connection2.setClientID(clientID);
Session session2 = connection2.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber2 = session2.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
connection2.start();
Message message2 = subscriber2.receive(1000));
// message is null

MessageProducer messageProducer2 = session2.createProducer(session2.createTopic(topicName));
messageProducer2.send(session2.createTextMessage("Hello"));

connection2.close();

// Step 3
Connection connection3 = connectionFactory.createConnection();
connection3.setClientID(clientID);
Session session3 = connection3.createSession(false,Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber3 = session3.createDurableSubscriber(topic, subscriptionName, messageSelector, noLocal);
			
connection3.start();
Message message3 = subscriber3.receive(1000));
// is a message received or not?
connection3.close();

The message sent using the first connection was not added to the durable subscription. Similarly, I think that the message sent using the second connection should not be added to the durable subscription. Anything else would be inconsistent and not very useful.

Just to reiterate this: the effect of setting noLocal shouldn't be restricted to messages sent using the very first connection, the one used to create the durable subscription. It should apply throughout the life of the durable subscription.

However this leads to one further question. In case 3, step 2 above, does it matter whether the producer was created, and the message sent, before or after the durable subscription was activated? At what point does connection2 become "tainted" and unable to send messages to the durable subscription?

I think the simplest answer to that is to say that it doesn't matter at what point connection2 activates the durable subscription. It has the same clientID as was associated with the durable subscription, and so any messages it sends to the topic will never be added to the durable subscription. This is the only definition of noLocal which gives consistent behaviour throughout the life of the subscription.

However for JMS 2.0 we have made clientID optional when creating a durable subscription. This means we need to define what noLocal means when clientID is not set. The simplest approach would be to define that setting noLocal on a durable subscription has no effect unless clientID is set.

In summary

In summary, it is proposed to further clarify the meaning of the noLocal parameter in the method Session.createDurableConsumer as follows:

/** Creates a durable subscription with the specified name on the
 * specified topic, and creates a <code>MessageConsumer</code>
 * on that durable subscription, specifying a message
 * selector and the noLocal argument.

   . . .

 * <P>If <code>noLocal</code> is set to true, 
 * and the client identifier is set, then any messages published 
 * using this connection or any other with the same client identifier 
 * will not be added to the durable subscription. 
 * If the client identifier is unset then 
 * setting <code>noLocal</code> to true has no effect.
 * The default value of <code>noLocal</code> is false.


   . . .

 * @param noLocal if true, and the client identifier is set, 
 * then any messages published using this connection 
 * or any other with the same client identifier 
 * will not be added to the durable subscription. 

Similar changes will be made to Session.createDurableSubscriber and JMSContext.createDurableConsumer, and to the JMS specification itself.

Comment by Nigel Deakin [ 30/May/12 ]

I've now updated the draft spec and javadocs in accordance with the changes proposed in the previous comment.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

Section 6.11.1 "Durable TopicSubscriber" has been reworded to define the effect of setting noLocal as follows:

When a durable subscription is created on a topic, the noLocal argument may be used to specify that messages published to the topic by its own connection or any other with the same client identifier will not be added to the durable subscription. If the client identifier is unset then setting noLocal to true has no effect.

In addition, the effect of supplying a different value of noLocal when creating a consumer on an existing durable subscription has been clarified as follows:

If there are no active consumers on the durable subscription (and no consumed messages from that subscription are still part of a pending transaction or are not yet acknowledged in the session), and this method is used to create a new consumer on that durable subscription, specifying the same name and client identifier (if set) but a different topic or message selector, or, if the client identifier is set, a different noLocal argument, then the durable subscription will be deleted and a new one created.

However if there is an active consumer on the durable subscription (or a consumed message from that subscription is still part of a pending transaction or is not yet acknowledged in the session), and an attempt is made to create an additional consumer, specifying the same name and client identifier (if set) but a different topic or message selector, or, if the client identifier is set, a different noLocal argument, then a JMSException or JMSRuntimeException will be thrown.

Note that changing noLocal only has an effect if the client identifier is set.

These changes are also listed in the change log, section B.5.16.

The updated Javadocs can be downloaded here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar
or browsed online here:
http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/index.html

I've clarified the javadocs for all the existing methods on Session and JMSContext that create durable subscribers. The methods affected are the Session methods createDurableSubscriber and createDurableConsumer and the JMSContext methods createDurableConsumer. These all now have javadoc comments similar to the following example:

* Creates a durable subscription with the specified name on the specified
* topic (if one does not already exist), specifying a message selector and
* the <code>noLocal</code> parameter, and creates a
* <code>TopicSubscriber</code> on that durable subscription.


* If there are no active consumers on the durable subscription (and no
* consumed messages from that subscription are still part of a pending
* transaction or are not yet acknowledged in the session), and this method
* is used to create a new consumer on that durable subscription, specifying
* the same name and client identifier (if set) but a different topic or
* message selector, or, if the client identifier is set, a different
* noLocal argument, then the durable subscription will be deleted and a new
* one created. 
*
* However if there is an active consumer on the durable
* subscription (or a consumed message from that subscription is still part
* of a pending transaction or is not yet acknowledged in the session), and
* an attempt is made to create an additional consumer, specifying the same
* name and client identifier (if set) but a different topic or message
* selector, or, if the client identifier is set, a different noLocal
* argument, then a <code>JMSException</code> will be thrown.
*
* If <code>noLocal</code> is set to true, and the client identifier is set,
* then any messages published to the topic using this session's connection,
* or any other connection or <code>JMSContext</code> with the same client
* identifier, will not be added to the durable subscription. If the client
* identifier is unset then setting <code>noLocal</code> to true has no
* effect. The default value of <code>noLocal</code> is false.

. . .

* @param noLocal
*            if true, and the client identifier is set, then any messages
*            published to the topic using this session's connection, or any
*            other connection or <code>JMSContext</code> with the same
*            client identifier, will not be added to the durable
*            subscription.
Comment by Nigel Deakin [ 13/Sep/12 ]

I've added a further change:

If the client identifier is unset then setting noLocal to true will cause an IllegalStateException or IllegalStateRuntimeException (depending on the method signature) to be thrown.

Comment by clebertsuconic [ 13/Sep/12 ]

I agree.. clientID is non set, calling createDurableSubscription with noLocal=true should throw an exception, otherwise there's no way to replay durable subscriptions.

However.... if you set clientID==null on a non-durable subscription, it would be possible to filter out with some sort of UUID at the implementation. However the usage semantics would get complicated.. so I would vote to just keep it simple.. i.e.:

clientID==null && noLocal==true => throw SomeException

Comment by chris.barrow [ 13/Sep/12 ]

Are you suggesting the createConsumer method should follow the same logic? I would have to urge against that because clientID has nothing whatsoever to do with non-durables, so it would be confusing to suddenly relate the two. Moreover it would be an incompatible change from 1.1 (which currently allows createConsumer with noLocal=true whether or not there is a clientID set on the connection).

Comment by Nigel Deakin [ 13/Sep/12 ]

This change (and this whole issue) concerns durable subscriptions only, and was intended to clarify what the existing JMS 1.1 behaviour should be.

The definition of noLocal for non-durable, non-shared subscriptions is unchanged from JMS 1.1. In that case client identifier may be either set or unset when noLocal is true. If a message is sent by the same Connection object which created the subscription then the message will not be added to the subscription. No need to rely on UUID, since when the connection that created the subscription is closed, the subscription will be deleted.

The introduction of shared durable and non-durable subscriptions in JMS 2.0 does introduce the issue of what noLocal means in that case. I will raise this as part of issue JMS_SPEC-40 which covers shared durable and non-durable subscriptions.

Comment by clebertsuconic [ 13/Sep/12 ]

My bad .. this is is certainly only about durable subscription

I'm happy with what you propose then.. but as I told you in a private email I prefer some exception as opposed to just ignore it.

Comment by chris.barrow [ 13/Sep/12 ]

Sorry to eat my words here, but in light of the discussion about non-durables I would now recommend changing the behavior for createDurableSubscription with noLocal=true to make it independent of clientID and consistent with non-durable shared consumers. See my recent comment in JMS_SPEC_40.

Comment by clebertsuconic [ 13/Sep/12 ]

@chriss: you need some sort of client-id to replay the queues and do the correct association.

Most implementations I know will use an internal filter on the queue with message.originatingID != currentID.

how would you replay the queue on these circunstances? what about previous sent messages?

Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-54] Define a standard way to configure the destination on which a JMS MDB consumes messages Created: 21/Oct/11  Updated: 20/Mar/13  Resolved: 07/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on CONNECTOR_SPEC-4 Clarify whether the ResourceAdapter.e... Resolved
blocks MQ-250 Implement JMSRA activation properties... Closed
Related
is related to JMS_SPEC-30 Define mandatory activation config pr... Resolved
is related to JMS_SPEC-55 Define a standard way to configure th... Resolved
Tags: eg, jms20-jsr345, pd20-added

 Description   

This is a request for the JMS and/or EJB specifications to improve the way in which specify how an application or deployer may specify the destination from which a JMS message-driven bean to receive messages. There are several significant omissions from the specification which need to be rectified.

Although MDBs are specified in the EJB specification, this request should be considered first by the JMS 2.0 expert group who may then want to raise it with the EJB 3.2 expert group.

Review of existing specification (EJB 3.1)

In the EJB 3.1 specification, Section 16.9 "Message Destination References" states that the destination used by a JMS message-driven bean can be specified using the <message-destination-link> element of the <message-driven> element in ejb-jar.xml:

<message-driven>
   <ejb-name>ExpenseProcessing</ejb-name>
   <ejb-class>com.wombat.empl.ExpenseProcessingBean</ejb-class>
   <messaging-type>javax.jms.MessageListener</messaging-type>
   ...
   <message-destination-type>javax.jms.Queue</message-destination-type>
   <message-destination-link>ExpenseProcessingQueue</message-destination-link>
   ...
</message-driven>

Issues with the existing specification

This raises the following questions:

1. What is <message-destination-link>?

The <message-destination-link> element defines the destination from which the MDB consumes messages in terms of a "message destination reference".

The purpose of "message destination references" is to allow an application which sends messages to a particular destination and also consumes from the same destination to inform the deployer of this fact without having to actually specify the name (or JNDI name) of the destination.

As stated above, a MDB can specify the "message destination reference" of the destination from which it consumes messages using a <message-destination-link> element under the <message-driven> element. Another component (e.g. a session bean or another MDB) can specify the destination to which it sends messages using a <message-destination-link> element under a <message-destination-ref> element. If these two elements contain the same string then the deployer knows they refer to the same queue or topic.

A message destination reference is not the JNDI name of the queue or topic. It is just a logical name. It can be mapped to an actual JNDI name using the <assembly-descriptor> element in ejb-jar.xml as follows:

Here's how ejb-jar.xml could be used to define a MDB as consuming messages from a "message destination reference" called MsgBeanInQueue which was mapped to a JNDI name jms/inboundQueue:

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <display-name>MDB1</display-name>
      <ejb-name>MessageBean</ejb-name>
      <messaging-type>javax.jms.MessageListener</messaging-type>
      <transaction-type>Container</transaction-type>
      <message-destination-type>javax.jms.Queue</message-destination-type>
      <message-destination-link>MsgBeanInQueue</message-destination-link>
    </message-driven>
  </enterprise-beans>
  <assembly-descriptor>
    <message-destination>
      <lookup-name>jms/inboundQueue</lookup-name>   <!---
      <message-destination-name>MsgBeanInQueue</message-destination-name>
    </message-destination>
  </assembly-descriptor>
</ejb-jar> 

A message destination reference can typically also be mapped to an actual JNDI name using the application-server-specific deployment descriptor, though by definition this is beyond the scope of the EJB specification.

2. Is that the only way you can define the destination on which a MDB consumes messages in ejb-jar.xml? Can you define its JNDI name directly without bothering with references?

No, the EJB specification doesn't mention any way to define the destination in ejb-jar.xml apart from using the <message-destination-link> element of ejb-jar.xml. In particular it doesn't define any way to define its JNDI name directly, analogous to using either the JNDI API or a @Resource(lookup="jms/foo") declaration for managed connections.

3. Can I define the message destination reference for a MDB using annotation?

No, there is equivalent to <message-destination-link> using annotation.

4. Can I define the JNDI name of the destination on which a MDB consumes messages directly using annotation?

No, there is no way to define this using annotation, analogous to using a @Resource(lookup="jms/foo") declaration when using the JMS API directly.

So, what seems to be missing?

A. As explained in (2) and (4) above, there isn't a standard way for MDB applications to short-circuit the use of message destination references and define the JNDI name of the destination from which a JMS message-driven bean consumes messages, either using ejb-jar.xml or annotations. This contrasts with EJBs which send messages, where the JNDI name of the destination can be specified in the MDB code using the JNDI API or a @Resource(lookup="jms/foo") declaration.

B. As explained in (3) above, there is no standard way for the application to define using annotation the "message destination reference" on which the JMS message-driven bean is consuming messages.

Proposals:

A. It is proposed that the <message-driven> element in ejb-jar.xml be extended to define an additional sub-element which can be used to specify the JNDI name of the destination from which a JMS message-driven mean consumes messages. A suggested element name is <message-destination-jndi-name>:

<ejb-jar>
  <display-name>Ejb1</display-name>
  <enterprise-beans>
    <message-driven>
      <display-name>MDB1</display-name>
      <ejb-name>MessageBean</ejb-name>
      <message-destination-type>javax.jms.Queue</message-destination-type>
      <message-destination-jndi-name>jms/inboundQueue<message-destination-jndi-name>
      ...

It might be asked why this needs to be defined by a new subelement of <message-driven> rather than, say, a new standard activation configuration property. The answer is that the way that the JNDI name is defined needs to be consistent with the way that the message destination reference is defined, which is by the <message-destination-link> subelement of <message-driven>

B. It is proposed that the equivalent annotation be a new attribute of the @MessageDriven annotation, called messageDestinationJndiName. For example:

@MessageDriven(messageDestinationJndiName="jms/inboundQueue")
public class MyMDB implements MessageListener {
....

C. It is proposed that the @MessageDriven annotation be extended to allow applications to define the "message destination reference" on which the JMS message-driven bean is consuming messages, using a new attribute messageDestinationLink"

@MessageDriven(messageDestinationLink="ExpenseProcessingQueue")
public class MyMDB implements MessageListener {
....


 Comments   
Comment by rdohna [ 25/Oct/11 ]

Linked these two issues

Comment by Nigel Deakin [ 25/Oct/11 ]

Corrected names of annotation attributes

Comment by Nigel Deakin [ 07/Nov/11 ]

Added tag jsr345 to identify that this issue requires changes to the EJB spec, not the JMS spec

Comment by Nigel Deakin [ 05/Dec/12 ]

The current proposal is to define a standard activation property destinationLookup.

However this is only possible if the connector spec can guarantee that the resource adapter will be able to perform the lookup in the endpointActivation call. I have logged CONNECTOR_SPEC-4 to request clarification .

Comment by Nigel Deakin [ 07/Feb/13 ]

Note that CONNECTOR_SPEC-4 is now resolved.

Comment by Nigel Deakin [ 07/Feb/13 ]

The JMS 2.0 and EJB 3.2 specifications now define a activation property destinationLookup. This is defined as follows (JMS 2.0 section 13.1 "MDB activation properties"):

Activation property Description
destinationLookup This property may be used to specify the lookup name of an administratively-defined javax.jms.Queue or javax.jms.Topic object which defines the JMS queue or topic from which the endpoint (message-driven bean) is to receive messages.

This issue can now be marked as resolved.





[JMS_SPEC-62] Define standard way to create JMS Destination objects from within a Java EE application Created: 23/Nov/11  Updated: 24/Feb/12  Resolved: 24/Feb/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: arjan tijms Assignee: Unassigned
Resolution: Invalid Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: destination, javaee

 Description   

The JMS 1.1 spec states in section 2.3 that JMS Destinations (Queue and Topic) are administered objects for the following reason:

It is also expected there will be major differences in how a provider's system is installed and administered. If JMS clients are to be portable, they must be isolated from these proprietary aspects of a provider.

In practice however, there is often only very little information needed to create a basic Destination that is suitable for a lot of use-cases and there aren't really any major differences there. Especially if such Destinations are completely used internally in the application, they don't necessarily need to be administered objects. Many Java EE servers do make it possible to define Destinations from within the application, but every implementation has a different way to do this. This hurts portability.

For instance;

JBoss AS 6.x

*-hornetq-jms.xml
<configuration xmlns="urn:hornetq"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"
>    
    <queue name="myQueue">
        <entry name="/queue/myQueue" />
    </queue>
</configuration>

Glassfish 3.1.x

META-INF/glassfish-resources.xml
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" 
    "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
    <admin-object-resource res-adapter="jmsra" res-type="javax.jms.Queue" jndi-name="java:app/myQueue" >        
        <property name="Name" value="myQueue"/>
    </admin-object-resource>
</resources>

As can be seen in these two examples, all that the user needs to declare is a name and whether a queue or topic is required.

I would like to propose to define a standard way to define Destinations from within a Java EE application, analogous to how JDBC datasources can be defined via a DataSourceDefinition annotation and a corresponding <data-source> element in application.xml.



 Comments   
Comment by arjan tijms [ 04/Dec/11 ]

Slide 29 of http://java.net/downloads/jms-spec/JMS2.0Devoxx2011.pdf mentions exactly this:

JSR 342 (Java EE 7) will define new annotations:

@JMSConnectionFactoryDefinition( 
    name="java:app/MyJMSFactory", 
    resourceType="javax.jms.QueueConnectionFactory", 
    clientId="foo",
    resourceAdapter="jmsra", 
    initialPoolSize=5, 
    maxPoolSize=15
)
@JMSDestinationDefinition( 
    name="java:app/orderQueue", 
    resourceType="javax.jms.Queue", 
    resourceAdapter="jmsra", 
    destinationName="orderQueue"
)
Comment by Nigel Deakin [ 08/Dec/11 ]

As mentioned in those Devoxx slides, the Java EE 7 platform expert group is planning to include a feature similar to this. Please contact the Java EE 7 expert group for more information. http://javaee-spec.java.net

This is a platform issue and won't be addressed in the JMS spec.

Comment by Nigel Deakin [ 24/Feb/12 ]

Please see section EE.5.17.5 "JMS Destination Definition" of the proposed Java EE 7 specification (available via http://javaee-spec.java.net). This states

An application may define a JMS Destination resource. A JMS Destination resource is a JMS Queue or Topic.

The JMS {{Destination}}resource may be defined in any of the JNDI namespaces described in Section EE.5.2.2, “Application Component Environment Namespaces”.

A JMS Destination resource may be defined in a web module, EJB module, application client module, or application deployment descriptor using the jms-destination element.

For example:

<jms-destination>
    <description>Sample JMS Destination definition</description>
    <name>java:app/MyJMSDestination</name>
    <class-name>javax.jms.Queue</class-name>
    <resource-adapter-name>myJMSRA</resource-adapter-name>
    <resource-name>myQueue1</resource-name>
    <property>
      <name>Property1</name>
      <value>10</value>
    </property>
    <property>
      <name>Property2</name>
      <value>20</value>
    </property>
    </jms-destination>

A JMS Destination resource may also be defined using the JMSDestinationDefinition annotation on a container-managed class, such as a servlet or enterprise bean class.

For example:

@JMSDestinationDefinition(
    name="java:app/MyJMSQueue",
    className="javax.jms.Queue",
    resourceName="myQueue1")

The JMSDestinationDefinition annotation can be overridden by a deployment descriptor when the application is deployed.)

Once defined, a JMS Destination resource may be referenced by a component using the resource-ref deployment descriptor element or the Resource annotation. For example, the above Destination could be referenced as follows:

@Stateless
public class MySessionBean {
    @Resource(lookup = "java:app/MyJMSQueue")
    Queue myQueue;
    ...
}

The following JMSDestinationDefinition annotation elements (and corresponding XML deployment descriptor elements) are considered to specify an address for a JMS Destination resource: resourceAdapterName, resourceName.

Comment by Nigel Deakin [ 24/Feb/12 ]

I've marked this as resolved, with a resolution of "invalid". This doesn't mean the suggestion was invalid, of course, but that the request applied to a different specification. Comments and feedback remain welcome.





[JMS_SPEC-52] Clarify that a message may be sent using a different session from that used to create the message Created: 21/Sep/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-170 Implement clarified behaviour of meth... Open
Tags: ed20-added

 Description   

The JMS 1.1 API defines how a JMS message object is created using one of the following methods on a Session:

Message 	createMessage() 
BytesMessage 	createBytesMessage() 
MapMessage 	createMapMessage() 
ObjectMessage 	createObjectMessage() 
ObjectMessage 	createObjectMessage(java.io.Serializable object) 
StreamMessage 	createStreamMessage() 
TextMessage 	createTextMessage() 
TextMessage 	createTextMessage(java.lang.String text) 

The following question has been raised:

Can a message be sent using a MessageProducer that was created from a different Session than was used to create the message?

This is not stated explicitly in the specification, and discussions within the JSR 343 Expert group show that different individuals have come to different conclusions on this issue.

My own interpretation is that a MessageProducer must be able to send a javax.JMS.Message irrespective of how it was created. It might have been created using Session.createMessage(), or it may have been received by a MessageConsumer.

Section 4.4.5 "Optimized message implementations" of the JMS 1.1 specification states:

A session provides message create methods that use provider-optimized implementations. This allows a provider to minimize its overhead for handling messages.
Sessions must be capable of sending all JMS messages regardless of how they may be implemented.

Furthermore, Section 3.12 of the JMS 1.1 specification states explicitly that a MessageProducer must be able to send a message that was created using a different JMS provider, and which would therefore have used a different session:

A provider must be prepared to accept, from a client, a message whose implementation is not one of its own. A message with a 'foreign' implementation may not be handled as efficiently as a provider's own implementation; however, it must be handled.

Despite this, there is a widespread view within the JMS community that for messages created within the same JVM by the same JMS provider, the session used to create the message must be the same as that used to send it.

It is therefore proposed that the JMS specification be clarified that there is no such restriction, and that a MessageProducer can be used to send any message object

  • irrespective of which session or connection was used to create it,
  • irrespective of whether the message was created within this JVM or received from a JMS destination, and
  • irrespective of whether the MessageProducer and message are implemented by the same or different JMS providers.


 Comments   
Comment by Nigel Deakin [ 22/Sep/11 ]

Edited description to clarify that a MessageProducer can be used to send any message object
irrespective of what connection (as well as session) was used to create it.

Comment by Nigel Deakin [ 19/Dec/11 ]

I've now updated the javadocs and the draft spec to clarify this issue (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The six message-creation methods on Session have been modified to include the following additional javadoc comments:

* The message object returned may be sent using any session or messaging context. 
* It is not restricted to being sent using the session used to create it.
* <p>
* The message object returned may be optimised for use with the JMS provider
* used to create it. However it can be sent using any JMS provider, not just the 
* JMS provider used to create it.

The second sentence above has been included because it would be confusing and inconsistent to mention that a message may be sent using a different session and not also mention the even more significant fact that a message may be sent using a different JMS provider.

The six message-creation methods on the proposed new MessagingContext interface have been modified to include the following additional javadoc comments:

* The message object returned may be sent using any session or messaging context. 
* It is not restricted to being sent using the messaging context used to create it.
* <p>
* The message object returned may be optimised for use with the JMS provider
* used to create it. However it can be sent using any JMS provider, not just the 
* JMS provider used to create it.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
All changes are highlighted clearly with changebars. The changes for this issue are as follows:

Section 4.4.5. "Optimized Message Implementations" has been updated to state:

A session provides the following methods to create messages: createMessage, createBytesMessage, createMapMessage, createObjectMessage, createStreamMessage and createTextMessage.

These methods allow the JMS provider to create message implementations which are optimized for that particular provider and allow the provider to minimize its overhead for handling messages.

A session provides message create methods that use provider-optimized implementations. This allows a provider to minimize its overhead for handling messagesHowever .the fact that these methods are provided on a session does not mean that messages must be sent using a message producer created from the same session. Messages may be sent using any session, not just the session used to create the message.

Furthermore, Sessions must be capable of sending all JMS messages regardless of how they may be implemented. See section 3.12 "Provider Implementations of JMS Message Interfaces".

Section 11.5.5 "Clarification: message may be sent using any session" is the change log for this clarification.





[JMS_SPEC-51] New methods to replace Session.createDurableSubscriber() and return a MessageConsumer Created: 16/Sep/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-171 New methods to replace Session.create... Closed
Tags: ed20-added

 Description   

In JMS 1.1 the following two methods on Session return a TopicSubscriber.

TopicSubscriber createDurableSubscriber(Topic topic)

TopicSubscriber createDurableSubscriber(Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal)

These are the only "domain-independent" methods in the whole JMS 1.1 API which depend on a "domain-specific" interface. This dependency prevents the "domain-specific" interfaces being removed from JMS as proposed in JMS_SPEC-47.

It is therefore proposed to modify these methods to return a MessageConsumer. Since this is a supertype of TopicSubscriber it should not break existing applications.



 Comments   
Comment by Nigel Deakin [ 20/Sep/11 ]

It has been pointed out that the above proposal would require existing applications would need to cast the MessageConsumer that is returned down to a TopicSubscriber.

This suggests that we need to provide new versions of this method which return a MessageConsumer. This would allow us to mark the old methods as deprecated and propose them for removal.

We can't simply add new methods with the same name which return a MessageConsumer since the compiler would consider these duplicate methods.

Two options have been proposed:

Option 1

We could define new methods named createConsumer:

MessageConsumer createConsumer(Topic topic, java.lang.String name)

MessageConsumer createConsumer(Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal)

However there's potential confusion between the first of those methods and the existing method to create an ordinary consumer with a message selector:

MessageConsumer createConsumer(Destination destination, java.lang.String messageSelector)

The compiler would allow it, but if the user tried to create a durable subscription using a variable which was really a Topic but which was declared as Destination then the wrong method would be called.

It could also be argued that removing the word "durable" from the method name would be confusing for users.

We could either live with these drawbacks, or we could use:

Option 2

We could define new methods named createDurableConsumer:

MessageConsumer createDurableConsumer(Topic topic, java.lang.String name)

MessageConsumer createDurableConsumer(Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal)

Comment by Nigel Deakin [ 03/Jan/12 ]

Following a discussion within the JSR 343 expert group I've selected option 2 above.

I've now updated the javadocs and the draft spec accordingly (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar
(Two createDurableConsumer methods have been added to Session. See below for javadocs).

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(all changes are highlighted clearly with changebars, but the only place I've changed is 6.11.1 "Durable TopicSubscriber" and 11.5.9 "createDurableConsumer" which is the change log).

Here are the two new methods:

    /** Creates a durable subscription with the specified name on the
      * specified topic, and creates a <code>MessageConsumer</code> 
      * on that durable subscription.
      * <P>
      * If the durable subscription already exists then this method
      * creates a <code>MessageConsumer</code> on the existing durable
      * subscription.
      * <p>
      * A durable subscription is used by a client which needs to receive
      * all the messages published on a topic, including the ones published 
      * when there is no <code>MessageConsumer</code> or <code>TopicSubscriber</code> associated with it. 
      * The JMS provider retains a record of this durable subscription 
      * and ensures that all messages from the topic's publishers are retained 
      * until they are delivered to, and acknowledged by,
      * a <code>MessageConsumer</code> or <code>TopicSubscriber</code> on this durable subscription
      * or until they have expired.
      * <p>
      * A durable subscription will continue to accumulate messages 
      * until it is deleted using the <code>unsubscribe</code> method. 
      * <p>
      * A durable subscription which has a <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * associated with it is described as being active. 
      * A durable subscription which has no <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * associated with it is described as being inactive. 
      * <p>
      * Only one session at a time can have a
      * <code>MessageConsumer</code> or <code>TopicSubscriber</code> for a particular durable subscription.
      * <p>
      * A durable subscription is identified by a name specified by the client
      * and by the client identifier if set. If the client identifier was set
      * when the durable subscription was first created then a client which 
      * subsequently wishes to create a <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * on that durable subscription must use the same client identifier.
      * <p>
      * A client can change an existing durable subscription by calling
      * <code>createDurableConsumer</code> 
      * with the same name and client identifier (if used),
      * and a new topic and/or message selector. 
      * Changing a durable subscriber is equivalent to 
      * unsubscribing (deleting) the old one and creating a new one.
      *
      * @param topic the non-temporary <CODE>Topic</CODE> to subscribe to
      * @param name the name used to identify this subscription
      *  
      * @exception JMSException if the session fails to create the durable subscription 
      *            and <code>MessageConsumer</code> due to some internal error.
      * @exception InvalidDestinationException if an invalid topic is specified.
      *
      * @since 2.0
      */ 
     MessageConsumer createDurableConsumer(Topic topic, String name) throws JMSException;
     /** Creates a durable subscription with the specified name on the
      * specified topic, and creates a <code>MessageConsumer</code> 
      * on that durable subscription, specifying a message 
      * selector and whether messages published by its
      * own connection should be delivered to it.
      * <P>
      * If the durable subscription already exists then this method
      * creates a <code>MessageConsumer</code> on the existing durable
      * subscription.
      * <p>
      * A durable subscription is used by a client which needs to receive
      * all the messages published on a topic, including the ones published 
      * when there is no <code>MessageConsumer</code> or <code>TopicSubscriber</code> associated with it. 
      * The JMS provider retains a record of this durable subscription 
      * and ensures that all messages from the topic's publishers are retained 
      * until they are delivered to, and acknowledged by,
      * a <code>MessageConsumer</code> or <code>TopicSubscriber</code> on this durable subscription
      * or until they have expired.
      * <p>
      * A durable subscription will continue to accumulate messages 
      * until it is deleted using the <code>unsubscribe</code> method. 
      * <p>
      * A durable subscription which has a <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * associated with it is described as being active. 
      * A durable subscription which has no <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * associated with it is described as being inactive. 
      * <p>
      * Only one session at a time can have a
      * <code>MessageConsumer</code> or <code>TopicSubscriber</code> for a particular durable subscription.
      * <p>
      * A durable subscription is identified by a name specified by the client
      * and by the client identifier if set. If the client identifier was set
      * when the durable subscription was first created then a client which 
      * subsequently wishes to create a <code>MessageConsumer</code> or <code>TopicSubscriber</code>
      * on that durable subscription must use the same client identifier.
      * <p>
      * A client can change an existing durable subscription by calling
      * <code>createDurableConsumer</code> 
      * with the same name and client identifier (if used),
      * and a new topic and/or message selector. 
      * Changing a durable subscriber is equivalent to 
      * unsubscribing (deleting) the old one and creating a new one.
      *
      * @param topic the non-temporary <CODE>Topic</CODE> to subscribe to
      * @param name the name used to identify this subscription
      * @param messageSelector only messages with properties matching the
      * message selector expression are delivered.  A value of null or
      * an empty string indicates that there is no message selector 
      * for the message consumer.
      * @param noLocal if set, inhibits the delivery of messages published
      * by its own connection
      *  
      * @exception JMSException if the session fails to create the durable subscription 
      *                         and <code>MessageConsumer</code> due to some internal error.
      * @exception InvalidDestinationException if an invalid topic is specified.
      * @exception InvalidSelectorException if the message selector is invalid.
      *
      * @since 2.0
      */ 
      MessageConsumer createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal) throws JMSException;   
Comment by Nigel Deakin [ 03/Jan/12 ]

I've changed the summary line for this issue from
Change Session.createDurableSubscriber() to return a MessageConsumer
to
New methods to replace Session.createDurableSubscriber() and return a MessageConsumer.

This reflects the decision not to change the existing methods (to preserve backwards compatibility) but to add new methods.





[JMS_SPEC-63] Introduce concept of platform default JMS connection factory in Java EE Created: 04/Dec/11  Updated: 20/Mar/13  Resolved: 23/Aug/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0

Type: Improvement Priority: Major
Reporter: arjan tijms Assignee: Unassigned
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on JAVAEE_SPEC-2 Define platform default JMS connectio... Resolved
Tags: jms20-jsr342-added

 Description   

In a Java EE environment a JMS provider is mandatory present and can be used without the user having to configure or setup anything.

Some implementations (e.g. JBoss AS), provide by default a JMS connection factory for this platform provided JMS provider (java:/ConnectionFactory and java:JmsXA), yet in other implementations (e.g. GlassFish) users have to create a connection factory themselves.

I would like to propose to formally introduce the concept of a platform default JMS connection factory and make this available under some portable JNDI name (e.g. java:/JmsConnectionFactory). The exact configuration of this factory should be an implementation detail, but the spirit of the specification should be that it must not be purposely crippled and should be principally intended for production use.

Besides shielding users from having to create a connection factory, an additional benefit might be that other platform JMS facilities that otherwise would need an explicit reference to a connection factory, could default to this standard connection factory.

E.g. from http://java.net/downloads/jms-spec/JMS2.0Devoxx2011.pdf slide 23:

@Inject 
@JMSConnection(lookup="jms/connFactory") 
@JMSDestination(lookup="jms/inboundQueue") 
MessageProducer producer;

could become:

@Inject 
@JMSDestination(lookup="jms/inboundQueue") 
MessageProducer producer; // defaults to java:/JmsConnectionFactory

etc.



 Comments   
Comment by Nigel Deakin [ 08/Dec/11 ]

I think this is a good idea, which I'll raise with the JSR 343 expert group. This might need to be defined in the Java EE platform spec rather than the JMS spec. I'll investigate.

Comment by Nigel Deakin [ 19/Jan/12 ]

I have logged this in the Java EE issue tracker as JAVAEE_SPEC-2

Comment by Nigel Deakin [ 23/Aug/12 ]

This has now been included in the Java EE 7 specification. A new section EE 5.19 "Default JMS COnnection Factory" states:

The Java EE Platform requires that a Java EE Product Provider provide a JMS provider in the operational environment (see Section EE.2.7.8, "Java™ Message Service (JMS)") . The Java EE Product Provider must also provide a preconfigured, JMS ConnectionFactory for use by the application in accessing this JMS provider.

The Java EE Product Provider must make the default JMS connection factory accessible to the application under the JNDI name java:comp/defaultJMSConnectionFactory.

The Application Component Provider or Deployer may explicitly bind a JMS ConnectionFactory resource reference to the default connection factory using the lookup element of the Resource annotation or the lookup-name element of the resource-ref deployment descriptor element. For example,

@Resource(name="myJMSCF", lookup="java:comp/defaultJMSConnectionFactory") 
ConnectionFactory myJMScf;

In the absence of such a binding for a JMS connection factory resource reference, the reference will map to a JMS connection factory for the product's JMS provider.

For example, the following will map to a preconfigured connection factory for the product's default JMS provider:

@Resource(name="myJMSCF")
ConnectionFactory myJMScf;




[JMS_SPEC-53] Make Connection and other interfaces implement AutoCloseable Created: 29/Sep/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-169 Make Connection and other interfaces ... Closed
Tags: ed20-added

 Description   

This is a proposal to change all the JMS interfaces that currently implement a close() method to implement the java.lang.AutoCloseable interface?

This would affect Connection, Session, MessageConsumer, MessageProducer, QueueBrowser.

This is a new feature of Java SE 7 which makes it easier to write code which closes a resource after use.

There's a nice explanation here:
http://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html]

Briefly, it allows you to write code such as:

try { 
   Connection conn = connectionFactory.createConnection();
   Session sess = conn.createSession(false,Session.AUTO_ACKNOWLEDGE;
   MessageProducer producer = seession.createProducer(dest);
}{
   Message mess = sess.createTextMessage("hello");
   producer.send(mess);
} catch(JMSException e){
  // exception handling
}

When this code is executed, the close() methods on the connection, session and producer are always called after use.

  • There's no need to call close() on any of the objects that are created.
  • There's no need to provide a finally block containing the calls to close().
  • Objects are closed in the reverse order in which they were created.
  • There's no need to guard against calling close() on a null value.
  • There's no need to use a nested try/catch block within the finally block to catch exceptions thrown by close()
  • If the try() block throws an exception, and a subsequent call to close() throws a second exception as a consequence, then it is the first exception, not the second exception, that is passed to the catch block. So you only see the exception that really matters. Any suppressed exceptions can still be accessed from the thrown exception if needed.

This change would be of benefit to both Java SE and Java EE applications. The only drawback I can think of is that it would introduce a dependency on Java SE 7. This isn't an issue for Java EE 7 applications since these are already dependent on Java SE 7. But it would force Java SE applications to use Java SE 7. However by the time JMS 2.0 is released, in a year from now, Java 7 will be pretty widespread so this might not be a problem.



 Comments   
Comment by Nigel Deakin [ 16/Dec/11 ]

I've now updated the javadocs and the draft spec with details of this new feature (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar
(One-line changes to Connection, Session, MessageProducer, MessageConsumer and QueueBrowser)

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(all changes are highlighted clearly with changebars, but the only place I've changed is 4.3.5 "Closing a Connection", 4.4.1 "Closing a Session", the example in section 9.1.3. Creating a Connection", and, in the changelog, section 11.5.3 "Automatically closing a connection or session")

I've now made Connection, Session, MessageProducer, MessageConsumer and QueueBrowser all extend AutoCloseable. (Note that MessagingContext, part of the proposed simplified API, already extends AutoCloseable)

(This updates the previous version of this comment which only referred to changes to Connection).

Comment by Nigel Deakin [ 05/Feb/12 ]

I've also changed javax.jms.SyncMessageConsumer to extend AutoCloseable, for consistency with MessageConsumer. API and javadocs updated.





[JMS_SPEC-55] Define a standard way to configure the connection factory used by a JMS MDB to consume messages Created: 07/Nov/11  Updated: 20/Mar/13  Resolved: 07/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on CONNECTOR_SPEC-4 Clarify whether the ResourceAdapter.e... Resolved
blocks MQ-250 Implement JMSRA activation properties... Closed
Related
is related to JMS_SPEC-54 Define a standard way to configure th... Resolved
Tags: jms20-jsr345, pd20-added

 Description   

This is a request for the EJB specification to define a standard way to configure the connection factory used by a MDB to consume messages.

Currently there is no standard way to do this, and vendors differ in the way in which connection information is specified in a MDB. Some vendors support an activation property connectionFactoryJndiName but this is not defined in the EJB 3.1 (or the JCA 1.6) specifications and support for it is not universal. In fact some vendors expect connection information to be specified directly using non-standard activation properties rather than via a connection factory.

This limits the portability of applications between different JMS providers, resource adapters and application servers. It will also hinder the automatic provisioning of JMS resources in a PaaS environment which is a goal of Java EE 7.

Two alternatives are proposed:

1. Define a mandatory activation property connectionFactoryJndiName

This would make it mandatory for application servers to support the activation property connectionFactoryJndiName. This would essentially standardise what some vendors support already.

This could be specified in ejb-jar.xml as follows:

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>MyMDB</ejb-name>
      <activation-config>          
         <activation-config-property>
            <activation-config-property-name>connectionFactoryJndiName</activation-config-property-name>
            <activation-config-property-value>jms/connectionFactory</activation-config-property-value>
         </activation-config-property>
      <activation-config>   
      ...

...or using annotation as follows:

@MessageDriven(
    activationConfig = {
        @ActivationConfigProperty(
            propertyName="connectionFactoryJndiName", propertyValue="jms/connectionFactory")
    })
public class MyMDB implements MessageListener {
....

2. Define a new element under the <message-driven> element and a corresponding annotation

This option would propose that the <message-driven> element in ejb-jar.xml be extended to define an addition sub-element which can be used to specify the JNDI name of the connection factory used by a JMS message-driven bean to consume messages. A suggested element name is <connection-factory-jndi-name>:

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>MessageBean</ejb-name>
      <message-destination-type>javax.jms.Queue</message-destination-type>
      <connection-factory-jndi-name>jms/connectionFactory<connection-factory-jndi-name>
      ...

To provide an equivalent annotation, a new attribute would need to be added to the @MessageDriven annotation. A suggested name is connectionFactoryJndiName:

@MessageDriven(connectionFactoryJndiName="jms/connectionFactory")
public class MyMDB implements MessageListener {
....

It might be asked why this needs to be defined by a new subelement of <message-driven> and a new attribute of @MessageDriven rather than by a new standard activation configuration property. Possible answers are:

  • this is needed for consistency with the existing <message-destination-link> and the proposed <message-destination-jndi-name> subelements of <message-driven>. (See JMS_SPEC-54).
  • the connection factory is such an important property of a JMS MDB that it deserves explicit support in the ejb-jar.xml schema and by the compiler, rather than being relegated to being just an activation property.

Options

In brief, the options are:

1) New mandatory activation property connectionFactoryJndiName
2) New element <connection-factory-jndi-name> and corresponding annotation @MessageDriven(connectionFactoryJndiName=...
3) Both 1) and 2)
4) Neither



 Comments   
Comment by Nigel Deakin [ 05/Dec/12 ]

The current proposal is to define a standard activation property connectionFactoryLookup.

However this is only possible if the connector spec can guarantee that the resource adapter will be able to perform the lookup in the endpointActivation call. I have logged CONNECTOR_SPEC-4 to request clarification .

Comment by Nigel Deakin [ 07/Feb/13 ]

The JMS 2.0 and EJB 3.2 specifications now define a activation property connectionFactoryLookup. This is defined as follows (JMS 2.0 section 13.1 "MDB activation properties"):

Activation property Description
connectionFactoryLookup This property may be used to specify the lookup name of an administratively-defined javax.jms.ConnectionFactory, javax.jms.QueueConnectionFactory or javax.jms.TopicConnectionFactory object that will be used to connect to the JMS provider from which the endpoint (message-driven bean) is to receive messages.

This issue is now incorporated in the JMS 2.0 spec and can be marked as resolved.





[JMS_SPEC-64] Define simplified JMS API Created: 08/Dec/11  Updated: 20/Mar/13  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-176 Implement simplified API for JMS 2.0 Closed
blocks JMS_SPEC-33 Improving the JMS API with API simpli... Resolved
blocks JMS_SPEC-70 Define annotations for injecting Mess... Resolved
Tags: pd20-added

 Description   

This is a request for a simplified JMS API. This would achieve the following goals:

  • To reduce the number of objects needed to send and receive messages, and in particular to combine the JMS 1.1 Connection, Session, MessageProducer and MessageConsumer objects as much as possible.
  • To take advantage of the fact that this is a new API to simplify method signatures and make other simplifications which cannot be made to the old API because it would break backwards compatibility.
  • To maintain a consistent style with the existing API where possible so that users of the old API feel it to be an evolution which that can learn quickly.
  • To support, and offer benefits to, both Java EE and Java SE applications.
  • To allow resource injection to be exploited in those environment which support it, whilst still offering significant improvements for those environments which do not.
  • To provide the option to send and receive message payloads to be sent and received directly without the need to use javax.jms.Message objects.
  • To remove as much as possible the need to catch JMSException on method calls
  • To be functionally complete. The old API will remain to provide backwards compatibility. However the new API is intended to be functionally as complete as the old JMS 1.1 API. Users should not need to switch back to the old API to perform an operation that is unavailable in the new API.


 Comments   
Comment by Nigel Deakin [ 08/Dec/11 ]

A proposed API is described in JMS20SimplifiedAPIv1.pdf with javadocs in jms-2.0-javadoc.jar

Comment by Nigel Deakin [ 03/Feb/12 ]

I've now updated the API, javadocs and the draft spec in accordance with the proposals made above.

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

See particularly the new interfaces javax.jms.MessagingContext, javax.jms.SyncMessageConsumer and the new factory methods on javax.jms.Connection.createMessagigingContext

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

See particularly the new chapter 13 "Simplified JMS API" and the change log in section 11.5.16.

Note that these changes cover the simplified API only. They do not include any proposals for injection of JMS objects (which will be handled in a separate JIRA issue).

Comment by Nigel Deakin [ 17/Feb/12 ]

I've updated the API, javadocs and the draft spec in accordance with the following changes.

The updated API and Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

Added new methods on MessagingContext to send the Map and byte[] payloads directly as MapMessage and BytesMessage.

Extended existing methods on SyncMessagingContext that receive message payloads directly to support MapMessage and BytesMessage

Added new method methods on MessagingContext: setAutoStart() and getAutoStart(). These allow the autostart behaviour (where the connection is automatically started when a consumer is created) to be disabled.

The spec has been clarified to define when MessagingContext.setClientID may be called and when it may not. The JMS 1.1 spec says that Connection.setClientID may only be called immediately after the conneciton is created and prior to doing anything else with the connection. Since the factory method to create a MessagingContext creates a connection and then uses it to create a session this means that calling MessagingContext.setClientID after this would never be valid. The spec has therefore been clarified to state that this is indeed valid.

Comment by Nigel Deakin [ 21/Mar/12 ]

Following discussions, I have changed the API for consuming messages asynchronously to require the use of a separate consumer. This means that applications cannot set a message listener directly on the MessagingContext. Instead they need to create a consumer object and set the message listener on that.

The new combined consumer object (for sync and async delivery) is called JMSConsumer
For reasons of consistency, MessagingContext has been renamed JMSContext

I've updated the API, javadocs and the draft spec with these changes

The updated API and Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

API and Javadoc changes

Changes to SyncMessageConsumer

  • Renamed to JMSConsumer
  • New method getMessageListener added
  • New method setmessageListener added
  • New method getBatchMessageListener added
  • New method setBatchMessageListener added

Changes to MessagingContext

  • Renamed to JMSContext
  • Existing method createSyncConsumer (3 methods) renamed to createConsumer
  • Existing method createSyncDurableConsumer (2 methods) renamed to createDurableConsumer
  • Existing method setmessageListener (5 methods) deleted
  • Existing method setBatchMessageListener (5 methods) deleted
  • Existing method createMessagingContext renamed to createContext

Changes to ConnectionFactory

  • Existing method {{createMessagingContext (4 methods) renamed to createContext

Spec changes

Section 11.2.4 "Consuming messages asynchronously" has been completely deleted.

Section 11.2.5 "Consuming messages synchronously" has been renamed 11.2.4 "Consuming messages" and updated to cover async message delivery as well.

Following the deletion of the section mentioned above, sections 11.2.6, 11.2.7, 11.2.8 and 11.2.9 become 11.2.5, 11.2.6, 11.2.7 and 11.2.8.

In section A.2 "Unresolved issues in the JMS 2.0 Early Draft", subsection A.2.1 "Simplified JMS API: Support for multiple consumers on a session" has been deleted since this issue has now been resolved.

References to MessagingContext have been changed to JMSContext throughout
References to SyncMessageConsumer have been changed to JMSConsumer throughout

Section 11.4. "Examples using the simplified API" has been updated to reflect these API changes.

Note that the spec does not attempt to record the changes between the Early Draft and this version, since this would be too complicated.

Comment by Nigel Deakin [ 21/Sep/12 ]

The API for sending messages has been completely revised to introduce a new interface JMSProducer. For a full description see section 11.2.4 "Sending messages" in the JMS 2.0 public draft.





[JMS_SPEC-20] New "Not Before" Header Created: 24/May/11  Updated: 07/Nov/11  Resolved: 07/Nov/11

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: fribeiro Assignee: Unassigned
Resolution: Duplicate Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

It would be nice to be able to filter out messages that shouldn't be consumed before a timestamp provided in a standard "not before" header.

I've heard before that at least one implementation provides a custom header for this use case, but can't find the reference now.



 Comments   
Comment by clebertsuconic [ 24/May/11 ]

+1 Most providers have scheduled delivery as part of their implementation. I even thought this was part of the API already.

There should be a standard way IMO through the API.

Comment by Nigel Deakin [ 07/Nov/11 ]

The JSR 343 Expert group has proposed JMS_SPEC-44 which is effectively a duplicate of this issue. I will therefore mark this issue as resolved with a resolution of "Duplicate.

Please look at JMS_SPEC-44 and add any comments you feel appropriate.





[JMS_SPEC-15] Queue Depth Created: 24/May/11  Updated: 09/Mar/12  Resolved: 09/Mar/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: colincrist Assignee: Unassigned
Resolution: Duplicate Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-18 Standard set of server JMX MBeans Open
duplicates JMS_SPEC-59 Basic metadata/management via JMS Open

 Description   

As a client I would like to get the current queue depth on a queue. All existing providers give this information via a custom API or JMX at present.



 Comments   
Comment by fribeiro [ 24/May/11 ]

Maybe we should revise whether the spec specifies the notifications that must be supported by implementations – this one should definitely be there.

Comment by rdohna [ 09/Dec/11 ]

JMS_SPEC-15 is a special case of JMS_SPEC-59

Comment by Nigel Deakin [ 09/Mar/12 ]

@fribeiro: I'm not sure what you mean by notifications here and how it relates to obtaining the queue depth (and I don't want to guess). Can you please log your proposal as a new JIRA issue?

Comment by Nigel Deakin [ 09/Mar/12 ]

I'm merging this proposal with two more general proposals:

JMS_SPEC-59 - which covers general non-JMX metadata queries
JMS_SPEC-18 - which covers general JMX facilities

I'm going to close this issue as a duplicate of those. Feel free to contribute comments to those issues.





[JMS_SPEC-12] Message producer confirms aka async message production. Created: 23/May/11  Updated: 05/Mar/12  Resolved: 05/Mar/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0

Type: New Feature Priority: Major
Reporter: colincrist Assignee: Nigel Deakin
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-43 New API to send a message with async ... Resolved

 Description   

The synchronous 1.1 JMS API has an impact on how a single thread can produce messages with a session. There is too much waiting around for a reply from the server.

As a JMS client I would like to send a message on a non-transacted session with persistent delivery and receive asynchronous confirmation that it is stable via a callback. The session can then interact with the server in a more efficient manner.

RabbitMQ has a good write up of the functionality http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms.
29West and Tervela have similar capability.
No doubt some JMS implementations have similar capabilities using non-JMS APIs.



 Comments   
Comment by timlfox [ 08/Jun/11 ]

+1 on this feature.

HornetQ was a pioneer with this - it's definitely a must for high throughput reliable message sending.

http://docs.jboss.org/hornetq/2.2.2.Final/user-manual/en/html/send-guarantees.html#asynchronous-send-acknowledgements

Comment by bsnyder [ 10/Jun/11 ]

Agreed, this is one area where there is a hole in the JMS 1.x spec.

Comment by rdohna [ 14/Jun/11 ]

I can see that there are some very-high-throughput use cases for this feature, but you'd need to implement your own two-phase commit, wouldn't you? It's a lot of code every client would have to re-implement... and it's easy to get it wrong and extremely difficult to test. It's quite a chimaera between transactional and non-transactional, isn't it?

I think we should either find a solution that's easier to work with, or choose to leave it out of the standard; it may have to be optimised for every JMS implementation anyway.

Comment by colincrist [ 15/Jun/11 ]

Persistent messaging does not imply container managed transactions. In the classic J2EE world the way to do persistent messaging and database co-ordination is via XA. This is fine for many use cases but I have found JMS used a great deal without a J2EE container and XA is not the only way to avoid data loss although it does require a bit of coding to co-ordinate

If say on some thread(s) messages are sent whilst on another the stability confirms are received sometime later then the application can update its store that the message (say an order) has indeed been sent successfully and can also do this in batch, keeping the disk I/O under control. This approach leads to a flurry of application generated duplicate messages on recovery as the application has to send messages it has not seen stability confirms for but this is the price you pay for scalability. On the plus side there is far less waiting around to co-ordinate disk writes via XA so you get a hugh increase in throughput, 10s-100s of times faster is not uncommon.

The implementation of this part of the API is up to the provider and its performance would be another differentiator between products.

Comment by rdohna [ 16/Jun/11 ]

NON_PERSISTENT means at-most-once message delivery. PERSISTENT currently (as of JMS 1.1) means once-and-only-once message delivery. I understand that this issue requests something else, as it doesn't want to pay the price for the transaction overhead, but still wants guaranteed delivery.

This means that you'd have to mark the reason for the message as "in progress" before you send the message. When you receive an ack, you'd mark that status as "done". This as a manual two-phase commit, isn't it?

Now whenever the sender or the receiver fails, there are two options: If the receiver is idempotent, you can resend all "in progress" messages... that's a new at-least-once message delivery and not yet supported by JMS... there may be use cases for this.

But if you still require full once-and-only-once guarantee, there has to be some resolution mechanism to re-sync the status of the sender and the receiver. Distributed transactions have such mechanisms, but that's expensive... and I can see no way around that.

If JMS 2.0 defines a at-least-once delivery guarantee, I'd prefer not to have every client to repeat that code, but to hide it somehow at a lower layer. But I don't have any good ideas, yet.

Comment by abien [ 18/Jun/11 ]

+1 for callback. But why just with persistent messages? Could be also interesting for transient messages.

Comment by Nigel Deakin [ 05/Mar/12 ]

This requirement appears to have been satisfied by JMS_SPEC-43, which was included in the JMS 2.0 Early Draft. Please review that draft and provide any comments.

That other issue appears to be a duplicate of this one. Given that the other issue contains details of the proposed changes I will close this issue as being a duplicate. Feel free to make comments on the other issue, or directly to users@jms-spec.java.net.





[JMS_SPEC-45] Clarify and improve Connection.createSession Created: 09/Aug/11  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-172 Implement two new Connection.createS... Closed
Tags: ed20-added

 Description   

In the JMS 1.1 specification, the following method on a javax.jms.Connection is used to create a javax.jms.Session:

Session createSession(boolean transacted, int acknowledgeMode) throws JMSException

where transacted may be set to true or false and
acknowledgeMode may be set to Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE

(There are similar methods on javax.jms.QueueConnection and javax.jms.TopicConnection: this whole issue applies to all three.)

This is a rather confusing method for several reasons:

  • It uses two arguments to define a single aspect of the session
  • In a Java EE transaction, both arguments are ignored anyway
  • In a Java EE unspecified transaction context, the meaning of the arguments is undefined and unclear

It uses two arguments to define the same thing

This method uses two arguments to define what is in practice a single aspect of the session with four possibilities: if transacted is set to false then the session is non-transacted and the acknowledgeMode argument defines which of three kinds of acknowledgement are used when receiving messages. If transacted is set to true then the acknowledgeMode argument is ignored.

This is inconsistent with the method Session.getAcknowledgeMode() which returns one of four values: Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, or Session.DUPS_OK_ACKNOWLEDGE if the session is not transacted and Session.SESSION_TRANSACTED if the session is transacted.

This also leads to code which is potentially misleading, since if transacted is false the user still has to set acknowledgeMode to some value even if it is ignored, which leads to code such as

Session session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE);

Some developers like to use

Session session = connection.createSession(true,Session.SESSION_TRANSACTED);

though this is still misleading since since if transacted was set to true then the second argument is ignored anyway, and if transacted is false then setting acknowledgeMode to Session.SESSION_TRANSACTED would be an error.

In a Java EE transaction, both arguments are ignored anyway

In a Java EE transaction none of the four options listed above are permitted. Instead, both arguments to connection.createSession are ignored and a global transaction is used.

The EJB 3.1 Specification, section 13.3.5 "use of JMS APIs in Transactions" states that, in a container-managed or bean-managed transaction,

Because the container manages the transactional enlistment of JMS sessions on behalf of a bean, the parameters of the createSession(boolean transacted, int acknowledgeMode) method createQueueSession... are ignored.

This also applies to web applications. The Java EE platform spec, Section EE.6.7 "Java Message Service (JMS) 1.1 Requirements" specifies that

The behavior of a JMS provider should be the same in both the EJB container and the web container." It continues "The EJB specification describes restrictions on the use of JMS in an EJB container, as well as the interaction of JMS with transactions in an EJB container. Applications running in the web container should follow the same restrictions.

Instead, the receiving and sending of messages must be part of the container-managed or bean-managed transaction, and the transaction will be committed or rolled back in the way that container-managed or bean-managed transactions are committed or rolled back.

  • Container-managed transactions are either committed when the appropriate business method completes or are rolled back using EJBContext.setRollbackOnly.
  • Bean-managed transactions are either committed using UserTransaction.commit or rolled back using UserTransaction.rollback.

How explicit is the EJB specification about all this? In addition to specifying that in a transactional context the arguments to Connection.createSession are ignored, it also states the following:

  • Section 13.3.5 states that "within a transaction" the bean should not use the acknowledge method. This therefore covers both container-managed and bean-managed transactions.
  • Section 13.3.3 states that in the case of bean-managed transactions, the bean must not invoke the commit or rollback methods on the javax.jms.Session interface.
  • Section 13.3.4 states that in the case of container-managed transactions, the bean must not "use any resource-managed specific transaction management methods that would interfere with the container's demarcation of transaction boundaries" and again must not invoke the commit or rollback methods on the javax.jms.Session interface.
  • Section 13.1.1 states that in the case of bean-managed transactions, "all resource manager accesses between the UserTransaction.begin and UserTransaction.commit calls are part of a transaction", thereby apparently ruling out the use of non-transacted sessions using auto-acknowledgement and dups-ok-acknowledgement as well as those using client-acknowledgement.
  • Section 13.1.1 also states in a container-managed transaction the transaction demarcation depends on the transaction attributes of the bean method. It doesn't explicitly state that all resource manager accesses should be part of this transaction, but this is implied.

In a Java EE unspecified transaction context, the meaning of the arguments undefined and unclear

The previous section only relates to the use of the JMS API "in transactions". It does not cover how the JMS API should behave when there is no current container-managed or bean-managed transaction. That is, when there is an unspecified transaction context.

The EJB 3.1 Specification, section 13.6.5 "Handling of Methods that run with an unspecified transaction context" defines an "unspecified transaction context" as covering "the cases in which the EJB architecture does not fully define the transaction semantics of an enterprise bean method execution".

Section 13.6.5 goes on to give a list of examples of when an "unspecified transaction context" may arise. All the cases given are for container-managed transactions, leaving an ambiguity about what an "unspecified transaction context" means when using bean-managed transactions. An obvious interpretation is that that if a bean is configured to use bean-managed transactions, then business methods or onMessage() code executed before a call to userTransaction.begin(), or after a call to UserTransaction.commit or UserTransaction.rollback, is executed in an unspecified transaction context, as is any code executed in the four bean lifecycle callback methods listed in 13.6.5 (PostConstruct,PreDestroy, PostActivate, or PrePassivate). However this is not explicitly stated in the EJB spec.

So, what does the EJB spec say should happen in an "unspecified transaction context"?

Section 13.6.5 is written with all resource managers (not just JMS) in mind, and states that

"The EJB specification does not prescribe how the container should manage the execution of a method with an unspecified transaction context—the transaction semantics are left to the container implementation.

It goes on to give some options, which include treating "each call... to a resource manager as a single transaction", merging multiple calls into a single transaction, or accessing the resource manager "without a transaction context".

Now in the case of JMS the application has a way to give the container a hint as to what behaviour they desire: the arguments to {[createSession}}. So it would seem reasonable to follow these.

However the EJB 3.1 specification, section 13.3.5 does explicitly state that "The Bean Provider should not use the JMS acknowledge method either within a transaction or within an unspecified transaction context. Message acknowledgment in an unspecified transaction context is handled by the container.

It is curious that although Session.acknowledge is prohibited in a unspecified transaction context, Session.commit is not, even though both perform message acknowledgement. If the former is invalid, then the latter must be as well.

This means that within an unspecified transaction context:

  • a non-transacted session using client acknowledgement is explicitly prohibited
  • a (local) transacted session is implicitly prohibited
  • a non-transacted session is permitted, with both client-acknowledgement and dups-ok-acknowledgement (which is an optimised version of auto-acknowledgement) allowed.

Summary

So in Connection.createSession (and QueueConnection.createQueueSession and TopicConnection.createTopicSession we have a method which offers different options depending on the context in which it is used:

  • In a Java EE transaction there are no options: the session is part of a transaction managed by the container and the application has no choice on the matter.
  • In a Java EE unspecified transaction context there are two options:
    • non-transacted session with auto-acknowledgement
    • non-transacted session with dups-ok-acknowledgement
  • In a Java SE environment there are four options:
    • non-transacted session with auto-acknowledgement
    • non-transacted session with dups-ok-acknowledgement
    • non-transacted session with client-acknowledgement
    • transacted session

So, in the light of all this, what are the problems?

  • the special behaviour of this method in a Java EE transaction is not mentioned anywhere in the JMS specification or in the javadocs, which means that users are surprised when they discover that the arguments to createSession are ignored. Fortunately, however, the required behaviour is clearly defined in the EJB specification.
  • the special behaviour in a Java EE unspecified transaction context is also not mentioned anywhere in the JMS specification or in the javadocs. Unfortunately, the required behaviour is not explicitly described in the EJB specification but has to be pieced together from various different sections, as in the analysis above. This needs to be confirmed and stated explicitly.
  • the actual API for createSession, with its two arguments, not only does not reflect the four options available in the normal Java SE case, it does not reflect the zero options available in the Java EE transaction case or the two options available in the Java EE unspecified transaction context case. However when compared the the two preceding issues this is perhaps not such a major issue.

Proposals

It is proposed that

  • The JMS specification and javadocs be updated to describe how createSession behaves in a Java EE applicaiton, both in a transaction and in an unspecified transaction context. The former case will be a restatement of the existing EJB spec, the latter case will be intended to remove any ambiguities in the EJB spec along the lines of the analysis above.
  • A new method be provided in a javax.jms.Connection
Session createSession(int sessionMode) throws JMSException

In a normal Java SE environment sessionMode may be set to 
Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE 
or Session.TRANSACTED

In a Java EE transaction, sessionMode is ignored.

In a Java EE undefined transaction context, sessionMode may be set to 
Session.AUTO_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE only.
  • A further new method be provided in a javax.jms.Connection
Session createSession() throws JMSException

This method is  particularly intended for use in a Java EE environment,
though it may also be used in a normal Java SE environment.

In a normal Java SE environmentm this is equivalent to calling createSession(Session.AUTO_ACKNOWLEDGE)

In a Java EE transaction, the session will be part of a transaction managed by the container. 

In a Java EE undefined transaction context, the session will have a sessionMode of Session.AUTO_ACKNOWLEDGE.
  • The existing method createSession(boolean transacted,int acknowledgeMode will remain with a note added to encourage applications to use the other two methods. In accordance with Java EE policy it will remain in the API indefinitely, and will not be formally marked as @Deprecated.


 Comments   
Comment by Nigel Deakin [ 23/Sep/11 ]

Description updated to propose new method Session createSession() with no arguments for use in a Java EE environment.

Comment by Nigel Deakin [ 30/Sep/11 ]

Updated to propose that the existing method createSession(boolean transacted,int acknowledgeMode will be formally marked as @Deprecated

Comment by Nigel Deakin [ 18/Oct/11 ]

Do we need a new method getSessionMode()?

There is already a method getAcknowledgeMode() which Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, Session.DUPS_OK_ACKNOWLEDGE or Session.TRANSACTED as appropriate. It therefore already returns the session mode though the name is misleading.

We have lived with this mis-named method for a long time so I don't think it is necessary to create a new method getSessionMode() which is functionally identical but more appropriately named. We could never remove the old method, so this would simply clutter up the API whilst confusing the user.

We should therefore stick with getAcknowledgeMode and change the javadoc documentation to clarify that what it returns is the same as the session mode.

Comment by Nigel Deakin [ 13/Jan/12 ]

Before we finalise the above proposals I'd like to explore in more detail exactly how createSession (and other methods in the JMS API) are required to behave in a Java EE environment. Before we can clarify the use of this method we need to be able to answer the following questions.

(I've already suggested answers to some, but not all, of these questions in my proposals above. However I think it's very important to get this right and it's work revisiting them. In addition, there are several additional issues which need to be answered before users can unambiguously know how this method is required to behave.)

1. JMS resources which do not support JTA transactions

In the EJB 3.1 specification, section 13.3.5 "use of JMS APIs in Transactions" states that:

Because the container manages the transactional enlistment of JMS sessions on behalf of a bean, the parameters of the createSession(boolean transacted, int acknowledgeMode) method createQueueSession... are ignored."

The reference to "transaction enlistment" appears to be a reference to JTA transactions managed by the application server, which may be "bean-managed" (using the UserTransaction API to begin and commit the transaction) or, for EJBs, "container-managed".

Q1.1: Does the sentence quoted above mean that the JMS session must participate in the transaction, or is it permitted to create a session which does not participate in the transaction.

There have been suggestions that connections which are "non-managed" or "non-JCA" connections are not required to participate in the transaction. However there is no mention of such cases in the EJB spec.

Q1.2: Is this permitted?

Q1.3: Are such cases also exempt from the requirement that the arguments to createSession be ignored?

2. When there isn't a container-managed or bean-managed transaction.

I'd also like to explore the case where there isn't a container-managed or bean-managed transaction. The EJB 3.1 Specification, section 13.6.5 "Handling of Methods that run with an unspecified transaction context" contains some guidance about the transaction semantics in such a case.

Q2.1: What is an "unspecified transaction context"? Does this mean any case where there is not an active JTA transaction, such as where the transaction attribute is set to "Never"? Does it include the BMT case before userTransaction.begin() or after userTransaction.commit()? Does it include all of the EJB callback methods?

3. The ban on calling acknowledge()

Section 13.3.5 of the EJB spec, "Use of JMS APIs in Transactions", states that "The Bean Provider should not use the JMS acknowledge method either within a transaction or within an unspecified transaction context. Message acknowledgment in an unspecified transaction context is handled by the container."

Q3.1: What is the reason for this restriction? Is it necessary?

Q3.2: If acknowledge is called in a Java EE environment, what should happen? Should an exception be thrown?

Q3.3: Do these restrictions on explicit message acknowledgement also apply to local transactions, given that calling session.commit has the effect of acknowledging all messages received in the local transaction?

4. Bean-managed transactions

In a application that uses bean-managed transactions, what happens if the session is created before the transaction is started? Consider the following:

Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(destination);
producer.send(message1);
userTransaction.begin();
producer.send(message2);
. . .
userTransaction.commit();

Q4.1: Is this valid?

Q4.2: Is message1 sent immediately or is it committed as part of the user transaction?

Q4.3: Is message2 sent immediately or is it committed as part of the user transaction?

Comment by Nigel Deakin [ 24/Jan/12 ]

I've now updated the API, javadocs and the draft spec in accordance with the proposals made above.

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

  • New methods Connection.createSession(int sessionMode) and Connection.createSession() which create a Session.
  • New javadoc comment for the existing method Connection.createSession(boolean transacted, int acknowledgeMode) which creates a Session.
  • New javadoc comments for the various methods on ConnectionFactory and MessagingContext which create a MessagingContext

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf

  • Updated section 1.4.7 "Java Platform, Enterprise Edition (Java EE)"
  • Deleted section 1.4.8 "Integration of JMS with the EJB Components"
  • New chapter 12 "Use of JMS API in Java EE applications"
  • New section 12.2 "Use of JMS API in Java EE applications"
  • New sections 11.5.14 & 11.5.15 which are the change log for these changes

(I'll come back later and formally answer the questions I made in the previous comment)

Comment by Nigel Deakin [ 24/Jan/12 ]

I have updated the description above to remove the statement that the existing method createSession(boolean transacted,int acknowledgeMode will be marked as @Deprecated and that the javadocs will warn that this method may be removed in the future.

The Java EE Backwards Compatibility Requirements do not allow us to use @Deprecated, not do they allow us to remove existing methods from the API.

Instead the javadoc comment for this method will simply have a note which encourages applications to use the other two createSession methods instead.

Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-101] New methods Message.getBody(Class<T> c) and isBodyAssignableTo(Class c) Created: 23/Oct/12  Updated: 20/Mar/13  Resolved: 08/Nov/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-226 Implement new method Message.getBody ... Closed
blocks JMS_SPEC-102 Make JMSConsumer.receivePayload metho... Closed
Tags: pd20-added

 Description   

This is a proposal to add a new method to javax.jms.Message which allows the message payload to be obtained without the need to cast the object to the appropriate subtype first. This can slightly simplify the code of a MessageListener's, onMessage method, where the object passed in is always declared to be a javax.jms.Message.

Here is the proposed API:

	/**
	 * Returns the messages's payload, which must be of the specified type. If
	 * the message has no payload then null is returned. This method may be used
	 * to obtain the payload of any type of message except for
	 * <tt>StreamMessage</tt>.
	 * 
	 * @param c
	 *            The class of the payload.<br/>
	 *            If the message is a <code>TextMessage</code> then this should
	 *            be set to <code>String.class</code>.<br/>
	 *            If the message is a <code>ObjectMessage</code> then this
	 *            should be set to <code>java.io.Serializable.class</code>. <br/>
	 *            If the message is a <code>MapMessage</code> then this should
	 *            be set to <code>java.util.Map.class</code>.<br/>
	 *            If the message is a <code>BytesMessage</code> then this should
	 *            be set to <code>byte[].class</code>.<br/>
	 *            If the message payload is not of the specified type a
	 *            <code>MessageFormatException</code> will be thrown
	 * 
	 * @return the messages's payload
	 * 
	 * @exception JMSException
	 *                if the JMS provider fails to get the payload due to some
	 *                internal error.
	 * @exception MessageFormatException
	 *                if the payload is not of the specified type or, if the
	 *                message is an ObjectMessage, if object deserialization
	 *                fails.
	 * @Exception MessageNotReadableException - if the message is a BytesMessage
	 *                and the message is in write-only mode.
	 */
	<T> T getPayload(Class<T> c) throws JMSException;

This means that instead of something like:

    public void onMessage(Message message) {
        String payload = ((TextMessage) message).getText();

we could have

    public void onMessage(Message message) {
        String payload2 = message.getPayload(String.class); 


 Comments   
Comment by Nigel Deakin [ 23/Oct/12 ]

Here's an updated proposal:

	/**
	 * Returns the messages's payload, which must be assignable to the specified
	 * type. If the message has no payload then null is returned. This method
	 * may be used to obtain the payload of any type of message except for
	 * <tt>StreamMessage</tt>.
	 * 
	 * @param c
	 *            The class of the payload.
	 *            <br/>
	 *            If the message is a <code>TextMessage</code> then this should
	 *            be set to <code>String.class</code> or any other class to
	 *            which a String is assignable.
	 *            <br/>
	 *            If the message is a <code>ObjectMessage</code> then this
	 *            should be set to <code>java.io.Serializable.class</code> or
	 *            any other class to which the payload is assignable.
	 *            <br/>
	 *            If the message is a <code>MapMessage</code> then this should
	 *            be set to <code>java.util.Map.class</code>.
	 *            <br/>
	 *            If the message is a <code>BytesMessage</code> then this should
	 *            be set to <code>byte[].class</code>.
	 * 
	 * @return the messages's payload
	 * 
	 * @exception JMSException
	 *                if the JMS provider fails to get the payload due to some
	 *                internal error.
	 * @exception MessageFormatException
	 *                if the message is a <code>StreamMessage</code>, or the
	 *                payload cannot be assigned to the specified type, or the
	 *                message is an <code>ObjectMessage</code> and object deserialization
	 *                fails.
	 * @exception MessageNotReadableException - if the message is a <code>BytesMessage</code>
	 *                and the message is in write-only mode.
	 */
	<T> T getPayload(Class<T> c) throws JMSException;
Comment by Nigel Deakin [ 26/Oct/12 ]

Following discussion on the expert group the name of this proposed method is changed from getPayload to getBody (for consistency with established JMS 1.1 terminology). Minor changes have also been made to the wording. Here's the latest draft API:

	/**
	 * Returns the message body as an object of the specified type. The message
	 * body must be capable of being assigned to the specified type. This means
	 * that the specified class or interface must be either the same as, or a
	 * superclass or superinterface of, the class of the message body. This
	 * method may be used to obtain the body of any type of message except for
	 * <tt>StreamMessage</tt>. If the message has no body then null is returned.
	 * 
	 * @param c
	 *            The type to which the message body should be assigned. <br/>
	 *            If the message is a <code>TextMessage</code> then this should
	 *            be set to <code>String.class</code> or another class to which
	 *            a String is assignable. <br/>
	 *            If the message is a <code>ObjectMessage</code> then this
	 *            should be set to <code>java.io.Serializable.class</code> or
	 *            another class to which the payload is assignable. <br/>
	 *            If the message is a <code>MapMessage</code> then this should
	 *            be set to <code>java.util.Map.class</code>. <br/>
	 *            If the message is a <code>BytesMessage</code> then this should
	 *            be set to <code>byte[].class</code>. The
	 *            <code>BytesMessage</code> must not be in write-only mode.
	 * 
	 * @return the message body
	 * 
	 * @exception JMSException
	 *                if the JMS provider fails to get the message body due to
	 *                some internal error.
	 * @exception MessageFormatException
	 *                if the message is a <code>StreamMessage</code>, or the
	 *                message body cannot be assigned to the specified type, or
	 *                the message is an <code>ObjectMessage</code> and object
	 *                deserialization fails.
	 * @exception MessageNotReadableException
	 *                if the message is a <code>BytesMessage</code> and the
	 *                message is in write-only mode.
	 */
	<T> T getBody(Class<T> c) throws JMSException;

In addition, there has been a proposal to provide an additional method isBodyAssignableTo which can be used to find out whether a subsequent call to getBody would throw a MessageFormatException. Here it is:

	/**
	 * Returns whether the message body is capable of being assigned to the
	 * specified type. If this method returns true then a subsequent call to the
	 * method <code>getBody</code> with the same type argument would not throw a
	 * MessageFormatException.
	 * <p>
	 * If the message is a <code>StreamMessage</code> then false is returned. If
	 * the message is a <code>ObjectMessage</code> and object deserialization
	 * fails then false is returned. If the message has no body then true is
	 * returned.
	 * 
	 * @param c
	 *            The specified type <br/>
	 *            If the message is a <code>TextMessage</code> then method will
	 *            only return true if this parameter is set to
	 *            <code>String.class</code> or another class to which a String
	 *            is assignable. <br/>
	 *            If the message is a <code>ObjectMessage</code> then this
	 *            method will only return true if this parameter is set to
	 *            <code>java.io.Serializable.class</code> or another class to
	 *            which the payload is assignable. <br/>
	 *            If the message is a <code>MapMessage</code> then this method
	 *            will only return true if this parameter is set to
	 *            <code>java.util.Map.class</code>. <br/>
	 *            If the message is a <code>BytesMessage</code> then this this
	 *            method will only return true if this parameter is set to
	 *            <code>byte[].class</code>.
	 * 
	 * @return whether the message body is capable of being assigned to the
	 *         specified type
	 * 
	 * @exception JMSException
	 *                if the JMS provider fails to return a value due to some
	 *                internal error.
	 * @exception MessageNotReadableException
	 *                if the message is a <code>BytesMessage</code> and the
	 *                message is in write-only mode.
	 */
	boolean isBodyAssignableTo(Class c) throws JMSException;
Comment by Nigel Deakin [ 26/Oct/12 ]

Change issue summary to refer to getBody instead of getPayload.

Comment by Nigel Deakin [ 08/Nov/12 ]

This is now approved and added to the public draft.





[JMS_SPEC-105] Provide API to allow an app server or resource adapter to obtain a XAResource from a JMSContext Created: 30/Oct/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 2.0PD
Fix Version/s: 2.0PD, 2.0

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-233 Implement API to allow an app server ... Closed
Tags: pd20-added

 Description   

JMS 1.1 defined an optional API to allow an application server or resource adapter to obtain a XAResource object corresponding to a Session object. This is the "chapter 8" API, which defines the optional interfaces XAConnectionFactory, XAConnection, XASession and the method XASession#getXAResource().

However there is currently no equivalent API to allow an application server or resource adapter to obtain a XAResource object corresponding to a JMSContext object.

This means that an application server which uses the "chapter 8" API to integrate with a JMS provider (rather than using a resource adapter) cannot support JMSContext properly. The same applies for a generic resource adapter which uses the "chapter 8" API to integrate with any JMS provider.

There are two alternatives:

Option 1

This option follows the same approach as the existing "chapter 8" API

  • Add four new new createXAContext methods to XAConnectionFactory. These are similar to the four existing createContext methods on ConnectionFactory except that they return a XAJMSContext rather than a JMSContext
  • Define a new interface XAJMSContext. This is a subtype of JMSContext with one additional method, getXAResource, which returns a XAResource.

Option 2

  • Simply add a new method getXAResource to the JMSContext

In both cases implementation of the new interfaces and methods would be optional just like the rest of the existing "chapter 8" API is.

It is proposed that option 1 be adopted, but option 2 is mentioned as a possible alternative.

Note that even though the chapter 8 API is optional, and JMS 2.0 encourages the use of a the JCA API rather than the chapter 8 API for integration of a JMS provider and an application server, the chapter 8 API continues to be part of JMS and is valued by some vendors. If we did not implement this change then we would effectively be breaking this API by making it unusable with JMSContext objects.



 Comments   
Comment by clebertsuconic [ 30/Oct/12 ]

Another issue I constantly face over Transactions is... Most Transaction Managers will offer a recovery option, and currently there's no way to register the XAResource to be recovered. There's no public API that would allow that. it would be nice if we could address that. But I think this will probably go beyond the scope of JMS.

Comment by Nigel Deakin [ 30/Oct/12 ]

@clebert: Do you mean there is no standard way for a transaction manager performing recovery to obtain all the XAResource objects it needs to use for recovery? If so then this is more than a JMS issue.

Comment by nwright [ 12/Nov/12 ]

If I understand, it looks like we'd need a hook on the transaction manager API to actively tell it that we (a JMS resource) are a candidate for XA recovery. In which case this does go beyond the scope of JMS, who can we talk to from the JTA spec about this?

I may have the wrong end of the stick however

Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-106] Methods on JMSContext that are disallowed if the context is injected should throw a IllegalStateException not a JMSException Created: 07/Nov/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 2.0PD
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-240 Implement modified exceptions on JMSC... Closed
Tags: pd20-added

 Description   

Section 11.3.5. "Restrictions on use of injected JMSContext objects" of the draft JMS 2.0 specification lists some methods which may not be used if the JMSContext is injected (container-managed). It specifies that these methods must throw a JMSRuntimeException if the JMSContext is injected.

A better exception to throw would be an IllegalStateRuntimeException since the error is caused by the JMSContext being "in the wrong state" (container-managed).



 Comments   
Comment by Nigel Deakin [ 14/Nov/12 ]

API docs and spec now updated.





[JMS_SPEC-97] Define Java EE JMS Connection Factory Definition annotation and descriptor elements Created: 23/Jul/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-added

 Description   

The Java EE 7 Early Draft specifies that an application may define a JMS ConnectionFactory resource using either a JMSConnectionFactoryDefinition annotation on an application class or a <jms-connection-factory> element in the deployment descriptor.

Although this feature is specified in the Java EE platform spec, the JMS spec needs to define the following:

  • The list of standard properties that may be specified
  • The actual javax.jms.JMSConnectionFactoryDefinition annotation as part of the JMS API


 Comments   
Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-96] Define Java EE JMS Destination Definition annotation and descriptor elements Created: 23/Jul/12  Updated: 22/Mar/13  Resolved: 22/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-added

 Description   

The Java EE 7 Early Draft specifies that an application may define a JMS Destination resource using either a JMSDestinationDefinition annotation on an application class or a <jms-destination> element in the deployment descriptor.

Although this feature is specified in the Java EE platform spec, the JMS spec needs to define the following:

  • The list of standard properties that may be specified
  • The actual javax.jms.JMSDestinationDefinition annotation as part of the JMS API





[JMS_SPEC-98] Fix findbugs warnings in JMSException, JMSRuntimeException, QueueRequestor, TopicRequestor Created: 14/Aug/12  Updated: 20/Mar/13  Resolved: 04/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Bug Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-added

 Description   

The following JMS 1.1 classes give the following findbugs warnings:

javax/jms/JMSException.java:86: UG_SYNC_SET_UNSYNC_GET: 
javax.jms.JMSException.getLinkedException() is unsynchronized, 
javax.jms.JMSException.setLinkedException(Exception) is synchronized

javax/jms/QueueRequestor.java:62: URF_UNREAD_FIELD:
Unread field: javax.jms.QueueRequestor.queue

java/javax/jms/TopicRequestor.java:61: URF_UNREAD_FIELD: Unread field:
javax.jms.TopicRequestor.topic

It should be possible for fix all these without breaking backwards compatibility.

Also, the following new JMS 2.0 class givs the following findbugs warnings:

javax/jms/JMSRuntimeException.java:118: UG_SYNC_SET_UNSYNC_GET:
javax.jms.JMSRuntimeException.getLinkedException() is unsynchronized,
javax.jms.JMSRuntimeException.setLinkedException(Exception) is synchronized

This should be fixed.



 Comments   
Comment by Nigel Deakin [ 04/Sep/12 ]

Now fixed.





[JMS_SPEC-87] Section 2.5 "Interfaces" needs updating to introduce the simplified API Created: 12/Mar/12  Updated: 20/Mar/13  Resolved: 14/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fd20-doc-added

 Description   

Section 2.5 "Interfaces" needs updating to introduce the simplified API alongside the "standard" API and to explain how they interrelate.

As part of this work it may be helpful to modify Figure 2.2 "Overview of JMS object relationships" to show the cardinality of the inter-object relationships, for both the standard and simplified API and for Java SE and for the Java EE web or EJB container.



 Comments   
Comment by Nigel Deakin [ 14/Feb/13 ]

The structure of the JMS 1.1 specification reflected the domain-specific APIs introduced in JMS 1.0, with section titles such as "QueueConnection" and "TopicSubscriber". This was an inappropriate structure even in JMS 1.1 since these interfaces had been superseded in JMS 1.1 by the "unified" API. The addition of the simplified API in JMS 2.0 makes that structure even more inappropriate.

The JMS 2.0 specification has now been completely restructured along functional lines, with chapter headings such as "connecting to a JMS provider" and "receiving messages". These describe each area of functionality in generic terms followed by a description of how it is implemented in the various APIs. In general these chapters contain the same text as in the previous version.

In particular a new section 2.5. "JMS APIs" introduces the various APIs introduced in each version of JMS. A new section 2.7. "Classic API interfaces" contains a diagram of the objects used in the "classic" (formerly "standard") API, and section 2.8. "Simplified API interfaces" contains a diagram of the objects used in the simplified API.





[JMS_SPEC-86] Chapter 1 "Introduction" is a little dated and requires rewriting Created: 12/Mar/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fr20-doc-added

 Description   

Chapter 1 "Introduction" of the JMS 1.1 specification (and the JMS 2.0 Early Draft) is a little dated (as would be expected given that it was written almost ten years ago). This would probably merit from rewriting.



 Comments   
Comment by Nigel Deakin [ 20/Mar/13 ]

Chapter 1 of the JMS 2.0 specification has been updated accordingly in time for the JMS 2.0 final release. The changes are summarised in this expert group email





[JMS_SPEC-93] Does changing the noLocal flag when connecting to a durable subscription cause the durable subscription to be deleted? Created: 30/Mar/12  Updated: 21/Sep/12  Resolved: 17/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks JMS_SPEC-40 Allow multiple consumers to be create... Resolved
Tags: pd20-added

 Description   

The JMS 1.1 specification, section 6.11.1 "Durable TopicSubscriber" states:

A client can change an existing durable subscription by creating a durable TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal attribute. Changing a durable subscription is equivalent to deleting and recreating it.

However the javadoc here for the Session method createDurableSubscriber(Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal) states that

A client can change an existing durable subscription by creating a durable TopicSubscriber with the same name and a new topic and/or message selector. Changing a durable subscriber is equivalent to unsubscribing (deleting) the old one and creating a new one.

The latter text uses an almost identical sentence but does not mention the effect of creating a durable subscriber with a different value of the noLocal flag.

This is contradictory and needs to be clarified. What is the effect if creating a durable subscriber with a different value of the noLocal flag than was used when the durable subscription was created?

I propose that we should interpret the javadoc as being correct and change the spec to match. The NoLocal flag determines whether messages sent using the connection that created the durable subscription should be added to it. Its significance ceases when the connection is closed. If the second call to createDurableSubscription uses a different connection then the value of noLocal that it specifies is completely independent of the previous value and does not render the durable subscription invalid. It is therefore not necessary to delete the durable subscription and create a new one.



 Comments   
Comment by Nigel Deakin [ 15/May/12 ]

When I logged this issue I think I was misunderstanding the meaning of the noLocal parameter. A clarified definition of this parameter is proposed in http://java.net/jira/browse/JMS_SPEC-65#action_339660 . This proposes we interpret noLocal as meaning "If noLocal is set to true, and the client identifier is set, then any messages published using this connection or any other with the same client identifier will not be added to the durable subscription."

In this case the value of noLocal remains a part of the definition of the durable subscription for the whole of its lifetime. This means that an attempt to activate the durable subscription using a different value of noLocal will invalidate the subscription, and so should cause the subscription to be deleted and recreated.

If the proposals in http://java.net/jira/browse/JMS_SPEC-65#action_339660 are approved then I propose that we resolve this issue by doing the opposite of what I first proposed, and to change the javadoc to match the specification.

Comment by Nigel Deakin [ 17/Sep/12 ]

Following the changes for JMS_SPEC-65, the API docs and spec have been clarified as follows:

If there are no active consumers on the durable subscription (and no consumed messages from that subscription are still part of a pending transaction or are not yet acknowledged in the session), and this method is used to create a new consumer on that durable subscription, specifying the same name and client identifier (if set) but a different topic or message selector, or, if the client identifier is set, a different noLocal value, then the durable subscription will be deleted and a new one created.

However if there is an active consumer on the durable subscription (or a consumed message from that subscription is still part of a pending transaction or is not yet acknowledged in the session), and an attempt is made to create an additional consumer, specifying the same name and client identifier (if set) but a different topic or message selector, or, if the client identifier is set, a different noLocal value, then a JMSException or JMSRuntimeException will be thrown.





[JMS_SPEC-94] Define what characters are valid in a durable (or shared subscription) name Created: 17/Apr/12  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0PD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-added

 Description   

The JMS 1.1 specification does not specify what characters are valid in a durable subscription name.

It is proposed that the JMS 2.0 specification defines a minimum set of characters which are valid in a durable or non-durable subscription name.

This is needed to allow portable applications to be created. It is also needed because EJB_SPEC-41 states that if a MDB is defined with subscriptionDurability set to Durable but subscriptionName is not set then the container will automatically set subscriptionName to a suitably unique global name of the MDB, and the container vendor needs to be sure that the name it generates will always be a legal subscription name.



 Comments   
Comment by Nigel Deakin [ 31/May/12 ]

In addition, the JMS 2.0 should specify the minimum length of durable subscription name that a JMS provider should support.

Comment by chris.barrow [ 06/Dec/12 ]

Issue JMS_SPEC-90 "Provide simpler mechanism to refer to queues and topics in a portable way" is related. Could we deal with that issue at the same time? It could easily be resolved by stipulating the same rules for queue and topic names as those proposed for durable subscription name (minimum set of characters and length that must be supported), as noted in a comment I added to that issue.

Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-115] Remove the statement that portable applications should only have one consumer per queue Created: 19/Feb/13  Updated: 20/Mar/13  Resolved: 25/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fd20-doc-added

 Description   

The JMS 1.1 specification, in section 4.4.9 "Multiple Sessions" states that

For PTP, JMS does not specify the semantics of concurrent QueueReceivers for
the same Queue; however, JMS does not prohibit a provider from supporting
this. Therefore, message delivery to multiple QueueReceivers will depend on the
JMS provider's implementation. Applications that depend on delivery to
multiple QueueReceivers are not portable

This means that a JMS provider is not required to support multiple consumers on the same queue, and that although JMS providers are allowed to do so, any application which depends on this is not portable.

I think that statement is obsolete now that all modern JMS providers allow multiple consumers on a queue. It is also anomalous now that JMS 2.0 requires shared subscriptions to allow multiple consumers.

It is therefore proposed that the section above be reworded to state that a queue may have multiple consumers, but that JMS does not define how messages from a queue are distributed amongst multiple consumers (i.e. there is no requirement for load-balancing etc).

Although JMS does not define how many concurrent consumers on a queue or shared subscription must be supported, providers are expected to support more than one consumer.



 Comments   
Comment by Nigel Deakin [ 25/Feb/13 ]

In the JMS 2.0 final draft, a new section 4.1.2 "Queue semantics" has been added. Significant text in bold:

When point-to-point messaging is being used, an application sends messages to a queue.

An application may consume messages from the queue by creating a consumer (a MessageConsumer, JMSConsumer or QueueReceiver object) on that queue. A consumer may be used to consume messages either synchronously or asynchronously.

A queue may have more than one consumer. Each message in the queue is delivered to only one consumer.

A consumer may be configured to use a message selector. In this case only messages whose properties match the message selector will be delivered to the consumer. Messages which are not selected remain on the queue or are delivered to another consumer.

The order in which an individual consumer receives messages is described in section 6.2.9 “Message order” below.
By definition, if a consumer uses a message selector, or there are other consumers on the same queue, then a consumer may not receive all the messages on the queue. However those messages that are delivered to the consumer will be delivered in the order defined in section 6.2.9.

Apart from the requirements of any message selectors, JMS does not define how messages are distributed between multiple consumers on the same queue.

A corresponding new section 4.2.2 "Topic semantics" has been added. Significant text in bold:

When pub/sub messaging is being used, an application sends messages to a topic.

An application consumes messages from a topic by creating a subscription on that topic, and creating a consumer (a MessageConsumer, JMSConsumer or TopicSubscriber object) on that subscription.

A subscription may be thought of as an entity within the JMS provider itself whereas a consumer is a JMS object within the application.

A subscription will receive a copy of every message that is sent to the topic after the subscription is created, except if a message selector is specified. If a message selector is specified then only those messages whose properties match the message selector will be added to the subscription.

Each copy of the message is treated as a completely separate message. Work done on one copy has no effect on any other; acknowledging one does not acknowledge any other; one message may be delivered immediately, while another waits for its consumer to process messages ahead of it.

Some subscriptions are restricted to a single consumer. In this case all the messages in the subscription are delivered to that consumer. Some subscriptions allow multiple consumers. In this case each message in the subscription is delivered to only one consumer. JMS does not define how messages are distributed between multiple consumers on the same subscription.

The order in which messages are delivered to a consumer is described in section 6.2.10 “Message order” below. By definition, if a subscription uses a message selector, or there are other consumers on the same subscription, then a consumer may not receive all the messages sent to the topic. However those messages that are delivered to the consumer will be delivered in the order defined in section 6.2.10.





[JMS_SPEC-114] Clarify javadoc descriptions of XAQueueConnection#createSession and XATopicSession#createSession Created: 14/Feb/13  Updated: 20/Mar/13  Resolved: 14/Feb/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0FD, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-fd20-doc-added

 Description   

In JMS 1.1 the javadoc description of Connection#createSession is "Creates an Session object...Returns: a Session object"
http://docs.oracle.com/javaee/6/api/javax/jms/XAConnection.html#createSession%28boolean,%20int%29

However the javadoc description of XAQueueConnection.html#createQueueSession is "Creates an XAQueueSession object...Returns: a newly created XAQueueSession"
http://docs.oracle.com/javaee/6/api/javax/jms/XAQueueConnection.html#createQueueSession%28boolean,%20int%29

and the javadoc description of XATopicConnection#createTopicSession is "Creates an XATopicSession object...Returns: a newly created XA topic session"
http://docs.oracle.com/javaee/6/api/javax/jms/XATopicConnection.html#createTopicSession%28boolean,%20int%29

The latter two descriptions are inconsistent with the return type. The fact that the first description is consistent with the return type confirms that this is a typo. They should be changed to be consistent with the return type declared in the method signature.

XAQueueConnection.html#createQueueSession should "return a QueueSession" and

XATopicConnection#createTopicSession should "return a TopicSession"



 Comments   
Comment by Nigel Deakin [ 14/Feb/13 ]

Now corrected at

http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/XAQueueConnection.html#createQueueSession%28boolean,%20int%29

http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/XATopicConnection.html#createTopicSession%28boolean,%20int%29





[JMS_SPEC-107] Extend connection consumer API to support shared durable and non-durable subscriptions Created: 06/Dec/12  Updated: 20/Mar/13  Resolved: 10/Dec/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 2.0PD
Fix Version/s: 2.0PD, 2.0

Type: New Feature Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks MQ-253 Extend connection consumer API to sup... Closed
Tags: pd20-added

 Description   

Now that JMS_SPEC-40 has added shared-durable and non-durable subscriptions to JMS, the connection consumer API needs to be extended to support them.

So in addition to the existing methods on Connection:

ConnectionConsumer createConnectionConsumer(
   Destination destination, String messageSelector, ServerSessionPool sessionPool, 
   int maxMessages)

(Queues or unshared non-durable topic subscriptions, clientId optional)

ConnectionConsumer createDurableConnectionConsumer(
   Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, 
   int maxMessages)

(Unshared durable topic subscriptions, clientId required)

we also need

ConnectionConsumer createSharedConnectionConsumer(
   Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, 
   int maxMessages)

(Shared non-durable topic subscriptions, clientId optional)

ConnectionConsumer createSharedDurableConnectionConsumer(
   Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, 
   int maxMessages)

(Shared durable topic subscriptions, clientId optional)



 Comments   
Comment by Nigel Deakin [ 06/Dec/12 ]

Here are the proposed new methods on Connection:

	/**
	 * Creates a connection consumer for this connection (optional operation)
	 * on the specific topic using a shared non-durable subscription with
	 * the specified name.
	 * <p>
	 * This is an expert facility not used by ordinary JMS clients.
	 * <p>
	 * This method must not be used in a Java EE web or EJB application. Doing
	 * so may cause a {@code JMSException} to be thrown though this is not
	 * guaranteed.
	 * 
	 * @param topic
	 *            the topic to access
	 * @param subscriptionName
	 *            the name used to identify the shared non-durable subscription
	 * @param messageSelector
	 *            only messages with properties matching the message selector
	 *            expression are delivered. A value of null or an empty string
	 *            indicates that there is no message selector for the message
	 *            consumer.
	 * @param sessionPool
	 *            the server session pool to associate with this connection
	 *            consumer
	 * @param maxMessages
	 *            the maximum number of messages that can be assigned to a
	 *            server session at one time
	 * 
	 * @return the connection consumer
	 * 
	 * @exception InvalidDestinationException
	 *                if an invalid destination is specified.
	 * @exception InvalidSelectorException
	 *                if the message selector is invalid.
	 * @exception JMSException
	 *                if the {@code Connection} object fails to create a
	 *                connection consumer for one of the following reasons:
	 *                <ul>
	 *                <li>an internal error has occurred 
	 *                <li>invalid arguments for {@code sessionPool} and 
	 *                {@code messageSelector} or 
	 *                <li>this method has been called in a Java EE web or EJB
	 *                application (though it is not guaranteed that an exception
	 *                is thrown in this case)
	 *                </ul>
	 * 
	 * @since 2.0
	 * @see javax.jms.ConnectionConsumer
	 */
	ConnectionConsumer createSharedConnectionConsumer(Topic topic,
			String subscriptionName,
			String messageSelector, ServerSessionPool sessionPool,
			int maxMessages) throws JMSException;
	/**
	 * Creates a connection consumer for this connection (optional operation)
	 * on the specific topic using a shared durable subscription with
	 * the specified name.
	 * <p>
	 * This is an expert facility not used by ordinary JMS clients.
	 * <p>
	 * This method must not be used in a Java EE web or EJB application. Doing
	 * so may cause a {@code JMSException} to be thrown though this is not
	 * guaranteed.
	 * 
	 * @param topic
	 *            topic to access
	 * @param subscriptionName
	 *            the name used to identify the shared durable subscription 
	 * @param messageSelector
	 *            only messages with properties matching the message selector
	 *            expression are delivered. A value of null or an empty string
	 *            indicates that there is no message selector for the message
	 *            consumer.
	 * @param sessionPool
	 *            the server session pool to associate with this durable
	 *            connection consumer
	 * @param maxMessages
	 *            the maximum number of messages that can be assigned to a
	 *            server session at one time
	 * 
	 * @return the durable connection consumer
	 * 
	 * @exception InvalidDestinationException
	 *                if an invalid destination is specified.
	 * @exception InvalidSelectorException
	 *                if the message selector is invalid.
	 * @exception JMSException
	 *                if the {@code Connection} object fails to create a
	 *                connection consumer for one of the following reasons:
	 *                <ul>
	 *                <li>an internal error has occurred 
	 *                <li>invalid arguments
	 *                for {@code sessionPool} and {@code messageSelector} or 
	 *                <li>this method has been called in a Java EE web or EJB
	 *                application (though it is not guaranteed that an exception
	 *                is thrown in this case)
	 *                </ul>
	 * @since 2.0
	 * @see javax.jms.ConnectionConsumer
	 */
	ConnectionConsumer createSharedDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector,
			ServerSessionPool sessionPool, int maxMessages) throws JMSException;




[JMS_SPEC-50] Clarify that JMS providers must implement both P2P and Pub-Sub Created: 19/Aug/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: ed20-added

 Description   

In the JMS Specification 1.1, Chapter 1.3 "What Is Required by JMS" says:

Providers of JMS point-to-point functionality are not required to provide publish/subscribe functionality and vice versa.

However Java EE 6 in Section EE.2.7.8 "Java™ Message Service (JMS)" says

The Java Message Service is a standard API for messaging that supports reliable point-to-point messaging as well as the publish-subscribe model. This specification requires a JMS provider that implements both point-to-point messaging as well as publish-subscribe messaging.

It is proposed to change the JMS specification to bring it in to line with Java EE, and make it mandatory for a standalone JMS provider to implement both point-to-point messaging (Queues) and publish-subscribe messaging (Topics).



 Comments   
Comment by Nigel Deakin [ 16/Sep/11 ]

This has been agreed in principle by the JSR 343 Expert group and will be in the JMS 2.0 Early Draft.

Comment by Nigel Deakin [ 03/Jan/12 ]

I've now updated the draft spec to reflect this decision (these changes are additive, so those docs include other changes).

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(All changes are highlighted clearly with changebars. The only sections affected are section 1.3 "What Is Required by JMS" and section 11.5.10 which is the change log for this issue.)





[JMS_SPEC-49] Improve specification of ExceptionListener Created: 16/Aug/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: ed20-added

 Description   

The use of a ExceptionListener is described in the JMS 1.1 specification in section 4.3.8 "ExceptionListener":

If a JMS provider detects a problem with a connection, it will inform the connection's ExceptionListener, if one has been registered. To retrieve an ExceptionListener, the JMS provider calls the connection's getExceptionListerer()
method. This method returns the ExceptionListener for the connection. If no ExceptionListener is registered, the value null is returned. The connection can then use the listener by calling the listener 's onException() method, passing it a JMSException describing the problem.

This allows a client to be asynchronously notified of a problem. Some connections only consume messages, so they would have no other way to learn their connection has failed.

A Connection serializes execution of its ExceptionListener.

A JMS provider should attempt to resolve connection problems itself prior to notifying the client of them.

The exceptions delivered to ExceptionListener are those that have no other place to be reported. If an exception is thrown on a JMS call it, by definition, must not be delivered to an ExceptionListener (in other words, ExceptionListener is not for the purpose of monitoring all exceptions thrown by a connection).

Despite this, there have been a number of questions about the use of an ExceptionListener. These questions are listed below, together with proposed answers. It is proposed that the answers to these questions be incorporated into the specification.

Question 1: When Connection.stop() or Connection.close() is called, must these methods wait until any active calls to ExceptionListeners for that connection have returned, in the same way that they must wait until any active call to MessageListeners have returned?

Proposed answer: No.

Question 2: Is there any restriction on the use of Connection.stop() or Connection.close() from an ExceptionListener?

Proposed answer: No.

Question 3: What does "a Connection serializes execution of its ExceptionListener" mean?

Proposed answer: This means that if a connection encounters multiple problems and therefore needs to call its ExceptionListener multiple times, then it will only invoke onMessage() from one thread at a time. Note however that if the same ExceptionListener is registered with different connections then it is undefined whether these connections could call onMessage() from different threads simultaneously.

Question 4: What is the effect of ExceptionListener.onException() being slow or blocking?

Proposed answer: This is undefined. There is no requirement that any other operation need block until ExceptionListener.onException() has return, apart from other calls to ExceptionListener.onException() for the same connection.



 Comments   
Comment by Nigel Deakin [ 16/Sep/11 ]

I've now written the following draft text:

Changes to section 4.3.8 "ExceptionListener":

After:

A Connection serializes execution of its ExceptionListener.

Insert:

This means that if a connection encounters multiple problems and therefore needs to call its ExceptionListener multiple times, then it will only invoke onMessage() from one thread at a time. Note however that if the same ExceptionListener is registered with multiple connections then it is undefined whether these connections could call onMessage() from different threads simultaneously.

At the end, insert:

There is no restriction on the use of the JMS API by the listener's onException method. However since that method will only be called when there is a serious problem with the connection, any attempt to use that connection may fail and cause exceptions.

New text in the javadoc for ExceptionListener:

There is no restriction on the use of the JMS API by the listener's onException method. However since that method will only be called when there is a serious problem with the connection, any attempt to use that connection may fail and cause exceptions.

A Connection serializes execution of its ExceptionListener. This means that if a connection encounters multiple problems and therefore needs to call its ExceptionListener multiple times, then it will only invoke onMessage from one thread at a time. Note however that if the same ExceptionListener is registered with multiple connections then it is undefined whether these connections could call onMessage from different threads simultaneously.

New text in the javadoc for Connection.stop():

For the avoidance of doubt, if an exception listener for this connection is running when stop is invoked, there is no requirement for the exception listener to return before the stop method returns.

New text in the javadoc for Connection.close():

For the avoidance of doubt, if an exception listener for this connection is running when stop is invoked, there is no requirement for the exception listener to return before the stop method returns.

Comment by Nigel Deakin [ 03/Jan/12 ]

I've now updated the javadocs and the draft spec with these clarifications (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar
(See updated javadocs for Connection.stop, Connection.close, Session.close, MessagingContext.stop, MessagingContext.close)

  • The javadoc comments for the stop and close methods on the Connection interface have been amended to clarify that, if an exception listener for the connection is running when stop or close are invoked, there is no requirement for the stop or close call to wait until the exception listener has returned before it may return.
  • Similarly, the javadoc comment for the close method on the Session interface has been amended to clarify that, if an exception listener for the session's connection is running when close is invoked, there is no requirement for the close call to wait until the exception listener has returned before it may return.
  • The javadoc comments for the stop and close methods on the MessagingContext interface have been amended to clarify that, if an exception listener for the MessagingContext's connection is running when stop or close are invoked, there is no requirement for the stop or close call to wait until the exception listener has returned before it may return.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
All changes are highlighted clearly with changebars.

The changes for this issue are to section 4.3.8 "Exception Listener":

  • The existing text which states that a connection "serializes execution of its ExceptionListener" has been extended to explain what this means.
  • A note has been added to state that there are no restrictions on the use of the JMS API by the listener's onException method.

In addition a new section 11.5.11 has been added which is the change log for this issue.





[JMS_SPEC-48] Specify that connection.stop() or close() may not be called from a MessageListener Created: 16/Aug/11  Updated: 20/Mar/13  Resolved: 20/Mar/13

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: None
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: ed20-added

 Description   

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.



 Comments   
Comment by Nigel Deakin [ 16/Sep/11 ]

I've now drafted the spec changes as follows:

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.

Comment by Nigel Deakin [ 04/Jan/12 ]

I've now updated the javadocs and the draft spec
(these changes are additive, so those docs include other changes).

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(all changes are highlighted clearly with changebars)

Section 4.3.4 "Pausing Delivery of Incoming Messages"

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.

Section 4.3.5 "Closing a Connection"

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.

Section 4.4.1 "Closing a Session"

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.

Section 11.5.12 "Clarification of use of stop or close from a message listener (JMS_SPEC-48)"

This is the change log for this issue.

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

New javadoc comment on Connection.stop():

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

New javadoc comment on Connection.close():

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

New javadoc comment on Session.close():

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

New javadoc comment on MessagingContext.stop():

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

New javadoc comment on MessagingContext.close():

     * A message listener must not attempt to close its own MessagingContext as this 
     * would lead to deadlock. The JMS provider must detect this and throw a 
     * javax.jms.IllegalStateRuntimeException.
Comment by Nigel Deakin [ 05/Dec/12 ]

I'd like to reopen this issue. Since the changes described above was added to the spec it has been pointed out that a similar issue applies with the close() methods on MessageConsumer and JMSConsumer.

I would therefore like to propose that we amend the definition of MessageConsumer.close() and JMSConsumer.close() to match the other methods listed here.

Comment by Nigel Deakin [ 05/Dec/12 ]

I've now drafted the necessary API changes:

New javadoc comment on MessageConsumer.close():

	 * This call blocks until a {@code receive} or message listener in progress
	 * has completed. A blocked message consumer {@code receive} call returns
	 * null when this message consumer is closed.
	 * <p>
	 * A {@code MessageListener} must not attempt to close its own
	 * {@code MessageConsumer} as this would lead to deadlock. The JMS provider
	 * must detect this and throw a {@code IllegalStateException}.
	 * 
	 * @exception IllegalStateException
	 *                this method has been called by a {@code MessageListener}
	 *                on its own {@code MessageConsumer}

Note that the words "this call blocks until a... message listener in progress has completed" are not new and were in JMS 1.1.

New javadoc comment on JMSConsumer.close()

	 * This call blocks until a {@code receive} or message listener in progress has completed.
	 * A blocked {@code receive} call returns null when
	 * this {@code JMSConsumer} is closed.
	 * <p>
	 * A {@code MessageListener} must not attempt to close its own
	 * {@code JMSConsumer} as this would lead to deadlock. The JMS provider
	 * must detect this and throw a {@code IllegalStateRuntimeException}.
	 * 
 	 * @exception IllegalStateRuntimeException
	 *                this method has been called by a {@code MessageListener}
	 *                on its own {@code JMSConsumer}

In addition I've added a new section 4.5.3 "Closing a MessageConsumer"

When the MessageConsumer's close method 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.

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

Comment by Nigel Deakin [ 12/Feb/13 ]

The JMS EG has agreed to revise the behaviour of consumer close to:

  • Allow consumer.close to be called from within a message listener
  • Allowing a consumer to be closed from any thread, even if it isn't the thread of control

The main changes are listed below.

New Javadoc for MessageConsumer.close

/**
 * Closes the message consumer.
 * <p>
 * Since a provider may allocate some resources on behalf of a
 * {@code MessageConsumer} outside the Java virtual machine, clients should
 * close them when they are not needed. Relying on garbage collection to
 * eventually reclaim these resources may not be timely enough.
 * <P>
 * This call will block until a {@code receive} call in progress on this
 * consumer has completed. A blocked {@code receive} call returns null when
 * this message consumer is closed.
 * <p>
 * If this method is called whilst a message listener is in progress in
 * another thread then it will block until the message listener has
 * completed.
 * <p>
 * This method may be called from a message listener's {@code onMessage}
 * method on its own consumer. After this method returns the
 * {@code onMessage} method will be allowed to complete normally. 
 * <p>
 * This method is the only {@code MessageConsumer} method that can be called
 * concurrently.
 * 
 * @exception JMSException
 *                if the JMS provider fails to close the consumer due to
 *                some internal error.
 */

Spec changes: new section 8.8. Closing a consumer

8.8. Closing a consumer

The close methods on MessageConsumer, JMSConsumer, QueueReceiver and TopicSubscriber allow a consumer to be closed separately from the session or connection used to create it.

Closing a consumer terminates the delivery of messages to the consumer.

close is the only method on a consumer that may be invoked from a thread of control separate from the one which is currently controlling the session.

If close is called in one thread whilst another thread is calling receive on the same consumer then the call to close must block until the receive call has completed. A blocked receive call returns null when the consumer is closed.

If close is called in one thread whilst a message listener for this consumer is in progress in another thread then the call to close must block until the message listener has completed.

If close is called from a message listener's onMessage method on its own consumer then after this method returns the onMessage method must be allowed to complete normally.

Closing a consumer has no effect on the acknowledgement of messages delivered to the application, or on any transaction in progress. This is because message acknowledgement and transactions are functions of the session, not the consumer.

  • If the session mode is AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE then any messages delivered to the application will be automatically acknowledged as normal.
  • If the session mode is CLIENT_ACKNOWLEDGE then any messages delivered to the application may be acknowledged by calling acknowledge in the normal way. It makes no difference whether this occurs before or after the consumer is closed.
  • If the session is transacted then the application may commit or rollback the transaction as normal. It makes no difference whether this occurs before or after the consumer is closed.
Comment by Nigel Deakin [ 20/Mar/13 ]

This issue is resolved in the JMS 2.0 final release. Marking issue as resolved with a "fix version" of 2.0





[JMS_SPEC-34] Calling setJMSDeliveryMode or setJMSPriority on a javax.jms.Message before it is sent don't have any effect Created: 25/Jul/11  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec
Component/s: None
Affects Version/s: 1.1
Fix Version/s: 2.0ED, 2.0

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Nigel Deakin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JMS_SPEC-60 Obscurity setting special JMSHeaders Closed
Tags: ed20-added

 Description   

This issue relates to the following methods on javax.jms.Message:

setJMSPriority
setJMSDeliveryMode

Many novice developers think these methods can be used to set the priority and delivery mode of a message before it is sent. In fact these methods have no effect: the only way to set priority and delivery mode is by using methods on javax.jms.MessageProducer.

This a common cause of confusion to developers. Can we either deprecate these methods or else change them so that actually do something?



 Comments   
Comment by Nigel Deakin [ 25/Jul/11 ]

The same issue applies to the following methods on javax.jms.Message as well:

setJMSDeliveryMode
setJMSExpiration
setJMSPriority
setJMSMessageID
setJMSTimestamp
setJMSRedelivered
setJMSDeliveryTime (proposed in JMS_SPEC-44)

If any of these methods are called on a message before it is sent they have no effect. The javadoc comment on each of these methods states "This method can be used to change the value for a message that has been received.", despite it being far from obvious why an application might want to do this.

Comment by Nigel Deakin [ 22/Nov/11 ]

These methods are needed because a JMS provider is required to be capable of sending messages whose implementation is not its own. This would typically occur if an application received a message from provider 1 and then sent the same message using provider 2.

When this happens, provider 2 is responsible for setting the JMSDestination, JMSDeliveryMode, JMSExpiration, JMSPriority, JMSMessageID and JMSTimestamp header field values on the message. The only way that provider 2 can set these values on a message implemented by provider 1 is using these public setter methods.

Here's an example: if the application sends a message with a priority of 3 then it does this either by setting the priority on the MessageProducer by calling its setPriority method prior to sending the message, or by setting the priority on the individual message send by calling the MessageProducer method send(destination, message, deliveryMode, priority, timeToLive). The provider is responsible for ensuring that, after the message has been sent, the message's JMSPriority header holds the appropriate priority so that the line of code following the call to send could obtain this value. (See section 3.4.10 of the JMS 1.1 spec).

// message1 was obtained from provider 1
// we're sending it using provider 2
messageConsumer.setPriority(3);
messageConsumer.send(message1);
int priority = message1.getJMSPriority(); // should return 3

In the above example, provider 2's send method needs to be able to set the JMSPriority header on message1, which was implemented by provider 1, so it needs a standard, public API to do this.

We therefore cannot remove these methods. It would, however, be possible to clarify the javadoc comments to make it clear that these methods cannot be used by the sending application to control the message priority, delivery mode. We will improve the wording in JMS 2.0.

I suspect that some people who fall into the trap of misunderstanding these methods simply guess the method name, see that it gets accepted by their IDE, and use it. There's not much we can do about this (though since most IDEs can display javadoc comments clarifying the javadoc may help).

Comment by koen.serneels [ 23/Nov/11 ]

My opinion is still that it should always be the goal of a good API to minimize the percentage of obscurity.
By offering methods in a public API that do nothing, you are creating confusion from the start.

Can't there be a Message SPI or some other way that the provider can set the priority before sending? Imho this is just bad design which leads to errornous code and time consuming debegugging to find out "why this setter method doesn't work" ?.

Comment by Nigel Deakin [ 23/Nov/11 ]

@koen.serneels: You're perfectly right, the existence of these methods is misleading and with hindsight the people who designed this API should have done something different. But removing them would be a non-compatible change so I think we're stuck with them.

Comment by Nigel Deakin [ 22/Dec/11 ]

I've now updated the javadocs and the draft spec with details of this new feature (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar

The javadoc comments for the following methods on Message have been updated:

setJMSDeliveryMode
setJMSExpiration
setJMSPriority
setJMSMessageID
setJMSTimestamp
setJMSRedelivered
setJMSDeliveryTime (proposed in JMS_SPEC-44)

Currently the javadoc comments for these methods simply states:

    /** Sets the message's [name of property] value
      *  
      * <P>JMS providers set this field when a message is sent. This method
      * can be used to change the value for a message that has been received.

These have been changed as follows:

   /** Sets the message's [name of property] value.
     *
     * <P>This method is for use by JMS providers only to set this field 
     * when a message is sent. This message cannot be used by clients 
     * to configure the [describe feature] of the message. This method is public
     * to allow one JMS provider to set this field when sending a message
     * whose implementation is not its own.

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(all changes are highlighted clearly with changebars. The changes for this issue are as follows:

Section 3.4.1 "How Message Header Values Are Set" has been updated.

Section 11.5.8. "Clarification: message headers that are intended to be set by the JMS provder" is the change log for this issue.

Comment by Nigel Deakin [ 23/Feb/12 ]

Clarified the explanation in the second comment .





[JMS_SPEC-31] change javadoc on session.createQueue and createTopic to make clearer the provider may create a physical destination Created: 15/Jul/11  Updated: 20/Mar/13  Resolved: 21/Sep/12

Status: Resolved
Project: jms-spec