[JMS_SPEC-178] MESSAGE_ACKNOWLEDGE session mode Created: 25/Apr/16  Updated: 25/Apr/16

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

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


 Description   

An addition of MESSAGE_ACKNOWLEDGE session mode would allow for consumers to acknowledge an individual message, as apposed to acknowledging all previous messages received by the session.

This is useful in scenarios where sessions may be shared across processing threads (example: ESB, or other lightweight integration framework), but message processing is non-linear.



 Comments   
Comment by mattrpav [ 25/Apr/16 ]

Apologies for the dup. See: JMS_SPEC-95





[JMS_SPEC-177] Last Will message support Created: 25/Apr/16  Updated: 25/Apr/16

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

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


 Description   

MQTTv3 has a "Last Will" feature that JMS users would also benefit from. A developer registers a "Last Will" message when connecting to the server and when the connection is disconnected (intentionally, or unintentionally) the broker delivers the Last Will message to a destination that is defined during the session setup. This allows application developers and administrators to implement automated handling of error conditions without the need for a number of 3rd party or provider-specific tools.

The one improvement on the MQTT implementation would be to support a closing of the session without delivering the Last Will message, so you could support a scenario where the Last Will message is only delivered for unplanned disconnects.

API additions:

JMSContext.createLastWill(Destination dest, Message msg)
JMSContext.close(boolean doNotDeliverLastWill) // default to true  





[JMS_SPEC-176] Allow message acknowledgment outside of the message delivery thread Created: 16/Oct/15  Updated: 11/Nov/15

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

Type: New Feature Priority: Major
Reporter: chris.barrow Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-95 Individual message acknowledge mode Open

 Description   

Several vendors currently support individual message acknowledgment outside of message listeners, that is, on a thread other than the thread of control of the Session. This is useful for certain types of application, for example, the asynchronous processing of queue or durable topic subscriber messages (for which individual message acknowledgment would also be useful, see JMS_SPEC-95).

The fact that several vendors already support this usage demonstrates the value of this feature.

It is therefore proposed to alter the JMS specification to explicitly allow message acknowledgment from a thread other than the message delivery thread of the Session that runs the MessageListeners. Currently the only Session-related methods which are allowed to be called outside of the thread of control of the Session are Session.close and Consumer.close (JMS 2.0 spec section 6.5). The proposed enhancement would add the Message.acknowledge method to this list when individual message acknowledge mode is being used (see JMS_SPEC-95).



 Comments   
Comment by chris.barrow [ 22/Oct/15 ]

Here's a comment from Tom Barnes (email 22-Oct-15):

It looks like there’s at least one race condition to consider for JMS_SPEC-176: With classic CLIENT_ACKNOWLEDGE, a non-onMessage-thread msg.acknowledge() call could unintentionally acknowledge a message that happens to arrive in the onMessage callback after the message being acknowledged. This is due to the spec requirement taht an ack() call must ack all of a session’s received messages - even those received after the message being acknowledged. I think this means that the proposed multi-threading supported should be limited to the proposed new ‘ack this message’ and ‘ack up to this message’ APIs.

Comment by chris.barrow [ 22/Oct/15 ]

I have amended the issue description in view of the above comment.

Comment by chris.barrow [ 29/Oct/15 ]

Notes from an email discussion with Nigel Deakin
(Nigel)
If you need to be able to receive a message using a MessageListener but acknowledge it in a different thread, then does this mean you want to call other methods on the Message object (e.g. getting the message body, headers etc) in the other thread?
(Chris)
For our use case we do not need to call other methods on the Message object in the other thread. What we are doing is writing the message in an encoded form onto a WebSocket connection so that a client can process it and reply with an ACK frame which is then used to acknowledge the message outside of the message listener. Basically we are extending JMS to work on web clients via WebSocket. I think this is an interesting use case with other people may want to do (or may even already be doing), and this sort of usage could add value to JMS. I did give a presentation on this architecture with a colleague at JavaOne back in 2011. But the feature could apply to any sort of asynchronous processing of messages that need to be acknowledged.
(Nigel)
Right. So it really is just the ack that's in a different thread.
However I think that once we allow individual acks, and allow messages to be acked in a thread other than the listener thread, users will also want to do more of the message processing in a different thread as well. (Though some people may want to argue this is allowed anyway anyway).

Comment by clebertsuconic [ 29/Oct/15 ]

I'm also a bit concerned about this... it breaks the Session = Thread contract defined by the Spec. It will require extra synchronizations to make such thing happen and vendors who optimized performance on client.ack will be affected by this.

If you synchronize everything is fine.. but if you favour high performance.. this can be affected as it clashes with the spec as mentioned by Tom Barnes.

Comment by chris.barrow [ 11/Nov/15 ]

I would think it should be possible to implement this without use of synchronization. For example, if the session message dispatcher thread is driven by a blocking input event (incoming message) queue, it should be possible just to post the acknowledge request onto that queue so it gets executed by the same thread that is delivering the messages. That would then be equivalent to current usage where message.acknowledge() is always called from a message listener.





[JMS_SPEC-175] Fix javadocs to remove need to disable doclint Created: 07/Sep/15  Updated: 07/Sep/15

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

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


 Description   

The JMS 2.0 javadocs cannot be built using Java 8. This is because the Java 8 version of javadoc runs doclint which fails with multiple errors.

The JMS 2.1 javadocs (and API jar) need to be built with Java 8 because they have a dependence on java.lang.annotation.Repeatable which was added in Java 8.

I have temporarily disabled doclint by modifying jms2.1/pom.xml as follows. This allows the javadocs to be built using Java 8.

  <properties>
    <additionalparam>-Xdoclint:none</additionalparam>
  </properties>  

However a better solution for JMS 2.1 is to fix the various bugs in the javadocs so that doclint can be reinstated.






[JMS_SPEC-174] Define a standard way to specify the resource adapter used by a JMS MDB Created: 30/Jun/15  Updated: 03/Jul/15

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

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

Issue Links:
Dependency
depends on EJB_SPEC-127 Define a standard way to specify the ... Open
Tags: jms21-forreview-major

 Description   

The EJB 3.2 specification does not define a standard way to associate a JMS MDB (or any other type of MDB) with a resource adapter. Instead, if the application requires that a particular resource adapter be used, and the application server does not use it by default, then the application must specify this in the app-server-specific deployment descriptor (e.g. glassfish-ejb-jar.xml.

It is therefore proposed that a standard way is defined to associate a JMS MDB (or any other type of MDB) with a resource adapter, using either ejb-jar.xml or the MessageDriven annotation.

This will require a change to the EJB specification, not JMS, and is logged here for tracking purposes. The EJB spec issue is EJB_SPEC-127.






[JMS_SPEC-173] Javadocs for JMSContext#start should mention that it is usually called automatically Created: 11/Jun/15  Updated: 11/Jun/15

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

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

Tags: jms21-forreview-minor

 Description   

The javadocs for JMSContext#start could be improved by mentioning that it is not normally necessary for applications to call this method, since the the underlying connection used by the JMSContext will be started automatically when a consumer is created.

The javadocs for JMSContext#createConsumer, JMSContext#createSharedConsumer and JMSContext#createSharedDurableConsumer should also mention this.






[JMS_SPEC-172] Resource adapter: define standard destination and connection factory properties Created: 19/May/15  Updated: 19/May/15

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

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


 Description   

The resource definition annotation @JMSDestinationDefinition (and the corresponding deployment descriptor element) defines the attributes className, description, properties and resourceAdapter.
https://jms-spec.java.net/2.0/apidocs/javax/jms/JMSDestinationDefinition.html

The resource definition annotation @JMSConnectionFactoryDefinition (and the corresponding deployment descriptor element) defines the attributes className, clientId, description, interfaceName, maxPoolSize, minPoolSize, password, properties, resourceAdapter, transactional and user.
https://jms-spec.java.net/2.0/apidocs/javax/jms/JMSConnectionFactoryDefinition.html

if the resource being defined is provided by the application server's built-in JMS provider then the application server will know how to set these properties (and which of them are supported).

However if the resource being defined is provided by a resource adapter then the application server has no way of knowing what to do with several of these properties. This is because there are no standards for the properties supported by resource adapter destination and connection factory objects.

To address this, it is proposed to extend chapter 13 "Resource Adapter" of the JMS 2.0 specification. Currently section 13.1 defines a recommended set of activation properties. It is proposed to add two new sections which define a recommended set of connection factory properties and a recommended set of destination properties.

Note that this proposal applies to resource adapters only, and since the provision of a resource adapter is optional, it will be optional for JMS providers to support these properties.

A minimal set of properties is proposed initially, corresponding to those defined in the resource definitions above:

Recommended ManagedConnectionFactory properties

@JMSConnectionFactory attribute ManagedConnectionFactory property Description
clientId clientId Client id to use for connection
description description Description of this JMS connection factory
user user User name to use for connection authentication
password password Password to use for connection authentication

Recommended Queue and Topic properties

@JMSDestinationDefinition attribute Queue and Topic property Description
description description Description of this JMS connection factory
destinationName destinationName Name of the queue or topic

To avoid possible name clashes with existing JMS resource adapters, it may be desirable to prefix these properties with (say) "JMS"

How are these properties set?

Since this proposal applies only to resource adapter objects the API for setting these properties is already defined by the JCA specification, which is to use javabean setter methods such as setUser.

(For this reason there is no need to define a standard way for the application server to set the properties defined in the properties attribute).






[JMS_SPEC-171] Typo in javadoc for JMSDestinationDefinition Created: 14/May/15  Updated: 14/May/15

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

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

Tags: jms21doc-minor

 Description   

In the Javadocs for JMSDestinationDefinition.html#properties the description is

JMS destination property. This may be a vendor-specific property or a less commonly used ConnectionFactory property.

This needs to be changed to

JMS destination property. This may be a vendor-specific property or a less commonly used destination property.






[JMS_SPEC-170] Discrepancy between spec and test suite re JMSMessageID during pub/sub Created: 18/Mar/15  Updated: 18/Mar/15

Status: Open
Project: jms-spec
Component/s: None
Affects Version/s: 1.0, 1.0.1, 1.0.2, 1.0.2b, 1.1, 2.0ED, 2.0PD, 2.0FD, 2.0
Fix Version/s: None

Type: Improvement Priority: Minor
Reporter: tdotrob Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

All.



 Description   

While the specification appears to require that the JMSMessageID should be preserved from the time it is generated during a publish until the time it is consumed from a subscribe, the test suite does not check for this condition.

I am intentionally avoiding a claim that the spec is ambiguous on this matter after discussion it with Nigel on Twitter and Stack Overflow. However, the IBM MQ JMS implementation (and perhaps others I'm unfamiliar with) changes the JMSMessageID between the publish and the subscribe and this is contrary to the intent of the specification, I am told.

The issue I am trying to resolve here is not IBM's implementation but rather the combination of the wording in the spec and test suite implementation that allows seasoned practitioners in the field to arrive at completely opposed interpretations of the spec on something so foundational as the JMSMessageID and both believe strongly that theirinterp[retation is correct.

Some specific issues that give rise to this include:

The word 'provider' is used both to mean the transport and the thing sending messages. The spec switches between these contexts without qualifying which is intended. This impacts the scope to which statements about atomicity of the message may apply.

The spec does not clearly distinguish between identical but separate physical copies of the same logical message versus distinct and unique logical messages. For example, the spec says that...

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.

IBM has advanced the theory that "the copies of the message created when sending to a Topic can be considered as completely separate messages." Based on this and the absence of a test in the reference suite to check whether the JMSMessageID has been preserved across a publish and subscribe, they conclude that "Because separate JMS messages are uniquely identified by their JMSMessageID field, each separate subscription message should have a different JMSMessageID."

Nigel advances a slightly different theory:

Each message sent to a topic is delivered to every subscriber on that topic. These subscribers will receive a separate copy of the same message, with the same body, properties and headers, including JMSMessageID value.

My argument is that if the specification was sufficiently clear, then the interpretations arrived at by an authoritative member of the spec team and a representative member of the JMS Experts group would be at least somewhat compatible. In this case, two advanced practitioners are not only diametrically opposed in their interpretation, but both adamant about the correctness of their positions. I would think either a clarification of the spec or a cage match is called for. I'd pay to see either but would prefer the clarification.

Finally, Nigel notes that after so much time and with large bodies of deployed code, it might not be worth amending the spec. If that is true, then at least a non-binding clarification would point implementers consistently in the right direction so that discrepancies in implementations can be addressed through attrition, if no other way.






[JMS_SPEC-169] Vendor-defined acknowledgement modes Created: 27/Feb/15  Updated: 14/Oct/15

Status: Open
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: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-95 Individual message acknowledge mode Open
is related to JMS_SPEC-168 No-acknowledge mode Open
Tags: jms21-forreview-minor

 Description   

Several vendors currently support non-standard acknowledgement modes as vendor-specific extensions.

(Edited) The most common vendor-specific modes are no-acknowledgement mode (see JMS_SPEC-168 and JMS_SPEC-21) and individual-acknowledge mode (see JMS_SPEC-95), and these are already proposed for standardization.

However individual vendors may wish to offer additional acknowledgement modes which are probably too vendor-specific to be suitable for incorporating in the standard.

Currently the JMS specification does not allow createSession and createContext to support modes other than the four defined in the specification. It is proposed to relax this restriction to allow vendors to define additional modes, so long as their integer value is within a special defined range.

Applications which use such vendor-specific modes will, inevitably, not be portable.

The specification for Session#getAcknowledgementMode and JMSContext#getSessionMode would need to be extended to cover this new feature.

One drawback of defining an integer range for vendor-specific modes is the possibility that two vendors may choose the same value. One way to avoid this would be to define new createContext and createSession methods which allow the session/acknowledgement mode to be specified as a string. JMS-defined modes would start with javax.jms, vendor-defined modes would start with a vendor-specific string such as com.vendorname.



 Comments   
Comment by chris.barrow [ 02/Mar/15 ]

An integer range for vendors combined with a registry to avoid collisions might be a good way to go. It would avoid increasing the complexity of the API and also be a useful source of possible modes we might want to add to the standard going forward.

Comment by clebertsuconic [ 03/Mar/15 ]

wouldn't be better to add two pre-defined integers such as NO_ACK and individual_ack and let it be optionally implemented?

Comment by chris.barrow [ 03/Mar/15 ]

That's a possibility, but if we do that we should provide a means of knowing if they are supported.

Comment by Nigel Deakin [ 03/Mar/15 ]

This proposal is intended to cater for "additional acknowledgement modes which are probably too vendor-specific to be suitable for incorporating in the standard.". A search through vendor documentation suggests that a number of other modes are in use.

One of the reasons for proposing this is to provide a way for vendors to support such modes whilst still conforming to the JMS specification.

I'm not enthusiastic about adding more createSession and createContext methods, but this would offer a self-managing mechanism for avoiding collisions between vendors. Managing a registry of vendor-defined integer acknowledgement modes sounds like an administrative burden for someone. (Are there any precedents for it in JCP specifications?).

Of course we could decide that avoiding such collisions was not necessary, since each vendor would doubtlessly define their own static constants, and applications which used them would not compile if a different vendor was used.

Comment by Nigel Deakin [ 06/Mar/15 ]

Comment received from Matthew White:

I like the idea of the No and message specific ack modes; we've had requests for customers for these. In our experience we've found that some developers don't realise that they have started to use vendor specific extensions. Or don't full realise the impact. Having potential overlapping integer values therefore I would be wary off. Strings possibly might be better here.

An alternative could be to have the extra no/message ack modes, but a vendor specific ackmode, and a separate way of passing the vendor specific info (setVendorInfo(...)) that way application writers are forced to know they have stepped outside the spec.

Indeed what over types of ack mode could be considered? May it be worth considering more of these for the spec.

Comment by clebertsuconic [ 06/Mar/15 ]

We already use that integer for vendor specific modes right now even thought that is "not supported".

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

Good point. Perhaps all we need to do is reserve a range of acknowledgeMode values for use by the JMS specification, like 1 to 20, i.e. require that vendor specific modes not use those values. This is a common future proofing technique used in many specs, for example RFC 6455 (WebSocket).
Here some examples of values being used:

  • Tibco EMS:
    public static final int NO_ACKNOWLEDGE = 22;
    public static final int EXPLICIT_CLIENT_ACKNOWLEDGE = 23;
    public static final int EXPLICIT_CLIENT_DUPS_OK_ACKNOWLEDGE = 24;
  • ActiveMQ:
    public static final int INDIVIDUAL_ACKNOWLEDGE = 4;
  • HornetMQ:
    public static final int INDIVIDUAL_ACKNOWLEDGE = 101;

If we reserve 1 through 20 then only ActiveMQ of the above list would be impacted, and that would be mitigated if we implement JMS
_SPEC-95 and make the new CLIENT_INDIVIDUAL_ACKNOWLEDGE mode have value 4 (which would be theexpected value to choose since JMS 1.1 and 2.0 only use values 1 through 3).

Comment by Nigel Deakin [ 16/Mar/15 ]
  • Weblogic JMS supports
    static final int NO_ACKNOWLEDGE = 4
    static final int MULTICAST_NO_ACKNOWLEDGE = 128
Comment by Nigel Deakin [ 16/Mar/15 ]

The simplest approach would indeed to be to reserve a range (e.g. 0-20) for JMS-defined modes. We would also need to amend the spec to explicitly allow vendor-defined modes, so long as they are outside the reserved range.

(Edited) Note that we have separate proposals to standardize "no-ack" mode: (JMS_SPEC-168 and JMS_SPEC-21) and "individual-ack" mode (JMS_SPEC-95). When choosing values for those modes we would probably want to try to avoid values which we know are already in use, though we couldn't guarantee this. Even though the spec is entitled to choose any values it wants, we don't want to place obstacles in the way of vendors adopting JMS 2.1 if we can avoid them.





[JMS_SPEC-168] No-acknowledge mode Created: 27/Feb/15  Updated: 14/Oct/15

Status: Open
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: Unresolved Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-21 Support for pre-acknowledge ack mode Open
is related to JMS_SPEC-95 Individual message acknowledge mode Open
is related to JMS_SPEC-169 Vendor-defined acknowledgement modes Open
Tags: jms21-forreview-minor

 Description   

Several vendors currently support a special acknowledgement mode in which messages are deleted from the topic subscription or queue as soon as they are sent, without waiting for an acknowledgement of any kind to be sent by the client.

Most of these vendors call this "no-acknowledge mode", though the terms "pre-acknowledge mode" and "explicit-client-acknowledge" are also used.

The fact that several vendors already support this mode as a non-JMS extension demonstrates the value of this feature.

It is therefore proposed to add it to the JMS specification as an additional acknowledgement mode.

In the simplified API, a new session mode JMSContext.NO_ACKNOWLEDGE will be defined, and the createContext methods will be extended to support it (as a mandatory feature).

In the classic API, a new acknowledgement mode JMSSession.NO_ACKNOWLEDGE will be defined, and the createSession methods will be extended to support it (as a mandatory feature).

This mode will be available in both Java SE and Java EE applications in all cases where a local or JTA transaction is not used.

The specification for Session#getAcknowledgementMode and JMSContext#getSessionMode would need to be extended to cover this new feature.



 Comments   
Comment by gemmellr [ 14/Oct/15 ]

This appears to supplant JMS_SPEC-21 (or duplicate it), which is referenced in JMS_SPEC-169 comments despite the Issue Link to here.

Comment by Nigel Deakin [ 14/Oct/15 ]

Yes, this seems to be a duplicate of JMS_SPEC-21 (Support for pre-acknowledge ack mode). We have three closely-related JIRA issues here, so I'll update the cross-references. I'll leave all the issues open for now until we discuss them for JMS 2.1.

Comment by gemmellr [ 14/Oct/15 ]

Great. I should probably have added that I think this would be a useful addition, such an acknowledge mode would be useful for JMS clients using AMQP as their underlying protocol as sending messages to a peer without further confirmation/acknowledgement is one of the protocols supported modes.





[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-166] Define that the JMS provider should call reset on a StreamMessage passed to a CompletionListener Created: 12/Jan/15  Updated: 12/Jan/15

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

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

Issue Links:
Related
is related to JMS_SPEC-125 Define whether a JMS provider should ... Closed

 Description   

JMS_SPEC-125 proposes that when a BytesMessage is sent asynchronously, the provider must call reset on the BytesMessage passed to the CompletionListener,

This issue proposes making the same change to StreamMessage, for exactly the same reasons. These reasons are discussed in JMS_SPEC-125.



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

Proposed changes

In the javadoc for StreamMessage, 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 StreamMessage is sent asynchronously, the provider must call reset on the StreamMessage passed to the CompletionListener. This means that the CompletionListener can read the message body without needing to call reset.





[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-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-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-159] Allow stop and close to be called from a message listener Created: 22/Sep/14  Updated: 23/Sep/14

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

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

Issue Links:
Dependency
depends on JMS_SPEC-158 JMS 2.0 introduced incompatible chang... Closed
Tags: jms21-forreview-minor

 Description   

In JMS 2.0, an application which calls JMSContext stop, JMSContext close , Connection stop, Connection close or Session close from a message listener on its own JMSContext, Connection or Session is required to throw a javax.jms.IllegalStateException.

JMS_SPEC-158 proposes a JMS 2.0 errata which would make it optional for JMS vendors to throw an exception and allow these methods to return normally instead. (See that issue for details).

However that would mean that applications which relied on being able to call these methods from a message listener would not be portable.

Assuming JMS_SPEC-158 is accepted, it is proposed that in a later version of JMS the required behaviour for these methods be changed to make it match the new behaviour of MessageListener close. The option of throwing an exception would be removed and these methods would be required to return normally.

Such no working application would be dependent on an exception being thrown, such a change would not be incompatible, whilst those applications which rely on being able to call these methods from a message listener would then become portable.



 Comments   
Comment by chris.barrow [ 22/Sep/14 ]

I would vote for this to be part of JMS 2.1. It's a much better solution than making the exceptions optional (JMS_SPEC-158). It should be easy for vendors to implement (just set a flag to invoke the method after the message listener completes).

Comment by Nigel Deakin [ 23/Sep/14 ]

There are quite a few details that would need to be defined. Closing a connection (say) does multiple things.

  • It blocks until (other) message listener callbacks have returned.
  • It blocks until any incomplete completion listener callbacks have returned.
  • It rolls back local transactions in this and other sessions.
  • It causes any subsequent use of the connection object to throw an exception, both in this and in other threads.

There are probably other things as well. Which of these would take place when close was called, and which would be deferred until after the message listener has returned?

In addition, if the message listener is using auto-ack, and the message listener closes the connection or session, then is the message automatically-acknowledged or not?

The purpose of JMS_SPEC-158 (the other issue) is to fix JMS 2.0 so that it doesn't force an incompatible change on JMS 1.1 vendors which long ago took the decision to allow stop or close to be called without causing deadlock. That issue is deliberately simple to allow it to be handled as a JMS 2.0 errata.

This issue is intended to be a longer-term solution which replaces that "optional" behaviour with some more specific required behaviour and so achieves application portability. Since it would require changes to the RI, CTS etc it can't be done in an errata and so is suggested for 2.1.

In both cases we will need to be careful to avoid introducing further incompatible changes on such vendors.





[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-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-156] JMS does not adequately define the behaviour of getAcknowledgeMode, getTransacted and getSessionMode in Java EE Created: 01/Sep/14  Updated: 25/Mar/15

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

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

Tags: jms20-errata, jms21-forreview-major

 Description   

JMS does not adequately define the behaviour of Session#getAcknowledgeMode, Session#getTransacted and JMSContext#getSessionMode in the Java EE web or EJB container.

What the spec currently says about these methods

The javadoc for Session#getAcknowledgeMode state that this method

Returns the acknowledgement mode of the session. The acknowledgement mode is set at the time that the session is created. If the session is transacted, the acknowledgement mode is ignored.

The javadoc for Session#getTransacted state that this method

Indicates whether the session is in transacted mode.

The javadoc for JMSContext#getSessionMode states that this method

Returns the session mode of the JMSContext's session. This can be set at the time that the JMSContext is created. Possible values are JMSContext.SESSION_TRANSACTED, JMSContext.AUTO_ACKNOWLEDGE, JMSContext.CLIENT_ACKNOWLEDGE and JMSContext.DUPS_OK_ACKNOWLEDGE

If a session mode was not specified when the JMSContext was created a value of JMSContext.AUTO_ACKNOWLEDGE will be returned.

However this leaves a number of ambiguities in the case where these methods are called in a Java EE web or EJB container.

Why this is ambiguous

The following discussion relates to the case of a Session created using Connection#createSession(boolean transacted, int acknowledgeMode) but the same issues arise for Session objects created using other methods, and for JMSContext objects.

There are two cases we need to consider: (1) When there is JTA transaction in progress and (2) when there is no JTA transaction in progress.

Case 1: when there is an active JTA transaction in progress

What do Session#getAcknowledgeMode and Session#getTransacted return in the case of a Session that was created when there is an active JTA transaction in progress?

The javadoc for Connection#createSession(boolean transacted, int acknowledgeMode) states that "Both arguments transacted and acknowledgeMode are ignored." So there appear to be two possible interpretations of the spec here.

Either (a) Session#getAcknowledgeMode and Session#getTransacted return the values of transacted and acknowledgeMode supplied by the caller when the Session was created,

or (b) these methods return values of transacted and acknowledgeMode which represent the actual behaviour of the session.

Interpretation (a) cannot be correct since this would contradict the requirement that the values supplied by the caller be "ignored". By definition, if these values are ignored then they will not be remembered by the session.

Interpretation (b) cannot be correct since the spec does not define what values of transacted and acknowledgeMode represent the case where the session participates in the JTA transaction.

The spec is quite explicit that whether or not the session participates in the JTA transaction is determined by whether or not there is a JTA transaction in progress, not by the parameters to createSession, so it does not define any values of these parameters which represent the use of a JTA transaction.

One possible way to implement interpretation (b) might be for Session#getAcknowledgeMode to return Session.SESSION_TRANSACTED and Session#getTransacted to return true.

However this would be ambiguous as it would not provide any distinction between a JTA transaction and a local transaction. It would also be inconsistent with the javadoc for the constant SESSION_TRANSACTED which states that getAcknowledgeMode returns this value "if the session is using a local transaction". There is no mention of it being used to represent a JTA transaction.

Case 2: when there is no active JTA transaction in progress

The same question applies in the case where the session is created when there is no JTA transaction in progress. Again, there are two options.

Either (a) Session#getAcknowledgeMode and Session#getTransacted return the values of transacted and acknowledgeMode supplied by the caller when the Session was created,

or (b) these methods return values of transacted and acknowledgeMode which represent the actual behaviour of the session.

We need to reject (a) for the same reason as stated above, which is that Connection#createSession(boolean transacted, int acknowledgeMode) states is required (or permitted, if we accept JMS_SPEC-155) to "ignore" the specified parameters.

However (b) is less problematical since there is no need to denote that the session is participating in a JTA transaction. So this would be a reasonable option.

Proposed clarification

It is proposed to clarify the behaviour of the JMSContext method getSessionMode and the Session methods getAcknowledgeMode and getTransacted when in a Java EE web or EJB container as follows:

  • If these methods are called in an active JTA transaction then the values returned are undefined.
  • A future version of JMS might define returned values which represented a JTA transaction, but this might require making incompatible changes to existing JMS providers so this would need careful consideration and is best deferred to a later occasion.
  • If these methods are called when there is no active JTA transaction, and the Session or JMSContext was created when there was also no active transaction, then the values returned must reflect the actual behaviour that would be exhibited by the Session or JMSContext if it were used to consume a message when there was no active JTA transaction.


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

Description updated with a new proposal.

Comment by Nigel Deakin [ 25/Mar/15 ]

Deferred until JMS 2.1





[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-154] Standardize Abstractions for Common Message Processing Patterns Created: 08/Jul/14  Updated: 06/Oct/14

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

Type: New Feature Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major

 Description   

I came across a very interesting idea while discussing the declarative message listener feature
(https://java.net/jira/browse/JMS_SPEC-134) at NFJS that I think is worth sharing.

We can actually think of standardizing some common JMS message processing patterns declaratively via
the feature. We have actually sort of already discussed this above but it can be flushed out/extended far
more. It's best to explain this via examples.

Batch processing messages is something we've already discussed:

@ApplicationScoped @Lock(WRITE)
public class MyListenerComponent {

  @JmsListener(destinationLookup="...", batchSize="...", retry="...", retryDelay="...", ...) 
  // Batch delivery, retry, retry delay, etc new features.
  public void listen (Message... messages) {
    ...
  }

}

On top of this we can think of ordering the batched messages by priority, timestamp, etc:

@ApplicationScoped @Lock(WRITE)
public class MyListenerComponent {

  @JmsListener(destinationLookup="...", batchSize="...", orderBy=TIMESTAMP) 
  // Messasages automatically ordered. Options could be priority, timestamp and delivery time.
  public void listen (Message... messages) {
    ...
  }

}

It could also be possible to use application defined "Dead Letter Queues" where messages are forwarded
once a delivery/retry count is exceeded:

@ApplicationScoped @MaxConcurrency(10)
public class MyListenerComponent {

  @JmsListener(destinationLookup="...", retry="...", dlqLookup="...") 
  // After a certain number of retries, automatically forward to the specified DLQ.
  public void listen (String message) {
    ...
  }

}

Another interesting case is provinding a simple abstraction for the request/reply pattern:

@ApplicationScoped @MaxConcurrency(10)
public class MyListenerComponent {

  @JmsListener(destinationLookup="...") 
  // Send the return response to the reply-to queue, populating a correlation ID
  // from the incoming message. 
  // Could potentially have a collection of responses, although that's probbaly rare.
  public String listen (String request) {
    String response = ... // Some default value.
    ...
    // Process the request and set the corresponding response.
    ...
    return response;
  }

}

I am sure there are other patterns I am missing that the community or the expert group could
fill in.

Please note that these are my opinions only and not necessarily those of Oracle as a company.






[JMS_SPEC-153] Correction to 7.3.8. "Use of the CompletionListener by the JMS provider" Created: 19/May/14  Updated: 19/May/14

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

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

Tags: jms20-bug

 Description   

In the JMS 2.0 specification, section 7.3.8. "Use of the CompletionListener by the JMS provider" states:

A session will only invoke one CompletionListener callback method at a time. For a given MessageProducer or JMSContext{, callbacks (both onCompletion and onException) will be performed in the same order as the corresponding calls to the asynchronous send method.

This requirement was added to the specification to make the handling of async callbacks as simple as possible, and as consistent with synchronous sends as possible. However the requirement that callbacks be performed in order for a given MessageProducer is inconsistent with the longstanding JMS principle defined in section 6.2.9.1 that "messages sent by a session to a destination must be received in the order in which they were sent".

It would perhaps be more consistent if the JMS specification were changed to state that callbacks be performed in order for a given Session.

A session will only invoke one CompletionListener callback method at a time. For a given Session or JMSContext, callbacks (both onCompletion and onException) will be performed in the same order as the corresponding calls to the asynchronous send method.

Note that although this may require JMS providers to change the order in which they perform callbacks, such a change would be completely compatible with existing applications since if callbacks occur in session order then they will by definition be in message producer order as well.






[JMS_SPEC-152] New method XAJMSContext#createXAJMSContext Created: 19/May/14  Updated: 19/May/14

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

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

Tags: jms20-bug

 Description   

A new method is needed on XAJMSContext which creates a new JMSXAContext using the same connection as the existing XAJMSContext and creating a new session.

XAJMSContext createXAContext()

This is analogous to the existing method createContext on JMSContext, but for XA-capable JMSContext objects.

This method was omitted from JMS 2.0 on the grounds that the JMS specification did not permit the creation of multiple sessions from the same connection in the Java EE web or EJB container. However this is not the right place to enforce that restriction, since it is a restriction on the application, not the application server or resource adapter, and the XAJMSContext interface is for use by the application server or resource adapter, not by applications. Omitting this method places an unnecessary restriction on the ability for application servers to use multiple sessions on the same connection whilst preventing applications doing the same.






[JMS_SPEC-151] Add repeating annotation support to @JMSConnectionFactoryDefinition and @JMSDestinationDefinition Created: 16/May/14  Updated: 19/May/14

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

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

Issue Links:
Dependency
blocks JAVAEE_SPEC-36 Adapt to Java SE 8 Repeating Annotations Open
Tags: jms21-forreview-minor

 Description   

Java SE 7 did not allow class-level annotations such as @JMSConnectionFactoryDefinition and @JMSDestinationDefinition to be repeated.

This meant that if a class needed to define more than one connection factory or destination, then they needed to be wrapped in a @JMSConnectionFactoryDefinitions or @JMSDestinationDefinitions annotation, which made the code quite complicated:

@JMSDestinationDefinitions({   
   @JMSDestinationDefinition(name = "java:global/jms/myQueue1", 
                             destinationName = "myQueue1",
                             interfaceName = "javax.jms.Queue"),
   @JMSDestinationDefinition(name = "java:global/jms/myQueue2", 
                             destinationName = "myQueue2",
                             interfaceName = "javax.jms.Queue")    
}) 

Java SE 8 allows annotation types to be marked as "repeatable". If the @JMSConnectionFactoryDefinition and @JMSDestinationDefinition annotations were marked as repeatable then the above example could be simplified to

@JMSDestinationDefinition(name = "java:global/jms/myQueue1", 
                             destinationName = "myQueue1",
                             interfaceName = "javax.jms.Queue")
@JMSDestinationDefinition(name = "java:global/jms/myQueue2", 
                             destinationName = "myQueue2",
                             interfaceName = "javax.jms.Queue")    

To allow this, the @JMSDestinationDefinition annotation would be extended as follows:

@Target(value=TYPE)
@Retention(value=RUNTIME)
@repeatable(JMSDestinationDefinitions.class)
public @interface JMSDestinationDefinition

and the @JMSConnectionFactoryDefinition annotation would be extended as follows:

@Target(value=TYPE)
@Retention(value=RUNTIME)
@repeatable(JMSConnectionFactoryDefinitions.class)
public @interface JMSConnectionFactoryDefinition

Note that it is necessary to specify a "containing annotation" which is generated by the compiler and used to store repeating annotations. It should be possible to re-use the existing annotations JMSDestinationDefinitions and JMSConnectionFactoryDefinitions for this purpose.






[JMS_SPEC-150] Add guidance on when to use receiveBody and how to handle MessageFormatRuntimeException Created: 08/May/14  Updated: 12/May/14

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

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

Tags: jms21-forreview-minor

 Description   

The JMSConsumer methods receiveBody(Class<T> c), receiveBody(Class<T> c, long timeout) and receiveBodyNoWait(Class<T> c) are intended to be used when the application knows in advance that the type of the next message will be, or if all messages on the queue or topic are of the same type.

If the application calls these methods with an inappropriate class then a MessageFormatRuntimeException will be thrown. The specification defines what must happen next with the message; the required behaviour depends on the session mode but in all cases is designed to give the application a further opportunity to receive the message, either by calling receiveBody with a different class, or by calling the normal receive method.

It may be helpful if the documentation for these methods included some recommendations on when to use them, and how to handle a MessageFormatRuntimeException.

The documentation could state that these methods are intended to be used only when the application knows in advance that the type of the next message will be, or if all messages on the queue or topic are of the same type.

The documentation could also state that if a MessageFormatRuntimeException is thrown then since the application, by definition, does not know what the type of the message is, it is probably best to receive the message a second time using the normal receive method, which does not require the type of the next message to be known.

(Note that prior to calling receive, if the session mode is CLIENT_ACKNOWLEDGE then the application will need to call recover, and if the session mode is transacted then the application will need to rollback the transaction and start a new one. If the session mode is AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE then the application can simply call receive immediately.)






[JMS_SPEC-149] Asynchronous Send Functionality Should Use Java SE 8 Completeable Future Created: 02/Apr/14  Updated: 14/Jun/14

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

Type: Improvement Priority: Minor
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor

 Description   

Much better fit for the intent of the asynchronous send functionality than the current callback interface.



 Comments   
Comment by clebertsuconic [ 02/Apr/14 ]

good point IMO

Comment by Nigel Deakin [ 14/May/14 ]

Here is an analysis of what new API this would entail:

The standard API currently defines four existing methods on MessageProducer which perform an async send:

void sendAsync(Destination destination, Message message) throws JMSException
void sendAsync(Destination destination, Message message) throws JMSException
void sendAsync(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException
void sendAsync(Message message) throws JMSException

If we were to add equivalent methods which perform an async send and return a CompleteableListener then we would need:

CompletableFuture sendAsync(Destination destination, Message message) throws JMSException
CompletableFuture sendAsync(Destination destination, Message message) throws JMSException
CompletableFuture sendAsync(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException
CompletableFuture sendAsync(Message message) throws JMSException

In the simplified API, an async send is current specified on a JMSProducer by calling the existing method setAsync(CompletionListener completionListener) followed by a call to one of five existing send methods. These send methods return the JMSProducer to allow message chaining:

JMSProducer send(Destination destination, byte[] body)
JMSProducer send(Destination destination, Map<String,Object> body)
JMSProducer send(Destination destination, Message message)
{{JMSProducer send(Destination destination, Serializable body)
JMSProducer send(Destination destination, String body)

We would need to define five new methods which perform an async send and which return a CompleteableFuture. Since these methods don't return the JMSProducer they can't be used in message chaining:

CompletableFuture sendAsync(Destination destination, byte[] body)
CompletableFuture sendAsync(Destination destination, Map<String,Object> body)
CompletableFuture sendAsync(Destination destination, Message message)
{{CompletableFuture sendAsync(Destination destination, Serializable body)
CompletableFuture sendAsync(Destination destination, String body)

In all cases, the CompletableFuture allows the caller to use methods such as accept, apply or {[exceptionally}} to register callback functions which are executed in the event of successful or unsuccessful completion of the send (many other options are possible in addition to this).

Comment by Nigel Deakin [ 14/May/14 ]

As can be seen, quite a lot of new API would be required. The most important issue, I think, is whether providing this new API would be of genuine benefit to users. I think we current have insufficient information to determine this currently. It would be very helpful to have feedback from developers who are using the new JMS 2.0 async send feature.

Implementing these new methods would be fairly simple - indeed applications could probably write their own implementations on top of the JMS 2.0 API.

One issue to bear in mind is that JMS 2.0 specifies that completion callbacks must take place one at a time and in the correct order. This restriction would apply even if CompletableFuture were used instead, unless the spec defined otherwise.

Comment by reza_rahman [ 14/Jun/14 ]

Honestly I'm not sure about this one myself - we should probably gather more feedback or defer it for now...





[JMS_SPEC-148] The Delivery Delay Feature Should Utilize the Java SE 8 Date/Time API Created: 02/Apr/14  Updated: 13/Jun/14

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

Type: Improvement Priority: Minor
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor

 Description   

Isn't a much better fit for this purpose than the older Java SE APIs.



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

Please state what you are proposing.

In JMS 2.0, an application requests a delivery delay by specifying a minimum time interval in milliseconds. It doesn't involve the use of "the older Java SE APIs".

Comment by Nigel Deakin [ 14/May/14 ]

More information is needed to be able to assess this request (and I don't want to start guessing at what you had in mind). So I'm marking this as "incomplete".

Will re-open if specific proposals are made.

Comment by reza_rahman [ 03/Jun/14 ]

Returning back to this, hopefully it's not too late...

As I had noted (and you did as well), this is a relatively minor issue as JMSProducer.setDeliveryDelay uses long as an argument type as opposed to the old temporal APIs. However, this feature can arguably be made more type safe/easy to use by allowing an argument of one of the newer Java SE 8 types such as Period or Duration: http://docs.oracle.com/javase/tutorial/datetime/iso/overview.html. For one, that would make any date/time manipulation required before invoking setDeliveryDelay far easier. On the flip side the advantage of the current signature is that it is rather generic (basically down to the lowest common temporal denominator).

Does this help any?

Comment by Nigel Deakin [ 13/Jun/14 ]

Reopening in the light of more information, and tagging for discussion.

Comment by Nigel Deakin [ 13/Jun/14 ]

If we decide to add new methods to set/get delivery delay then we should add similar methods to set time to live.





[JMS_SPEC-147] Extend the @JMSConnectionFactory annotation to allow a resource reference to be defined Created: 17/Mar/14  Updated: 20/Mar/14

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

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

Tags: jms21-forreview-minor

 Description   

In JMS 2.0 the @Inject annotation may be used to inject a JMSContext into a Java EE application.

The @JMSConnectionFactory annotation may be used to specify the "the JNDI lookup name" of the connection factory which should be used. This is the only information about the connection factory that may be specified. The specification is unclear about what this lookup name represents.

Compare this with the @Resource annotation which may be used to inject a JMS connection factory. This allows the connection factory to be specified using the name, lookup, mappedName, authenticationType, description, shareable and type attributes.

The @JMSConnectionFactory annotation only allows a single attribute (value) to be specified. Since this is described as the "lookup name" we can assume it corresponds to the lookup attribute of the @Resource annotation, though this isn't stated explicitly.

The @JMSConnectionFactory annotation doesn't allow any of the other attributes to be specified. This means that some important characteristics of the connection factory cannot be specified when injecting a JMSContext.

Another consequence of this is that the @JMSConnectionFactory annotation doesn't allow a resource reference name to be defined. This prevents the deployer defining or overriding these values by creating a <resource-ref> element in the deployment descriptor.

The @JMSConnectionFactory annotation therefore needs to be clarified and extended to allow the same information to be specified as when using a @Resource annotation to inject a JMS connection factory. In addition the specification should state more clearly exactly what the existing value attribute specifies.



 Comments   
Comment by reza_rahman [ 20/Mar/14 ]

I honestly hope this one is prioritized via the EG/community. The problem is that things like @Resource name, mappedName, authenticationType, description, shareable and type are rarely used as far as I have seen personally over many years apart from perhaps the corner case of very, very large corporate environments (perhaps in the Fortune 10?). As a result, these features add to the impression of a complex and bloated API that isn't developer friendly. It was part of the reason we moved towards standard global JNDI names/scopes in the Java EE 6 EG (I was part of that discussion and still remember it clearly).

Please note that these are purely my personal views and certainly not of Oracle's as a company.





[JMS_SPEC-146] Allow the registration of a message listener via a connection when done within an ManagedExecutorService. Created: 25/Jan/14  Updated: 29/Jun/15

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

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-141 Allow async delivery to temporary des... Open
Tags: jms21-forreview-major

 Description   

Currently, you cannot call setMessageListener when a connection is running with in an application server. I believe we can circumvent this limitation if the registration of the underlying threads is done via a ManagedExecutorService. The spec should be updated to indicate that an implementation should register the delivery code via a ManagedExecutorService.



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

Adding to the list of issues to be considered for JMS 2.1 and tagging accordingly.





[JMS_SPEC-145] Allow the execution of async message sending on an application server if done within a ManagedExecutorService Created: 25/Jan/14  Updated: 04/Feb/14

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

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major

 Description   

Currently, we explicitly disallow the execution of async message sending in an application server.

I believe we can allow it by leveraging the Java EE concurrency utilities. The sending of a message this way can be done using a call wrapped inside of a ManagedExecutorService.



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

I wrote an explanation of why this was not permitted in JMS 2.0 in the JMS 2.0 Reasons FAQ. The main difficulty was in getting an async message send to participate correctly in an XA transaction. It's worth revisiting this to see if these issues can be overcome.

Comment by Nigel Deakin [ 04/Feb/14 ]

Adding to the list of issues to be considered for JMS 2.1 and tagging accordingly.





[JMS_SPEC-144] StreamMessage#getBody(Class<T>) Created: 23/Jan/14  Updated: 30/Aug/15

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

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

Tags: jms21-forreview-minor

 Description   

Logged on behalf of Philippe Marschall, who posted this to the community alias:
https://java.net/projects/jms-spec/lists/users/archive/2013-12/message/16

Since it's time to gather ideas for JMS 2.1 I thought I'd mention this early. I noted that #getBody does not have any conversions defined for StreamMessage. IMHO it would be really convenient if the following conversions where offered:

  • java.io.InputStream (if the message is not in write-only mode)
  • java.io.OutputStream (if the message is not in read-only mode)
  • java.io.Reader (if the message is not in write-only mode)
  • java.io.Writer (if the message is not in read-only mode)

This would also make it very easy to plug StreamMessage into anything else that does stream oriented IO in Java.

Obviously #isBodyAssignableTo(Class) would have to be updated as well.



 Comments   
Comment by Nigel Deakin [ 23/Jan/14 ]

This proposal doesn't simply provide a simpler alternative to existing API, it adds new functionality to StreamMessage. StreamMessage doesn't currently have methods to return objects of any of these four types, so the first thing to consider is whether we would want to add four new methods to StreamMessage to return an InputStream, OutputStream, Reader and Writer.

The StreamMessage object has methods which make it look like a stream, but it doesn't actually have any methods to return the stream directly. This was probably deliberate as it didn't force the implementer to use a stream internally. We need to consider carefully whether exposing the underlying stream (or perhaps forcing the implementation to create one if it doesn't use one internally) might cause problems for implementers.

The classes Reader and Writer are for character streams only, whereas a StreamMessage can hold a stream of different object types. I'm not sure that's a good match.

As for InputStream or OutputStream: I wonder whether returning an ObjectInputStream or ObjectOutputStream would be more appropriate, since these stream types, like StreamMessage, have specific methods to read and write various primitives such as boolean or long rather than simply bytes. However the methods it allows are not identical to the methods on StreamMessage (e.g. StreamMessage defines its own rules on type conversion). I wonder whether the differences would cause difficulties.

You use the word "conversions". Currently #getBody doesn't perform type conversions. There is currently a one-to-one mapping between the message type and the class that must be passed in. For example you can't use call getBody(byte[].class) on a TextMessage to obtain the text string as an array of bytes. But if we allow the body of a StreamMessage to be returned as (say) a OutputStream, do we also need to allow the same for other message types such as BytesMessage or TextMessage?

Comment by braghest [ 30/Aug/15 ]

To explain our problem a bit. We currently use JSR 353 (JSONP) to parse JSON we receive over JMS. JSR 353 is a streaming API and operates on the standard InputStream and Reader classes. Since{{StreamMessage}} does not offer adapters for these classes combining these two JavaEE technologies is more work than strictly necessary.

The proposal would not add any new methods to StreamMessage, it would do it all through the #getBody method.

I don't think ObjectInputStream and ObjectOutputStream are a good match since they are intended for Java Serialization.

I used "conversions" but meant type adapters.

The proposal would not force an implementor to use a stream internally or expose the underlying stream. See the class below on how such a stream could be provided with the current implementation. It is a bit inefficient since no bulk reading methods are provided. A similar solution could be come up for input stream.

public final class StreamMessageReader extends Reader {
  
  private final StreamMessage streamMessage;

  public StreamMessageReader(StreamMessage streamMessage) {
    this.streamMessage = streamMessage;
  }

  @Override
  public int read(char[] cbuf, int off, int len) throws IOException {
    int i = 0;
    try {
      char c = this.streamMessage.readChar();
      while (i < len) {
        cbuf[i + off] = c;
        i += 1;
        c = this.streamMessage.readChar();
      }
    } catch (MessageEOFException e) {
      return i;
    } catch (JMSException e) {
      throw new IOException("read failed", e);
    }
    return i;
  }
  
  @Override
  public int read() throws IOException {
    try {
      return this.streamMessage.readChar();
    } catch (MessageEOFException e) {
      return -1;
    } catch (JMSException e) {
      throw new IOException("read failed", e);
    }
  }
  
  @Override
  public void reset() throws IOException {
    try {
      this.streamMessage.reset();
    } catch (JMSException e) {
      throw new IOException("reset failed", e);
    }
  }

  @Override
  public void close() throws IOException {
    // ignore
  }

}




[JMS_SPEC-143] Define standard MDB activation properties to allow the MDB pool to be configured Created: 20/Nov/13  Updated: 20/Nov/13

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

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

Tags: jms21-forreview-minor

 Description   

Should there be standard activation properties to allow the pool of MDB instances to be configured?

It's not clear whether this is desirable or not.

MDBs are defined in the EJB specification, not the JMS specification, so we would need to work with the EJB expert group on this.

MDBs aren't just for JMS, so we would need to consider is whether we'd want to define standard pooling properties just for JMS, or for all MDBs.

The EJB spec doesn't require a MDB (whether JMS or not) to be implemented using a pool of MDB instances. So in standardising pooling we may be trespassing on what is currently an implementation detail.

Most MDB pools are configured using multiple properties such as initialPoolSize, minPoolSize, maxPoolSize, steadyPoolSize and so on, depending on how the pool is implemented and what features it offers (e.g. some pools may allow the pool to grow and shrink whilst others might be fixed-size). Which of these are could be standardised and which of these would we have to leave as an implementation detail? It would probably be inappropriate to attempt to standardise them all.

On the other hand, the new Java EE 7 resource configuration features do introduce a notion of pooling for JMS connections (not MDBs). The new <jms-connection-factory> deployment descriptor element has the sub-elements <max-pool-size> and <min-pool-size>, and the new javax.jms.ConnectionFactoryDefinition annotation has the attributes minPoolSize and maxPoolSize. So this does offer precedent for defining pooling properties.






[JMS_SPEC-142] Standardize Dead Letter Queues Created: 19/Nov/13  Updated: 23/Jan/14

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

Type: New Feature Priority: Minor
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 4
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major

 Description   

JMS 2 made the JMSXDeliveryCount property required. However, dead letter queues remain non-standard although they are widely implemented and used. As a result, JMS application portability is needlessly limited and the feature is harder to use (often requiring digging around vendor documentation).

This proposal is to standardize the concept of dead letter queues and make them available at a standard location - e.g. java:comp/deadLetterQueue.



 Comments   
Comment by Nigel Deakin [ 23/Jan/14 ]

Added to the agenda for JMS 2.1
https://java.net/projects/jms-spec/pages/JMS21Planning#Major_issues_to_be_considered_for_JMS_2.1





[JMS_SPEC-141] Allow async delivery to temporary destinations in Java EE Created: 18/Nov/13  Updated: 29/Jun/15

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

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

Issue Links:
Related
is related to JMS_SPEC-146 Allow the registration of a message l... Open
Tags: jms21-forreview-major

 Description   

Currently there is no (legal) way for an application running in the Java EE web or EJB containers to consume messages asynchronously from a temporary queue or topic.

The use of setMessageListener to register a MessageListener is not permitted.

It is not possible to configure a MDB to consume messages from a temporary destination.

This was raised in the GlassFish forum recently. https://www.java.net//node/900071 Is this a common requirement?

It is proposed that the discussion elsewhere to make async message delivery in Java EE applications more flexible should (at least) consider this requirement.



 Comments   
Comment by lprimak [ 19/Nov/13 ]

The primary pattern that uses temporary queues and asynchronous receivers is
gathering cluster nodes' health pattern.

  • all nodes broadcast a heartbeat on a topic with a temporary queue as jmsReplyTo
  • all nodes reply to the heartbeat message using getJMSReplyTo() from the heartbeat message (to the temp queue)
  • thus, all nodes will know all other nodes, and will remove stale nodes on heartbeat timeout.

This is the simplest way to implement this pattern.

Another pattern that uses this method is here:
http://www.drdobbs.com/jvm/asynchronous-java-calls-part-2/240003830





[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-139] Clarify scope of ClientID between JavaDoc and specification Created: 05/Nov/13  Updated: 05/Nov/13

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

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

Tags: jms21-forreview-minor

 Description   

The JavaDoc for the javax.jms.Connection setClientID method includes the following line

"If another connection with the same clientID is already running when this method is called, the JMS provider should detect the duplicate ID and throw an InvalidClientIDException."

The JMS2.0 TCK does include a test that checks that if a second connection is created from a CF with a client ID set, then the second create connection fails. I do not believe that this tested existing within the 1.1 TCK.

This line and test means that the scope of a ClientID is per active Connection (or context).

The text (PDF) specification does not explicitly state this - it says..

"The purpose of client identifier is to associate a connection and its objects with a state maintained on behalf of the client by a provider. By definition, the client state identified by a client identifier can be 'in use' by only one client at a time. A JMS provider must prevent concurrently executing clients from using it."

It says "concurrently executing clients" not "concurrently executing connections". This also implies that the definition of the word 'client' is a single active connection. Again this is not stated explicitly.

It does mean that pooling implementations have to be careful. They can not keep pools of active connections all from the same client ID. The connections in the pools must be stopped first.



 Comments   
Comment by mbwhite [ 05/Nov/13 ]

Forget to add - that this would also imply, I think, that a ConnectionFactory with a clientID set in it (the preferred) way can only have 1 active connection at time created from it. A set of programs running in 2 JVMs therefore could not share a common ConnectionFactory stored in JNDI.

Comment by John D. Ament [ 05/Nov/13 ]

a ConnectionFactory with a clientID set in it (the preferred) way can only have 1 active connection at time created from it

Can you clarify what you mean here? There is no way to set the clientId on a connection factory: https://jms-spec.java.net/2.0/apidocs/javax/jms/ConnectionFactory.html

Maybe for this issue in general we can discuss further on the users@ or eg groups? Maybe there's just a misunderstanding here.

Comment by Nigel Deakin [ 05/Nov/13 ]

Thanks for reporting the issue. I've added it to the list of issues to be considered for 2.1.

JMS 2.0 has not changed the clientID uniqueness requirements from JMS 1.1. All it did was to define a new method on JMSContext to set the clientID of the underlying connection.

If the JMS 2.0 TCK has added a new test, and that test is causing difficulty for vendors, then TCK licensees can address that through the TCK challenge procedure.

I think the intention of the JMS 1.1 spec was that no two JMS connections should have the same clientID. The use of the word "client" here is vague and it would be clearer if this were changed to refer to connections.

The use of the word "should" rather than the word "must" suggests that the clientID uniqueness requirement is a recommendation rather than an absolute requirement. It would be clearer if the spec as a whole clarified the meaning of the word "should". There's a document, RFC 2119, which the spec could refer to http://www.ietf.org/rfc/rfc2119.txt

The other comments you make are perfectly correct.

The clientID uniqueness requirement means that you can't have a pool of connections all of which have the same clientID.

And the statement in JMS 1.1 and 2.0 that "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" means that such a connection factory can only be used to create only one connection at a time.

I think the best solution to all these issues with clientID is to remove the need to set clientID at all, especially when working in a Java EE environment, and there have been various changes in JMS 2.0 to partially achieve that.

Comment by mbwhite [ 05/Nov/13 ]

From the 6.2.1 section of the PDF... 'ClientId'

"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"
So the spec prefers a ClientID to already be in place when a connection is created - and from a JavaEE perspective applications can't set it. (section 12.2).

It's true that clientID is really only used for non-shared durable subscriptions. And only one of those could be active at once anyway - but there's a logical consequence here that the TCK brought to my attention that I'm not sure is what is intended.

Yes - can send out an email to the list - good point.

Comment by mbwhite [ 05/Nov/13 ]

Thanks Nigel; I agree that the scope hasn't changed between 1.1 & 2 - nor is the TCK specifically at fault. Rather it has improved and is now checking something that as you state was always the intent but was perhaps not quite as clear. Hence it triggered the discussion and the logical conclusion that you've confirmed.

Would you agree it would be valid to have a pool of 'stopped' connections? i.e. only 1 active/started. Though that might be a little academic anyway!

Comment by Nigel Deakin [ 05/Nov/13 ]

It doesn't matter whether the connection is stopped or not. The spec is clear that calling stop() simply suspends the delivery of incoming messages. It doesn't have any effect on clientID. Only calling close() will release a client identifier from being in use.

Note that JMS doesn't define the internal implementation of your connection pool. It only defines the behaviour seen by the application. It doesn't matter what the connection pool does internally.

Comment by mbwhite [ 05/Nov/13 ]

ok; my comment was because the JavaDoc uses the work 'running' rather than 'created'. Running implies started and delivering messages.

Agree that JMS doesn't defined internal implementation of connection pool - my point is that with this definition of clientID there is no possibility of pooling these connections at all. Only one connection object can be created at any point in time.





[JMS_SPEC-138] Clarify whether you can call createContext on a QueueConnectionFactory or TopicConnectionfactory Created: 01/Nov/13  Updated: 14/May/15

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

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

Tags: jms20-errata, jms21-forreview-minor

 Description   

In the JMS 2.0 API, the legacy JMS 2.0 interfaces QueueConnectionFactory and TopicConnectionfactory inherit the methods createContext from ConnectionFactory.

However, this implies that an object which is specific to either queues or topics is capable of generating an object (a JMSContext) that must work with both queues and topics.

Section 9.2 of the JMS 2.0 specification "Method inheritance across messaging domains" addresses the general issue of domain-specific interfaces inheriting methods which are not appropriate to that particular messaging domain, such as the createTopic method which a QueueSession inherits from Session. It lists a number of inherited methods which must throw an IllegalStateException.

The absence of createContext from that list means that the JMS 2.0 specification currently requires that calling createContext on a QueueConnectionFactory or TopicConnectionfactory must be supported.

We might wish to consider whether we should extend the list in 9.2 to require that calling createContext on a QueueConnectionFactory or TopicConnectionfactory must similarly throw an IllegalStateException. This would be more consistent, though since JMS 2.0 is already released it may be too late to require this since it would probably constitute an incompatible change.

Perhaps the best approach is to confirm that these methods must be supported, and that the JMSContext that is returned must support both queue and topics. This would not remove any functionality from users and so not be an incompatible change. And it is unlikely that providers would have any difficulties implementing it.



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

The same issue applies to the classic API. If an application calls createConnection on a QueueConnectionFactory or TopicConnectionFactory, can the resulting Connection object be used with both queues and topics?

Comment by Nigel Deakin [ 13/Jan/15 ]

Taking both issues together, we have three possibilities if an application tries to perform an operation on a topic using a QueueConnectionFactory, or an operation on a queue using a TopicConnectionFactory:

1. An IllegalStateException must be thrown
2. The operation may work, or alternatively an IllegalStateException may be thrown. Applications which depended on this working would not be portable
3. The operation must work (as suggested above). This seems to be the best option, since defining that something "must work" is better than defining that something "must fail".





[JMS_SPEC-137] Section 8.7 of the JMS 2.0 spec has a malformed sentence Created: 04/Oct/13  Updated: 05/Nov/13

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

Type: Improvement Priority: Minor
Reporter: jlindwall Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

N/A


Tags: jms21-forreview-minor

 Description   

There is a confusing/malformed sentence in section 8.7 of the JMS 2.0 spec (also present in section 4.5.2 of 1.1 spec). The sentence is "Well behaved listeners should catch
such exceptions and attempt to divert messages causing them to some form
of application-specific 'unprocessable message' destination."

Is this trying to say ".. and attempt to divert messages to some form of application-specific ...
? In other words I feel like the words "causing them" should be removed from this sentence. In any case, it needs to be reworded somehow to make the meaning clear, in my opinion.

=== Larger quote:

8.7. Receiving messages asynchronously
...

It is possible for a listener to throw a RuntimeException; however, this is
considered a client programming error. Well behaved listeners should catch
such exceptions and attempt to divert messages causing them to some form
of application-specific 'unprocessable message' destination.

Thanks!
John Lindwall



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

The words "causing them" are used to suggest that the reason the listener might want to throw a RuntimeException is because there is something wrong (in application terms) with a message which prevents the message listener processing it, such as it containing invalid data.

That's why there is a suggestion that the listener should catch such exceptions and divert the "bad" message in question to to a dead message queue (DMQ) of some kind. The listener would continue to process the "good" messages as normal but would divert "bad" messages to the DMQ.

Note that the person developing the listener is free to ignore this advice and throw a RuntimeExceoption anyway. JMS provider will then behave as defined in this section.





[JMS_SPEC-136] Introduce a programmatic API for creating destinations. Created: 02/Sep/13  Updated: 02/Sep/13

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

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Since we have the option of creating a temporary queue/topic, it should also be possible to create a permanent queue/topic. The idea being that this queue/topic could survive for a long period of time, perhaps even be persistent. Most common attributes for configuring them should be addressed (e.g. name, JNDI location, require role/user, perhaps even storage scheme).






[JMS_SPEC-135] Add methods to get a Destination. Created: 02/Sep/13  Updated: 03/Sep/13

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

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Currently, the JMS API has no clear way of looking up a Queue or Topic. It's typically assumed to use JNDI, however when you're in Java SE there is no single entry point that allows one to look up a Queue or Topic.

Typically, permanent Queues/Topics are created via configuration (XML files, metadata, etc). As a result, I think we should add methods to ConnectionFactory/JMSContext/Connection that allows a developer to get a destination.



 Comments   
Comment by John D. Ament [ 02/Sep/13 ]

This may be as simple as clarifying that createQueue/createTopic should/should not be specific to temporary queues/topics. Looking at two open implementations (OpenMQ and HornetQ), one allows this to return temporary destinations, the other does not.

Comment by chris.barrow [ 03/Sep/13 ]

Methods createTemporaryQueue and createTemporaryTopic are provided for temporary destinations. AFAIK createQueue and createTopic are for non-temporary destinations. Many JMS providers allow these to be used to create new (dynamic) queues and topics. Their function is "get or create", so they can be used instead of doing a JNDI lookup.

Comment by Nigel Deakin [ 03/Sep/13 ]

The methods createQueue and createTopic provide a way for an application to obtain a Queue or Topic object identified by the specified name.

These methods are not intended to create the underlying queue or topic in the JMS provider but are simply ways of obtaining a Queue or Topic object which refers to an existing queue or topic.

(I know some JMS providers do support automatic creation of queues and topics but this is not a requirement of these methods.)

Can you say more about why these methods do not meet your needs? Are you asking for methods to physically create the queue or topic in the JMS provider?





[JMS_SPEC-134] Declarative Annotation Based JMS Listeners Created: 29/Aug/13  Updated: 03/Oct/13

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

Type: New Feature Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 11
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-100 Allow Java EE components other than M... Open
is related to JMS_SPEC-116 Take advantage of EJB 3.2's RA improv... Open
Tags: jms21-forreview-major

 Description   

MDB is currently the only declarative way of listening for JMS messages. While the MDB model is adequate, it has a few shortcomings (primarily related to it's true age). The first is that since it is rather generic to JCA, it makes the syntax less than ideal for JMS (ironically, the vast majority of MDB use is for JMS). The MDB model is highly coupled to the EJB component model, which makes generic use in managed beans needlessly difficult. Lastly and perhaps most importantly, reimaging the MDB model using CDI/annotations in a manner specific to JMS introduces the possibility of significant usability improvements/API modernization.

It is perhaps best to demonstrate these concepts using some simple code examples:

@Pooled // Documented here: https://java.net/jira/browse/EJB_SPEC-113
public class MyListenerComponent {

  @JmsListener(destinationLookup="...", clientId="...", subsciptionName="...", messageSelector="...", ...)
  @JMSConnectionFactory("...")
  @Transactional
  public void listen (Message message) {
    ...
  }
}
@ApplicationScoped
@MaxConcurrency(...) // Documented here: https://java.net/jira/browse/EJB_SPEC-113
public class MyListenerComponent {

  @JmsListener(destinationLookup="...")
  public void listen (String message) { // Message payload automatically type-checked and unwrapped
    ...
  }

}
@RequestScoped // A message received is a "request"
public class MyListenerComponent {

  @JmsListener(destinationLookup="...")
  // Message payload automatically type-checked and unwrapped, 
  // message contents automatically injected, type-checked, unwrapped.
  public void listen (byte[] message, 
                      @JmsMessageProperty boolean myFlag, 
                      @JmsMessageProperty("myFlag2") boolean myFlag2,
                      @JmsCorrelationId String myCorrelationId,
                      ... 
                      ) {
    ...
  }

}
@Pooled
public class MyListenerComponent {

  @JmsListener(destinationLookup="...", batchSize="...", retry="...", retryDelay="...", ...) 
  // Batch delivery, retry, retry delay, DLQ, etc new features.
  public void listen (Message... messages) {
    ...
  }

}

As suggested in the examples above, decoupling from the EJB component model also allows for a great deal of flexibility in putting together the component life-cycle, programming model, features and re-use.

Although I am entering this in JMS as I feel it is the correct place to get this done, I assume that this body of work will require a great deal of collaboration with the EJB, CDI and platform expert groups.

Do let me know if anything needs to be explained further - I am happy to help.

Please note that these are purely my personal views and certainly not of Oracle's as a company.



 Comments   
Comment by John D. Ament [ 29/Aug/13 ]

It's a great use case when you know your queues up front. We need to have more research in to use cases where destinations are created dynamically, based on tenant changes.

Comment by clebertsuconic [ 29/Aug/13 ]

@John what use cases do you mean? I think this would be a great way to replace MDBs.

It would be great if we could also support receiving multiple messages (arrays) (that's probably what you meant by (Message...messages)

I'm very favorable on this!!! +1000 from me

Comment by reza_rahman [ 29/Aug/13 ]

I imagine one could come up with an API adaptation that could parameterize some annotation metadata and supply them/trigger the listener POJO programmatically. In my experience though, in most enterprise cases, it's fine to assume meta data is known at deployment time.

Comment by reza_rahman [ 29/Aug/13 ]

Yes, the Message...messages/batchSize="..." is intended for batch/bulk message processing.

Comment by John D. Ament [ 02/Sep/13 ]

So, is the issue a case of needing to compare enterprise use cases to cloud based use cases?

I think the ability to support both a programmatic API for binding at runtime plus a series of annotations supporting deployment time options both make sense. It should be possible to do either using a simple DSL around MDB bindings. Enterprise use cases all know about how to do this at deployment time, however the cloud requires runtime manipulation to support multitenancy. Let's suppose that I need a queue per customer, there is no Java EE supported approach that allows me to do this.

1. Setup a message listener. Oh wait, Java EE won't allow us to bind message listeners.
2. Bind an MDB. Works assuming that you can redeploy your whole cloud to bring up a new tenant, including configuring deployment descriptors in between. Not a viable option for cloud providers.
3. Periodically poll the queue. This will work, but doesn't allow for immediate consumption. Easy to setup a scheduled job that does it, but becomes difficult when you have many tenants.

I've also considered that multitenancy is something that could be scripted, or prototyped. Some kind of "NewTenantInit" listener could be called that could setup everything needed to bring that tenant online. A message listener like the one you're describing could be expanded to have a @MultiTenantPrototype annotation that means nothing other than "don't deploy me unless explicitly requested" and all of your annotations could have a tenantId variable in there:

@JmsListener(destinationLookup="jsm/someQueue{tenantId}")

Of course, this would still require JMS providers to create an API that allowed for dynamic destination creation (which would be invoked, in this use case during the creation of a tenant). Maybe something along the lines of:

@Inject
private JMSServerContext serverContext;

...

Queue fooBar = serverContext.createNew(Queue.class).jndiF("jms/fooBar%s",tenantId).name("FooBar Queue for Tenant "+tenantId).storage("/path/to/tentantData").build();
serverContext.bindMDB(MyListenerComponent.class);  //assuming that MyListenerComponent is correct annotated for multitenant

For me right now, this is my biggest use case (and biggest struggle w/ JMS as a user)

Comment by reza_rahman [ 02/Sep/13 ]

I've said this before elsewhere, but I guess those thoughts are worth repeating here.

In Java EE, I think we need to be very careful in standardizing anything under the cloud moniker by making sure:

1. We are not too far ahead of common use cases that are fairly obvious/pervasive. I think that's a good general principal to follow for any standard and certainly Java EE.
2. We do not unduly delay or make more complex the pervasive use cases that we already understand well to try to support the cloud (heretofore) edge cases.

That being said, it's clear to me that by and large the EGs (especially the platform EG) is exercising the correct amount of caution on this particular feature set (for example, I think delaying cloud features like the tenant ID in Java EE 7 was the right call).

Please note that these are purely my personal views and certainly not of Oracle's as a company.

Comment by Nigel Deakin [ 02/Sep/13 ]

Good suggestions. I've added formatting to make the examples easier to read. Here are my thoughts on this proposal (For want of a better name I'll refer to these as "JMS listener beans" in what follows).

I think it's worth making clear that this would need to be a feature of the Java EE web and EJB containers only. Applications running a Java SE environment (or the Java EE application client container) would need to continue to use the JMS API (JMSConsumer#setMessageListener).

There are a number of significant ideas introduced here.

1. The JMS listener bean is a CDI managed bean, so its lifecycle would depend on its scope.

A scope of @ApplicationScoped would give a lifecycle equivalent to a MDB in that the bean(s) would be instantiated when the application was started (or deployed), and destroyed when the application was terminated (or undeployed). We'd need to ensure it was created automatically when the application was started rather than created lazily the first time it was invoked from some other bean. This might be a change to the way CDI beans work currently.

A scope of @Dependent would allow a shorter lifecycle which depends on the object into which it was injected. So you could inject a dependent-scoped JMS listener into a WebSocket endpoint. When a websocket client was connected, the websocket endpoint object is instantiated which would cause the JMS listener to be instantiated. When the websocket client disconnected, the websocket endpoint object is destroyed, which would cause the JMS listener to be destroyed.

Other scopes would be available as well (though we'd need to consider them carefully).

I think the key thing here is that it would allow the developer to define the lifecycle of their listener object, which is something that they cannot do with MDBs.

2. The JMS listener bean is defined to be "pooled".

This means that when the bean is instantiated you're actually instantiating a pool of instances, but just one. This pool of instances would share the load of processing listener callbacks. This is a key concept if this feature is to replace MDBs.

But if the JMS listener bean is actually a pool of beans, and it is injected into some other bean using

@Inject MyListenerBean myBean;

then what does the myBean variable actually refer to? It doesn't make sense to think of this as an object which the application can directly access.

3. Annotations on the JMS listener bean class and methods

I think the general principle of using JMS-specific method annotations to define the callback method, the queue or topic, and other consumer parameters is relatively straightforward, and is something that we could equally define for JMS MDBs as well. However we would need to clearly define the semantics of configuring two callback methods with different queues or topics, or two callback methods with the same queue or topic but with different message selectors.

Relationship to JCA

One final issue we would need to consider is the relationship to the JCA specification. The application server needs to be able to implement these JMS listener beans using a JCA resource adapter. What JCA specification changes would be needed to support JMS listener beans? With a bit of luck the existing endpointActivation/endpointDeactivation API will be sufficient to handle the creation/destruction of JMS listener bean pools. The Activation spec would become redundant with the resource adapter having to scan the annotations on the endpoint class to find out what it needs to do.

Comment by reza_rahman [ 02/Sep/13 ]

Thanks indeed for correcting the formatting - my bad .

I do agree figuring out the scoping is probably the most non-trivial part of this effort. You'd obviously want to work this out with the CDI/Java EE EGs, but I think things make the most sense if you can think of the underlying JMS message delivery infrastructure as a distinct CDI bean "client" that may share the bean with other clients, whatever the scope/life-cycle (including pooled beans). Semantically, this is fairly close to the current CDI event observer model IMO.

Do let me know, I can help with some of this as we discussed most of this as part of an alternative MDB model for Resin 4 (in part inspired by Spring JMS listeners: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/jms.html#jms-receiving and CDI observers: http://docs.jboss.org/weld/reference/latest/en-US/html/events.html#d0e3794).

Please note that these are purely my personal views and certainly not of Oracle's as a company.

Comment by John D. Ament [ 02/Sep/13 ]

So, my assumption with all of this is that this new "MDB" still leverages the brand new spec allowances for MDBs. It allows for better alignment w/ CDI, and allows for more annotations (not just activation config). Is there any preference from anyone on the list that MDBs will not support us? This should fix any EJB spec, object scoping or JCA alignment that may need to be clarified.

@Reza you lost me a little. All I'm suggesting is that we need a dynamic way of binding MDBs to destinations that have been created. While it's a common use case for cloud, it has some usage outside of cloud technology. This would be the functional equivalent of creating an MDB against a temporary queue/topic, except the queue/topic would live longer than the temporary object (almost permanent).

Comment by reza_rahman [ 02/Sep/13 ]

No worries and understood - I think your proposal could be a good one, especially if there are uses outside the cloud. My concern is a rather general one - that we use due caution to standardize any cloud features primarily because of the relative volatility/immaturity of the cloud. Now, all that might change in a few years and perhaps in enough time for EE 8, so it's definitely worth keeping an eye on/seriously considering. In particular, the tenant ID feature is one that I thought was premature/incomplete (and perhaps it still is). To be more specific, I am talking about the tenant ID discussion that took place in the Java EE 7 EG.

Please note that these are purely my personal views and certainly not of Oracle's as a company.

Comment by Nigel Deakin [ 03/Sep/13 ]

@John D. Ament: The changes in JCA 1.7 (which allow the resource adapter to query the methods and annotations on the endpoint class) would allow us to define a MDB which has JMS-specific method annotations to define the callback method, the queue or topic, and other consumer parameters. We already have JMS_SPEC-116 (which you logged) to cover that, and I mentioned this as point (3) in my comment above.

However Reza's issue here is introducing some additional features, which I listed as points (1) and (2) above. These would depend on changes in the EJB spec, which Reza has logged as EJB_SPEC-113. I think that CDI changes may also be needed.

We might actually be able to develop this in two stages.

  • The first stage could be JMS_SPEC-116 which would define new JMS-specific method annotations which removed the dependence of a JMS MDB on javax.jms.MessageListener whilst keeping keep the same MDB lifecycle model.
  • The second stage could be to define class annotations which would replace or extend MessageDriven and allowed the listener lifecycle to reflect CDI scopes, without losing the key concept of the listener invoking a pool of endpoints. I suspect these class annotations would need to be be defined in the EJB (or CDI) specs and would be generalised to cover cases other than JMS.

@John D. Ament: I think allowing "JMS listener beans" to have a defined scope would help with your multi-tenancy requirements. For example the use of dependent scope would allow them to have the same lifecycle as some tenant-specific application object. You also make some suggestions which would allow applications to dynamically generate Queue objects on a per-tenant basis. I think it would be worth you logging as a separate issue, since it isn't specific to async listeners but would be needed for sending messages and sync consumers as well. That said, explicit JMS support for multi-tenancy needs to take its lead from the Java EE platform spec. That's where multi-tenancy requirements should be raised initially (and obviously it's early days for Java EE 8 currently).

Comment by Bruno Borges [ 03/Oct/13 ]

I'd prefer to simply go with JMS_SPEC-100 for next version of JMS, until we are certain about Cloud use cases.

Comment by clebertsuconic [ 03/Oct/13 ]

I don't see a relation between JMS_SPEC-100 and this...

Cloud use cases AFAIK are more about multi-tenant support. I don't see that as a stopper on this. Or am I missing something?

Comment by reza_rahman [ 03/Oct/13 ]

I do agree that it is not necessary to delay this for the clouds to clear . In fact, I think the fundamental programming model is flexible enough such that it could be easily adapted later on to make into account dynamic destination creation, multi-tenancy, etc.

With regards to https://java.net/jira/browse/JMS_SPEC-100, I think the overlap is a good indication that the current MDB model really does need to be revisited. The reason I did not build upon it is because I felt it did not really take full advantage of the opportunity to revisit the entire programming model, still has a very over-generalized JCA/EJB/MDB centric syntax and did not have sufficient technical detail (with all due respect/credit to Bruno - technical detail is not an easy thing from a non container implementer perspective).

Comment by clebertsuconic [ 03/Oct/13 ]

We should seriously look into that. People are already taking this approach (look at Camel for instance).. If we keep banging the MDB route, it will become less and less relevant to our users.

We need something more programmers friendly like this IMHO.





[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-132] FR javadocs are out of sync Created: 25/Jun/13  Updated: 25/Jun/13

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

Type: Bug Priority: Major
Reporter: John D. Ament Assignee: Nigel Deakin
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

When I visit

http://download.oracle.com/otndocs/jcp/jms-2_0-fr-eval-spec/index.html

the javadocs available here are out of sync. For example, they are missing JMSContext#createContext(int sessionMode).

Not sure if other content is missing.



 Comments   
Comment by Nigel Deakin [ 25/Jun/13 ]

(I tried to download this and got a permissions error. I reported this and it seems to have gone away).

If I now download the javadocs from the location specified they look OK and include a javadoc comment for
javax/jms/JMSContext.html#createContext(int). Can you download it again and check?





[JMS_SPEC-131] Allow client-acknowledgement and local transactions to be used in the Java EE web and EJB container Created: 18/Jun/13  Updated: 18/Jun/13

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

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

Issue Links:
Related
is related to JMS_SPEC-129 Resolve some undefined use cases when... Open
Tags: jms21-forreview-major

 Description   

The JMS 2.0 specification, section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" states that if a Session or JMSContext is created when there is no active JTA transaction in progress, then the Session or JMSContext that is created will be non-transacted and any messages received will be automatically acknowledged.

The specification states that the use of local transactions or client acknowledgement is not permitted. A session parameter may be used to specify whether the acknowledgement mode should be AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE, but any other values will be ignored.

Issue: When there is no application server transaction (or if the Session or JMSContext has opted out of the JTA transaction if allowed by JMS_SPEC-130), should client-acknowledgement or local transactions be permitted?

If so, we would need to define an appropriate API by which the application specifies this. We can't use the existing parameters to createSession and createContext for this purpose since these must be ignored in accordance with the EJB 3.1 specification).



 Comments   
Comment by Nigel Deakin [ 18/Jun/13 ]

Historical background behind the current restrictions

The current restrictions precede JMS 2.0 and were defined in EJB 3.1 (and possible earlier versions). In EJB 3.1, 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... methods are ignored."

The same section 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."

JMS 2.0 took the view that the reference to "message acknowledgement" being "handled by the container" forbade use of both the Session.acknowledge() and the Session.commit() methods, since they both perform message acknowledgement. However EJB 3.1 did not explicitly mention the Session.commit() method.

Rationale behind the current restrictions

In an email exchange with one of the original authors of the JMS specification it was stated that the reason for not allowing client-acknowledgement (and presumably local transactions) was that it should be possible to change the transactional behaviour of an application my modifying the deployment descriptor without the need to change the code.

However this really only applies for container-managed transactions. A bean-managed transaction is, by definition, defined in the code.

Additional restriction when using an injected JMSContext

JMS 2.0 explicitly forbids the use of client acknowledgement or local transactions in an injected JMSContext object. This restriction is additional to the restrictions on the use of Session (and now JMSContext) objects defined in the EJB specification, and is imposed because an injected JMSContext needs to be "stateless" to avoid users getting confused by the same JMSContext object being used in multiple components within the same scope.

Imagine a user creates two EJBs (or other Java EE components such as a servlet or CDI bean) and injects a JMSContext into each, using the same annotations. If the two EJBs are used within the same transaction, or, if there is no transaction, within the same request, then the two injected JMSContext fields will (in accordance with expected CDI behaviour) refer to the same object. This means that calling a method such as acknowledge() or commit() on one JMSContext field would have an effect on the other JMSContext field. It was decided that this was potentially confusing and a possible cause of errors, especially if the two EJBs were developed by different people. To avoid this confusion it was decided to simply disallow the use of client-acknowledgement or local transactions on an injected JMSContext.

Since client-acknowledgement and local transactions were not allowed in a EJB or web application anyway, restricting their use on an injected JMSContext did not introduce any additional limitations. However this means that even if the specification was relaxed in the future to allow client-acknowledgement and local transactions in Java EE applications it would still be necessary to restrict their use when the JMSContext was injected unless the goal of making a JMSContext stateless was abandoned.





[JMS_SPEC-130] Allow a JMSContext or Session to opt out of a Java EE transaction Created: 18/Jun/13  Updated: 18/Jun/13

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

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

Issue Links:
Related
is related to JMS_SPEC-129 Resolve some undefined use cases when... Open
Tags: jms21-forreview-major

 Description   

The JMS 2.0 specification, section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" states that if a Session or JMSContext is created when there is an active JTA transaction in progress then any session parameters are ignored and the Session or JMSContext will participate in the JTA transaction and will be committed or rolled back when the JTA transaction is committed or rolled back.

The specification doesn't appear to offer any choice as to whether the Session or JMSContext participates in the JTA transaction.

Issue: Should it be possible for the Session or JMSContext to "opt out" of the transaction in some way?

Here are some circumstances in which the JTA transaction might be ignored:

  • If the JMS provider doesn't support XA. The specification is not clear on whether a JMS provider is required to support XA in the Java EE web and EJB containers. In JMS 2.0, section 6.2.8 "Distributed transactions" states that "JMS does not require that a provider support distributed transactions". However this wording dates from JMS 1.1 and it is possible that this statement is intended to apply only to standalone JMS providers which don't support Java EE. This should be clarified.
  • If the connection factory has been configured to not use a JTA transaction. Here are some possible ways in which a conneciton factory might be configured to not use JTA:
    • Using a JMSConnectionFactoryDefinition annotation with the transactional attribute set to false. (The javadocs says that this attribute may be "Set to false if connections should not participate in transactions.
    • Using a connection factory which has been configured in a provider-specific manner to not use JTA transaction.
    • By some standard mechanism, not yet defined, either on the connection factory or the deployment descriptor (see below)
    • By some new parameter to createSession or createContext. (We can't use the existing parameters since these must be ignored in accordance with the EJB 3.1 specification)

If the Session or JMSContext is allowed to opt out of the JTA transaction, then we could define that it behave the same way as a Session or JMSContext that is created when there is no JTA transaction (i.e. only AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE are allowed).

However another possibility is to further extend the specification to allow client-acknowledgement or a local transactions to be used. I think that can be discussed as a separate issue and I have created JMS_SPEC-131 to cover it.






[JMS_SPEC-129] Resolve some undefined use cases when using Java EE transactions Created: 18/Jun/13  Updated: 22/Aug/13

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

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

Issue Links:
Related
is related to JMS_SPEC-130 Allow a JMSContext or Session to opt ... Open
is related to JMS_SPEC-131 Allow client-acknowledgement and loca... Open
Tags: jms21-forreview-major

 Description   

Case 1

The JMS 2.0 specification, section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" states that if a Session or JMSContext is created when there is an active JTA transaction in progress then the Session or JMSContext will participate in the JTA transaction and will be committed or rolled back when the JTA transaction is committed or rolled back.

However the specification also states that "if a Session or JMSContext is created when there is an active JTA transaction but is subsequently used to send or receive messages when there is no active JTA transaction then the behaviour is undefined".

Issue 1: Can we define what should happen if a Session or JMSContext is created in a JTA transaction but is used to send or receive a message after the JTA transaction has been committed or rolled back?

Here's a simple example:

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {
   
      // start a transaction   
      ut.begin();

      // create JMSContext when there is a transaction                      
      JMSContext context = connectionFactory.createContext();

      // commit the transaction
      ut.commit();
      
      // what happens here?            
      context.createProducer().send(queue,"Hello world");
 
      context.close();
   }
}

There appear to be three possibilities:

  • This is a programming error and the use of the JMSContext (or Session) outside of the transaction should throw an exception
  • Any messages sent or received outside of the transaction will be non-transacted and automatically-acknowledged
  • The behaviour must remain undefined

Does it matter if the transaction was rolled back in another thread? (if this is a possible use case).

What happens if we then start a second transaction and use the same JMSContext to send or receive a message (as in the example below)?

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {
   
      // start a transaction   
      ut.begin();

      // create JMSContext when there is a transaction                      
      JMSContext context = connectionFactory.createContext();

      // commit the transaction
      ut.commit();
      
      context.createProducer().send(queue,"Hello world");

      // start a second transaction   
      ut.begin();

      // is this valid?          
      context.createProducer().send(queue,"Hello world");

      // commit the transaction
      ut.commit();
 
      context.close();
   }
}

Case 2

Conversely, the JMS 2.0 specification states that if a Session or JMSContext is created when there is no active JTA transaction in progress, then the Session or JMSContext that is created will be non-transacted and any messages received will be automatically acknowledged.

However the specification also states that "if a Session or JMSContext is created when there is no active JTA transaction but subsequently used to send or receive messages when there is an active JTA transaction then the behaviour is undefined."

Issue 2: Can we define what should happen if a Session or JMSContext is created when there is no JTA transaction but is used to send or receive a message when there is an active JTA transaction?

Here's a simple example:

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {

      // create JMSContext when there is no transaction                      
      JMSContext context = connectionFactory.createContext();

      // now start a transaction
      ut.begin();
      
      // is this message part of the transaction or not?             
      context.createProducer().send(queue,"Hello world");

      // now commit the transaction
      ut.commit();

      context.close();
   }
}

There appear to be four possibilities:

  • This is a programming error and the use of the JMSContext (or Session) outside of the transaction should throw an exception
  • Any messages sent or received whilst there is a JTA transaction must participate in the transaction
  • Any messages sent or received whilst there is a JTA transaction must not participate in the transaction.
  • This must remain undefined


 Comments   
Comment by John D. Ament [ 18/Jun/13 ]

Equivalently, what happens in EJB when this occurs?

Comment by Nigel Deakin [ 18/Jun/13 ]

John, can you please clarify your question? This issue affects any Java EE component that the UserTransaction API.

N.B. I'm going to log some more issues shortly on related issues.

Comment by Nigel Deakin [ 18/Jun/13 ]

Added some code examples to the initial issue description

Comment by Nigel Deakin [ 18/Jun/13 ]

Updated summary field.

Comment by Nigel Deakin [ 22/Aug/13 ]

The same issues arise for container-managed transactions.

Issue 1 also arises for container-managed transactions as follows: Imagine a stateful session bean with two business methods. The first method has a transactional attribute REQUIRED. This creates a JMSContext or Session and saves it in a field. The second method has a transactional attribute NOT_SUPPORTED. This method uses that JMSContext or Session to send a message. A client calls the first method and then the second.

Issue 2 also arises for container-managed transactions as follows: Imagine a stateful session bean with two business methods. The first method has a transactional attribute NOT_SUPPORTED. This creates a JMSContext or Session and saves it in a field. The second method has a transactional attribute REQUIRED. This method uses that JMSContext or Session to send a message. A client calls the first method and then the second.





[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-127] Incorrect HTML in API documentation Created: 29/May/13  Updated: 20/Nov/14

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

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

Tags: jms20-errata

 Description   

There are some HTML errors in the released JMS 2.0 documentation at
https://jms-spec.java.net/2.0/apidocs/index.html

For example, in the javadoc for Message:
https://jms-spec.java.net/2.0/apidocs/javax/jms/Message.html

The JMS API reserves the JMS_<I>vendor_name</I> property
<I>arithmetic-expr1</I> [NOT] BETWEEN <I>arithmetic-expr2</I> AND <I>arithmetic-expr3</I> (comparison operator)

"age&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19" is equivalent to "age&nbsp;>=&nbsp;15&nbsp;AND&nbsp;age&nbsp;<=&nbsp;19"
"age&nbsp;NOT&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19" is equivalent to "age&nbsp;<&nbsp;15&nbsp;OR&nbsp;age&nbsp;>&nbsp;19" 

The spurious <I> and &nbsp characters are caused by @code constructs containing HTML which is getting escaped by the javadoc program.



 Comments   
Comment by Nigel Deakin [ 29/May/13 ]

Changes to Message:

--- jms2.0/src/main/java/javax/jms/Message.java (revision 282)
+++ jms2.0/src/main/java/javax/jms/Message.java (working copy)
@@ -235,9 +235,9 @@
   * Unless specifically noted, the values and semantics of the JMSX properties
   * are undefined.
   *
-  * <P>The JMS API reserves the {@code JMS_<I>vendor_name</I>} property
+  * <P>The JMS API reserves the <CODE>JMS_<I>vendor_name</I></CODE> property
   * name prefix for provider-specific properties. Each provider defines its own
-  * value for {@code <I>vendor_name</I>}. This is the mechanism a JMS
+  * value for <CODE><I>vendor_name</I></CODE>. This is the mechanism a JMS
   * provider uses to make its special per-message services available to a JMS
   * client.
   *
@@ -399,70 +399,70 @@
   *     <LI>Arithmetic operations must use numeric promotion in the Java
   *         programming language.
   *   </UL>
-  *   <LI>{@code <I>arithmetic-expr1</I> [NOT] BETWEEN <I>arithmetic-expr2</I>
-  *       AND <I>arithmetic-expr3</I>} (comparison operator)
+  *   <LI><CODE><I>arithmetic-expr1</I> [NOT] BETWEEN <I>arithmetic-expr2</I>
+  *       AND <I>arithmetic-expr3</I></CODE> (comparison operator)
   *   <UL>
-  *     <LI>{@code "age&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19"} is
+  *     <LI><CODE>"age&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19"</CODE> is
   *         equivalent to
-  *         {@code "age&nbsp;>=&nbsp;15&nbsp;AND&nbsp;age&nbsp;<=&nbsp;19"}
-  *     <LI>{@code "age&nbsp;NOT&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19"}
+  *         <CODE>"age&nbsp;>=&nbsp;15&nbsp;AND&nbsp;age&nbsp;<=&nbsp;19"</CODE>
+  *     <LI><CODE>"age&nbsp;NOT&nbsp;BETWEEN&nbsp;15&nbsp;AND&nbsp;19"</CODE>
   *         is equivalent to
-  *         {@code "age&nbsp;<&nbsp;15&nbsp;OR&nbsp;age&nbsp;>&nbsp;19"}
+  *         <CODE>"age&nbsp;<&nbsp;15&nbsp;OR&nbsp;age&nbsp;>&nbsp;19"</CODE>
   *   </UL>
-  *   <LI>{@code <I>identifier</I> [NOT] IN (<I>string-literal1</I>,
-  *       <I>string-literal2</I>,...)} (comparison operator where
-  *       {@code <I>identifier</I>} has a {@code String} or
-  *       {@code NULL} value)
+  *   <LI><CODE><I>identifier</I> [NOT] IN (<I>string-literal1</I>,
+  *       <I>string-literal2</I>,...)</CODE> (comparison operator where
+  *       <CODE><I>identifier</I></CODE> has a <CODE>String</CODE> or
+  *       <CODE>NULL</CODE> value)
   *   <UL>
-  *     <LI>{@code "Country&nbsp;IN&nbsp;('&nbsp;UK',&nbsp;'US',&nbsp;'France')"}
+  *     <LI><CODE>"Country&nbsp;IN&nbsp;('&nbsp;UK',&nbsp;'US',&nbsp;'France')"</CODE>
   *         is true for
-  *         {@code 'UK'} and false for {@code 'Peru'}; it is
+  *         <CODE>'UK'</CODE> and false for <CODE>'Peru'</CODE>; it is
   *         equivalent to the expression
-  *         {@code "(Country&nbsp;=&nbsp;'&nbsp;UK')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;US')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;France')"}
-  *     <LI>{@code "Country&nbsp;NOT&nbsp;IN&nbsp;('&nbsp;UK',&nbsp;'US',&nbsp;'France')"}
-  *         is false for {@code 'UK'} and true for {@code 'Peru'}; it
+  *         <CODE>"(Country&nbsp;=&nbsp;'&nbsp;UK')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;US')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;France')"</CODE>
+  *     <LI><CODE>"Country&nbsp;NOT&nbsp;IN&nbsp;('&nbsp;UK',&nbsp;'US',&nbsp;'France')"</CODE>
+  *         is false for <CODE>'UK'</CODE> and true for <CODE>'Peru'</CODE>; it
   *         is equivalent to the expression
-  *         {@code "NOT&nbsp;((Country&nbsp;=&nbsp;'&nbsp;UK')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;US')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;France'))"}
-  *     <LI>If identifier of an {@code IN} or {@code NOT IN}
-  *         operation is {@code NULL}, the value of the operation is
+  *         <CODE>"NOT&nbsp;((Country&nbsp;=&nbsp;'&nbsp;UK')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;US')&nbsp;OR&nbsp;(Country&nbsp;=&nbsp;'&nbsp;France'))"</CODE>
+  *     <LI>If identifier of an <CODE>IN</CODE> or <CODE>NOT IN</CODE>
+  *         operation is <CODE>NULL</CODE>, the value of the operation is
   *         unknown.
   *   </UL>
-  *   <LI>{@code <I>identifier</I> [NOT] LIKE <I>pattern-value</I> [ESCAPE
-  *       <I>escape-character</I>]} (comparison operator, where
-  *       {@code <I>identifier</I>} has a {@code String} value;
-  *       {@code <I>pattern-value</I>} is a string literal where
-  *       {@code '_'} stands for any single character; {@code '%'}
+  *   <LI><CODE><I>identifier</I> [NOT] LIKE <I>pattern-value</I> [ESCAPE
+  *       <I>escape-character</I>]</CODE> (comparison operator, where
+  *       <CODE><I>identifier</I></CODE> has a <CODE>String</CODE> value;
+  *       <CODE><I>pattern-value</I></CODE> is a string literal where
+  *       <CODE>'_'</CODE> stands for any single character; <CODE>'%'</CODE>
   *       stands for any sequence of characters, including the empty sequence;
   *       and all other characters stand for themselves. The optional
-  *       {@code <I>escape-character</I>} is a single-character string
+  *       <CODE><I>escape-character</I></CODE> is a single-character string
   *       literal whose character is used to escape the special meaning of the
-  *       {@code '_'} and {@code '%'} in
-  *       {@code <I>pattern-value</I>}.)
+  *       <CODE>'_'</CODE> and <CODE>'%'</CODE> in
+  *       <CODE><I>pattern-value</I></CODE>.)
   *   <UL>
-  *     <LI>{@code "phone&nbsp;LIKE&nbsp;'12%3'"} is true for
-  *         {@code '123'} or {@code '12993'} and false for
-  *         {@code '1234'}
-  *     <LI>{@code "word&nbsp;LIKE&nbsp;'l_se'"} is true for
-  *         {@code 'lose'} and false for {@code 'loose'}
-  *     <LI>{@code "underscored&nbsp;LIKE&nbsp;'\_%'&nbsp;ESCAPE&nbsp;'\'"}
-  *          is true for {@code '_foo'} and false for {@code 'bar'}
-  *     <LI>{@code "phone&nbsp;NOT&nbsp;LIKE&nbsp;'12%3'"} is false for
-  *         {@code '123'} or {@code '12993'} and true for
-  *         {@code '1234'}
-  *     <LI>If {@code <I>identifier</I>} of a {@code LIKE} or
-  *         {@code NOT LIKE} operation is {@code NULL}, the value
+  *     <LI><CODE>"phone&nbsp;LIKE&nbsp;'12%3'"</CODE> is true for
+  *         <CODE>'123'</CODE> or <CODE>'12993'</CODE> and false for
+  *         <CODE>'1234'</CODE>
+  *     <LI><CODE>"word&nbsp;LIKE&nbsp;'l_se'"</CODE> is true for
+  *         <CODE>'lose'</CODE> and false for <CODE>'loose'</CODE>
+  *     <LI><CODE>"underscored&nbsp;LIKE&nbsp;'\_%'&nbsp;ESCAPE&nbsp;'\'"</CODE>
+  *          is true for <CODE>'_foo'</CODE> and false for <CODE>'bar'</CODE>
+  *     <LI><CODE>"phone&nbsp;NOT&nbsp;LIKE&nbsp;'12%3'"</CODE> is false for
+  *         <CODE>'123'</CODE> or <CODE>'12993'</CODE> and true for
+  *         <CODE>'1234'</CODE>
+  *     <LI>If <CODE><I>identifier</I></CODE> of a <CODE>LIKE</CODE> or
+  *         <CODE>NOT LIKE</CODE> operation is <CODE>NULL</CODE>, the value
   *         of the operation is unknown.
   *   </UL>
-  *   <LI>{@code <I>identifier</I> IS NULL} (comparison operator that tests
+  *   <LI><CODE><I>identifier</I> IS NULL</CODE> (comparison operator that tests
   *       for a null header field value or a missing property value)
   *   <UL>
-  *     <LI>{@code "prop_name&nbsp;IS&nbsp;NULL"}
+  *     <LI><CODE>"prop_name&nbsp;IS&nbsp;NULL"</CODE>
   *   </UL>
-  *   <LI>{@code <I>identifier</I> IS NOT NULL} (comparison operator that
+  *   <LI><CODE><I>identifier</I> IS NOT NULL</CODE> (comparison operator that
   *       tests for the existence of a non-null header field value or a property
   *       value)
   *   <UL>
-  *     <LI>{@code "prop_name&nbsp;IS&nbsp;NOT&nbsp;NULL"}
+  *     <LI><CODE>"prop_name&nbsp;IS&nbsp;NOT&nbsp;NULL"</CODE>
   *   </UL>
   *
   * <P>JMS providers are required to verify the syntactic correctness of a
@@ -1349,8 +1349,8 @@
       *
       * <P>This method can be used to return, in objectified format,
       * an object that has been stored as a property in the message with the
-      * equivalent {@code setObjectProperty} method call, or its equivalent
-      * primitive {@code set<I>type</I>Property} method.
+      * equivalent <CODE>setObjectProperty</CODE> method call, or its equivalent
+      * primitive <CODE>set<I>type</I>Property</CODE> method.
       *
       * @param name the name of the Java object property
       *
Comment by Nigel Deakin [ 29/May/13 ]

Changes to JMSProducer

--- src/main/java/javax/jms/JMSProducer.java	(revision 282)
+++ src/main/java/javax/jms/JMSProducer.java	(working copy)
@@ -1015,7 +1015,7 @@
 	 * This method can be used to return, in objectified format, an object that
 	 * has been stored as a property in the message with the equivalent
 	 * {@code setObjectProperty} method call, or its equivalent primitive
-	 * {@code set<I>type</I>Property} method.
+	 * <code>set<I>type</I>Property</code> method.
 	 * 
 	 * @param name
 	 *            the name of the property
Comment by Nigel Deakin [ 29/May/13 ]

Changes to MapMessage:

--- src/main/java/javax/jms/MapMessage.java	(revision 282)
+++ src/main/java/javax/jms/MapMessage.java	(working copy)
@@ -269,7 +269,7 @@
       * an object in the Java programming language ("Java object") that had 
       * been stored in the Map with the equivalent
       * {@code setObject} method call, or its equivalent primitive
-      * {@code set<I>type</I>} method.
+      * <code>set<I>type</I></code> method.
       *
       * <P>Note that byte values are returned as {@code byte[]}, not 
       * {@code Byte[]}.
Comment by Nigel Deakin [ 29/May/13 ]

Changes to StreamMessage

--- src/main/java/javax/jms/StreamMessage.java	(revision 282)
+++ src/main/java/javax/jms/StreamMessage.java	(working copy)
@@ -331,7 +331,7 @@
       * an object in the Java programming language ("Java object") that has 
       * been written to the stream with the equivalent
       * {@code writeObject} method call, or its equivalent primitive
-      * {@code write<I>type</I>} method.
+      * <code>write<I>type</I></code> method.
       *  
       * <P>Note that byte values are returned as {@code byte[]}, not 
       * {@code Byte[]}.




[JMS_SPEC-126] API to allow app servers to implement JMSContext without needing an additional connection pool Created: 20/May/13  Updated: 11/Oct/13

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

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

Tags: jms20-bug

 Description   

The problem

In JMS 2.0, chapter 11 "JMS application server facilities" defines some optional API which may be used by application servers to allow them to support any compliant JMS provider. Some application servers use this API directly whilst some use this API to implement a portable resource adapter.

Application servers or resource adapters that use this API typically maintain a pool of the JMS provider's Connection objects. To support this, they wrap the JMS provider's ConnectionFactory object so that a call to createConnection does not create a new Connection object but instead fetches one from a pool. They also wrap the JMS provider's Connection object so that a call to the close method does not close the connection but instead simply returns it to the pool.

The introduction of the JMSContext object in JMS 2.0 has complicated matters. Since a JMSContext contains a connection then an obvious approach is to maintain a separate pool of JMSContext objects. In such an implementation, the application server or resource adapter would wrap the JMS provider's ConnectionFactory object so that a call to createContext does not create a new JMSContext object but instead fetches one from a pool. It also would wrap the JMS provider's JMSContext object so that a call to the close method does not close the JMSContext but instead simply returns it to the pool.

However this approach requires the application server or resource adapter to maintain two separate pools of objects: a pool of Connection objects and a separate pool of JMSContext objects. This means that for every JMS application, in addition to configuring a Connection pool the user would also need to configure a JMSContext pool. This would be more complicated to administer. It would also be inefficient since a Connection that is released to the pool by a call to connection.close() could only be reused by an application that subsequently calls createConnection to create a Connection. It could not be reused by an application that subsequently called createContext to create a JMSContext.

The solution

This complication can be avoided by defining a new method which allows a JMSContext to be created using a connection that was fetched from the normal connection pool. As with the the existing methods for application server integration, implementing this method would be optional.

New method Connection#createContextForEE(Session s)

JMS providers would be required to implement a new method on Connection with the following signature:
JMSContext createContextForEE(Session session);

This method would simply create a new JMSContext using the specified connection and session.

This method would be for application server or resource adapter use only. The name createContextForEE is intended to discourage naive users from using it accidentally. The application server or resource adapter's implementation of the createContextForEE method on Connection would be encouraged to always throw an exception.

This new method would be used by the application server or resource adapter's ConnectionFactory implementation of createContext as follows:

1. Calls this.createConnection() to create a RA-implemented Connection which wraps a provider-implemented Connection. This would typically fetch the provider-implemented Connection from a pool.

2. Calls the RA-implemented Connection's createSession(sessionMode) method to create a RA-implemented Session which wraps a provider-implemented Session. If the RA-implemented Connection's createSession(sessionMode) method enforced the requirement that you can only create one session on a connection in a Java EE web or EJB container, then this check would be applied here. This also allows the RA-implemented Connection's createSession method to cache the provider-implemented Session if it wants to

3. Calls the provider-implemented Connection's createContext(connection,session) method (the new method we're defining here) to create the provider-implemented {{JMSContext }}object

4. Wraps the provider-implemented JMSContext object in a RA-implemented JMSContext

5. Returns the RA-implemented JMSContext to the application

The RA's JMSContext implementation would be a proxy for the JMS provider's JMSContext implementation and could delegate almost all behaviour to it. The exception to this would be the close method. This needs to be overridden so that instead of closing the session and connection it does whatever behaviour is already implemented when a wrapped session and connection is closed. So the RA's JMSContext implementation would override close as follows:

1. Calls the provider-implemented JMSContext's closeForEE() method. This is a new method (described below) offering the same behaviour as the close method but without closing the the underlying session and connection.

2. Calls the RA-implemented Session's close method. This can do whatever it does now, such as leaving the session open and cached with the connection.

2. Calls the RA-implemented Connection's close method. This can do whatever it does now, such as leaving the connection open and returning it to a pool.

New method JMSContext#closeForEE()

This method offers the same behaviour as the JMSContext close method but without closing the underlying session and connection.

It is intended to be called from an application server or resource adapter's implementation of the close method,
and so must provide the same behaviour to the application as is defined for the JMSContext close method.

This includes waiting for any receive call or message listener callback to return,
and for any incomplete asynchronous send operations for this JMSContext to be completed, including waiting for any CompletionListener callbacks to return.

It also includes ensuring that any subsequent call to acknowledge on a message received using this JMSContext causes an IllegalStateException to be thrown.

Again this method would be for application server or resource adapter use only. The name closeForEE is intended to discourage naive users from using it accidentally. The application server or resource adapter's implementation of the closeForEE method on JMSContext would be encouraged to always throw an exception.

It should be seen that this method does more than simply clean up state. It actually need to behave just the same as calling JMSContext#close since that's the method that the application will have called. The same issue applies for application servers and resource adapters that cache the JMS provider's session and connection objects in a pool and provide the application with wrappers around them. These need to be able to implement close without actually closing the object. This suggests that methods similar to closeForEE are needed on Session and Connection as well:

New method Session#closeForEE()

This method offers the same behaviour as the Session close method but without closing the session.
It is intended to be called from an application server or resource adapter's implementation of the close method,
and so must provide the same behaviour to the application as is defined for the Session close method.

This includes waiting for any receive call or message listener callback to return, and for any incomplete asynchronous send operations for this Session to be completed including waiting for any CompletionListener callbacks to return.

It also includes ensuring that any subsequent call to acknowledge on a message received using this Session causes an IllegalStateException to be thrown.

Again this method would be for application server or resource adapter use only. The name closeForEE is intended to discourage naive users from using it accidentally. The application server or resource adapter's implementation of the closeForEE method on JMSContext would be encouraged to always throw an exception.

New method Connection#closeForEE()

This method offers the same behaviour as the Connection close method but without closing the connection.
It is intended to be called from an application server or resource adapter's implementation of the close method,
and so must provide the same behaviour to the application as is defined for the Connection close method.

This includes waiting for any receive call or message listener callback to return, and for any incomplete asynchronous send operations for this Connection to be completed including waiting for any CompletionListener callbacks to return.

It also includes ensuring that any subsequent call to acknowledge on a message received using this Connection causes an IllegalStateException to be thrown.

Again this method would be for application server or resource adapter use only. The name closeForEE is intended to discourage naive users from using it accidentally. The application server or resource adapter's implementation of the closeForEE method on JMSContext would be encouraged to always throw an exception.

Naming considerations

An alternative name for closeForEE could be closeForPooling.

Alternatively some new interfaces could be defined which contain these new methods. This probably makes things too complicated but is included here for discussion.

A new interface PoolableConnection could be defined with two methods createContext(Session s) and closeForPooling. There would be a new method Connection#getPoolableConnection to obtain an instance of this interface from the Connection.

A new interface PoolableJMSContext could be defined with one method {closeForPooling}}. There would be a new method JMSContext#getPoolableJMSContext to obtain an instance of this interface from the JMSContext.

A new interface PoolableSession could be defined with one method {closeForPooling}}. There would be a new method JMSContext#getPoolableSession to obtain an instance of this interface from the Session.



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

Here's another idea: instead of Connection#createContextForEE(Session s) we could have Session#createContextForEE(). Both give the application server or resource adapter control over the creation of the connection and session.

Comment by clebertsuconic [ 12/Sep/13 ]

Is this really needed? all we care so for is pool the connection. a JMSContext instance should be pretty cheap to just be GCed... the JMSContext is always getting a Connection from the pool, in which case it should either reuse a previous connection or create a new one when needed.

I understand there could be an implementation mistake where this would end up being created every time. But I think it can be fixed using the current spec pretty easily without adding API changes.

Comment by clebertsuconic [ 12/Sep/13 ]

closeForEE.. I don't think that's needed as well? just reference counting and other implementation details can fix that. It seems to be fixable with implementation details rather than with API changes. maybe I'm missing something there?

Comment by clebertsuconic [ 12/Sep/13 ]

Also: with EE you only have one JMSContext. Someone could easily cache the instance on the Connection and just get it from there (if you really want to cache it).

Besides: I feel like javax.resource.spi.ManagedConnectionFactory and proper metadata would be enough to manage this.

I really feel this should be an implementation detail without requiring API changes.

Comment by Nigel Deakin [ 11/Oct/13 ]

These methods are needed to allow an application server to create JMSContext objects from existing pooled Connection (and Session) objects. Currently there is no standard API to do this.

Application servers can achieve this with their own JMS provider by using provider-specific API (that's what GlassFish does now). However if we want an application server to be able to achieve this with an arbitrary third-part JMS provider there needs to be a standard API for this.

There is definitely scope to debate the exact methods needed, but I think two new methods are needed (1) to create a JMSContext from a Connection and Session and (2) to do the reverse.

Comment by John D. Ament [ 11/Oct/13 ]

I personally don't see the point in doing this. Are you trying to say it should be possible for a third party to construct a JMSContext, on behalf of the application server?

Comment by Nigel Deakin [ 11/Oct/13 ]

This feature is proposed to for use in the following use cases:

(1) application servers which support third-party JMS providers directly (i.e. without using a resource adapter provided by the third party)

(2) resource adapters which support third-party JMS providers (i.e. JMS resource adapters which are not tied to a particular JMS provider but work with any JMS provider)

In these cases, when a Java EE 6 application calls connectionFactory.createConnection(), the application server or resource adapter currently intercepts this call and plucks a Connection out of the connection pool.

When a Java EE 7 application calls connectionFactory.createContext(), the application server or resource adapter will need to intercept this call and pluck a JMSContext out of the JMSContext pool. However this means that the application server will need to maintain a pool of JMSContext objects separate from the pool of Connection objects, which is potentially less efficient and gives the user something extra to configure.

This proposal is intended to avoid the need to create a second pool and allows the existing pool of Connection objects to be used both when the application calls createConnection() and when it calls createContext().

When a Java EE application calls connectionFactory.createContext(), the application server or resource adapter should be able to intercept this call, pluck a Connection out of the Connection pool, and then use the API proposed above to create a JMSContext from that Connection. There is no need to maintain a separate pool of JMSContext objects.

(Note that there'll be an opportunity to discuss this more thoroughly at the appropriate time; the comments on this issue make it clear that when that happens I'll need to explain carefully why I think this is a desirable feature).





[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-124] Sending a foreign message using a provider which does not support setJMSCorrelationIDAsBytes Created: 14/May/13  Updated: 14/May/13

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

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

Tags: jms21-forreview-minor

 Description   

It is optional whether a JMS provider supports the method setJMSCorrelationIDAsBytes on Message. This method is permitted to throw a java.lang.UnsupportedOperationException if the provider does not support this feature.

However there is an obscure case (which applies equally to JMS 1.1 and JMS 2.0) where the allowed behaviour is not specified. This is when a JMS provider is being used to send a message whose implementation is not its own (which JMS says must be allowed).

Imagine an application that receives a message from a JMS provider which supports native correlation ID values, and then sends the same message to a JMS provider which does not support them.

// receive message from JMS provider which supports native correlation ID values
MessageConsumer consumer = ....
Message message = consumer.receive(); 

// now call setJMSCorrelationIDAsBytes on the received message
// this will work as the provider supports native correlation ID values
message.setJMSCorrelationIDAsBytes(bytes);  

// now send this message using a JMS provider which does NOT support native correlation ID values
// should this throw a UnsupportedOperationException?
MessageProducer producer = ...
producer.send(message);  

There are two options here. Since the second JMS provider does not support native correlation ID values it must either throw a UnsupportedOperationException or simply ignore the value that was set.

The spec should be clarified to define the allowed behaviour.






[JMS_SPEC-123] JMSProducer#setJMSCorrelationIDAsBytes should be allowed to throw a java.lang.UnsupportedOperationException Created: 14/May/13  Updated: 14/May/13

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

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

Tags: jms20-bug

 Description   

In both JMS 1.1 and JMS 2.0, the method setJMSCorrelationIDAsBytes on Message is allowed to throw a java.lang.UnsupportedOperationException if the JMS provider does not support native correlation ID values. The javadoc states:

If a provider supports the native concept of correlation ID, a JMS client may need to assign specific JMSCorrelationID values to match those expected by native messaging clients. JMS providers without native correlation ID values are not required to support this method and its corresponding get method; their implementation may throw a java.lang.UnsupportedOperationException.

The same rule needs to be added to the method setJMSCorrelationIDAsBytes on JMSProducer. Its omission is as an error in the spec.






[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-121] Injection of JMSContext objects not possible in a WebSocket @OnMessage or @OnClose callback method Created: 07/May/13  Updated: 23/May/13

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

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

Issue Links:
Related
is related to WEBSOCKET_SPEC-196 WebSocket Spec does not define the ac... Open
Tags: jms20-bug

 Description   

If you inject a JMSContext into a websocket ServerEndpoint you can use it in the @OnOpen callback, but if you attempt to use it from the @OnMessage or @OnClose callbacks you get an exception from the CDI container because there is no valid request scope or transaction scope. From a user perspective it would seem reasonable to expect to be able to use an injected JMSContext in these places.

Here's an example of a websocket ServerEndpoint that injects a JMSContext:

@ServerEndpoint("/websocket")
public class SampleWebSocket {
    
    @Resource(lookup="java:comp/DefaultJMSConnectionFactory") ConnectionFactory cf;
    @Resource(lookup = "jms/myQueue") Queue myQueue;
    
    @Inject
    private JMSContext jmsContext;

    @OnOpen
    public void onOpen(final Session session) {
        // works OK as there is a valid request scope here
        context.createProducer().send(myQueue, message);
    }

    @OnMessage
    public void onMessage(final String message, final Session client) {
        // fails as there is no valid request scope here
        context.createProducer().send(myQueue, message);
    }

    @OnClose
    public void onClose(final Session session) {
        // fails as there is no valid request scope here
        context.createProducer().send(myQueue, message);
    }


 Comments   
Comment by Nigel Deakin [ 07/May/13 ]

JMS 2.0 defines an injected JMSContext to have transaction scope if there is a current transaction, and request scope otherwise. However neither scope is available in a websocket @OnMessage or @OnClose callback.

This seems to be an inconsistency in the CDI specification. Although there is no valid HTTP request during the @OnMessage and @OnClose callbacks, CDI already widens the definition of @RequestScoped to cover cases which have no relationship with HTTP. For example CDI 1.0 states that a MDB's onMessage method is executed within a request scope, even though there is no HTTP request involved. Now that WebSockets are part of Java EE 7 (JSR 356), it seems a bit arbitrary for a MDB callback to have a valid request scope, but for a WebSocket callback to not be.

I have asked the CDI expert group to consider whether a future version of CDI should extend the definition of @RequestScoped to include a WebSocket @OnMessage callback. This is https://issues.jboss.org/browse/CDI-370

If no such change is made, the JMS expert group may need to consider whether any changes are needed to the definition of the scope of an injected JMSContext.

Comment by John D. Ament [ 07/May/13 ]

A similar issue is currently floating around the CDI spec. This isn't an issue for CDI or JMS, but that WebSockets spec needs to indicate what contexts need to be activated (for example, regular CDI injections for any object that is request or transaction scoped are not injected either) for each of these annotated methods.

I haven't tested it yet, but I believe the work around will be to make your server endpoint a session bean (which makes it fall under the EJB spec) or to make the endpoint a standard CDI object.

Here's the link to the existing CDI issue: https://issues.jboss.org/browse/CDI-370

Comment by Bruno Borges [ 16/May/13 ]

I tried that John and it does not work. A different instance is created to the CDI context, besides the one for the ws endpoint.

Comment by Nigel Deakin [ 23/May/13 ]

Added link to WEBSOCKET_SPEC-196





[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-118] MessageListeners should be as simple as lambda expressions Created: 21/Mar/13  Updated: 10/May/13

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

Type: Improvement Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor

 Description   

It should be possible to define a lambda expression as a message listener, to avoid needing to implement the interface.

This of course would require using Java SE 8 in the runtime of a JMS provider.



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

Can you please say a bit more about what you have in mind?

javax.jms.MessageListener is a "functional interface" (with only one abstract method) so (if you're using Java SE 8) so even using the existing API you could specify a lambda expression instead of supplying a MessageListener implementation:

consumer.setMessageListener(
   m -> {String payload=m.getBody(string.class);
         System.out.println("Received message:"+payload);}
);




[JMS_SPEC-117] Specifying redelivery behaviour when a JMS MDB performs rollback Created: 21/Mar/13  Updated: 02/Apr/13

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

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

Issue Links:
Duplicate
is duplicated by MQ-220 Improvements in handling consecutive ... Closed
Tags: jms21-forreview-major

 Description   

It may be helpful if the spec defined what should happen if a JMS MDB receives a message and then rolls back the transaction, typically because setRollbackOnly has been called. If the rollback is caused by a system error (such as a database failure) then the same message might be redelivered and rolled back repeatedly.

Possible behaviour that might be required is:

  • A delay before the message is redelivered - perhaps increasing as the number of redelivery attempts increases
  • A maximum number of consecutive rollbacks after which the message will be delivered to a dead-message queue

No doubt there are other possibilities.

It would of course be necessary to allow this behaviour to be configured, perhaps using activation properties.



 Comments   
Comment by Nigel Deakin [ 02/Apr/13 ]

Comment from colleague TB:

I thought there were already some JIRAs in this area. As time permits, can you comment on whether the following related functionality is covered?

  • An equivalent to "setRollbackOnly" for non-TX MDB would be nice. E.g., a way to force redelivery without throwing
  • An equivalent to this JIRA issue for the MDB non-TX case (or extend the current JIRA).
  • An equivalent to this JIRA issue for pure JMS clients (or extend the current JIRA).

As for the latter, there are trade-offs between implementing rollback/recover side-effects at the JMS layer or the MDB layer. It looks like it would be helpful to consider both layers at the same time when spec'ing out this area.

JMS layer poison-messaging-handling can preserve the message-id and time-stamp, can treat both expired and redelivered messages using the same mechanism, can move the problem message to a new destination with optimal efficiency, and can move the message "exactly-once" to the error destination without requiring the client to be transactional. The MDB layer, on the other hand, can forward the message with a helpful "rollback reason" attached as a property, and can forward the failed message to any destination - not just destinations known to the original provider.





[JMS_SPEC-116] Take advantage of EJB 3.2's RA improvement for MDBs Created: 12/Mar/13  Updated: 28/Jul/15

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

Type: New Feature Priority: Major
Reporter: John D. Ament Assignee: Nigel Deakin
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-134 Declarative Annotation Based JMS List... Open
Tags: jms21-forreview-major, messagedriven, ra

 Description   

In a late change to the EJB 3.2 spec, a new feature around building MDBs without requiring method-level implementations has been added, specifically for use within the RA.

I am proposing that the JMS spec take advantage of this new feature in the following ways:

The description references this email thread from the EJB Spec: http://java.net/projects/ejb-spec/lists/jsr345-experts/archive/2013-03/message/49

1. Introduce a new interface "javax.jms.JMSMessageEndpoint" (or similar name) that can be used as a marker interface required by MessageEndpointFactory.getEndpointClass(). It shall have no methods, not extend any other interface but simply exist to be a marker that the given class will have its public methods exposed as potential targets for messages received by the RA.

2. Introduce a new annotation, or possibly several annotations, to represent the configuration available to these methods. I believe we should support something more fluid (e.g. compiler friendly) than the existing ActivationConfigProperty set.

3. Currently, the onMessage method is defined by looking for a method named "onMessage" that takes a "Message" object as an argument. This algorithm should be changed to also look for any instance of "JMSMessageEndpoint", find any method that is annotated as XXX (whatever is defined in 2) as a possible target, then depending on there being a match between that takes anything that derives from "Message" and only pass appropriate messages to it.

Some down sides:

1. The EG has already voted to not require an RA with every implementation.
2. This is a late change, so is the EJB equivalent.
3. Currently, MDB behavior and RA aren't necessarily defined within the JMS spec.



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

This interesting change comes too late to make any corresponding changes to JMS 2.0. I have added this issue to the list of issues which will be considered for JMS 2.1 and tagged it accordingly.

I'll also start a thread on the expert group to discuss this. Feel free to join in (or to contact me (Nigel) directly).

Comment by dblevins [ 26/Apr/15 ]

Hoping I can get some time to work on this in JMS 2.1. Adding some of the examples I've shown in presentations.

Before

Example JMS MDB with what we have up until EJB 3.1. It has some issues:

  • Only allows for a single method to consume messages. This results in an explosion of MDBs.
  • Loosely typed. The metadata is also passed via essentially a StringString map. Too easy to spell properties wrong or use the wrong argument format.
  • Undocumented. It isn't clear without a google search what the acceptable properties might be.
  • Overly generic method signature. Casting is required to do anything useful.
  • Unclear portability. Vendors may add properties, but it isn't clear from looking at the code which are portable.
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "maxSessions", propertyValue = "3"),
        @ActivationConfigProperty(propertyName = "maxMessagesPerSessions", propertyValue = "1"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "TASK.QUEUE")
})
public class BuildTasksMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {

            if (!(message instanceof ObjectMessage)) {
                throw new JMSException("Expected ObjectMessage, received " + message.getJMSType());
            }

            final ObjectMessage objectMessage = (ObjectMessage) message;

            final BuildTask buildTask = (BuildTask) objectMessage.getObject();

            doSomethingUseful(buildTask);

        } catch (JMSException e) {
            // Why can't I throw a JMS Exception
            throw new RuntimeException(e);
        }
    }

    // This is the only "useful" code in the class
    private void doSomethingUseful(BuildTask buildTask) {
        System.out.println(buildTask);
    }
}

After

Example JMS MDB with what we could do now with the changes added to EJB 3.2. Benefits:

  • Possible to consume multiple destinations in a single MDB
  • Strongly typed. You cannot misspell an annotation or use the wrong input type without a compile error.
  • Documented. Most IDEs allow you to easily explore the classes and annotations inside a package. Browse away and see your configuration choices.
  • User-defined method signature. If you need an ObjectMessage use it as the parameter. Better yet, use the value from inside the ObjectMessage as the parameter.
  • Clearer portability. Any annotations on the listener method not from javax.* are clearly vendor-specific
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.foo.Destination;
import javax.jms.foo.DestinationType;
import javax.jms.foo.MaxMessagesPerSession;
import javax.jms.foo.MaxSessions;
import javax.jms.foo.MessageType;

@MessageDriven
@MaxSessions(3)
@MaxMessagesPerSession(1)
public class BuildTasksMessageListener {

    @Destination("TASK.QUEUE")
    @DestinationType(javax.jms.Queue.class)
    @MessageType(ObjectMessage.class)
    public void processBuildTask(BuildTask buildTask) throws JMSException {

        System.out.println("Something useful " + buildTask);
    }

    @Destination("BUILD.TOPIC")
    @DestinationType(javax.jms.Topic.class)
    @MessageType(ObjectMessage.class)
    public void processBuildTask(BuildNotification notification) throws JMSException {

        System.out.println("Something happened " + notification);
    }

}

The actual annotations we use would of course be defined by the group, but this is just to get the creative juices flowing.

Comment by rdohna [ 01/May/15 ]

David,

Most of the annotations you proposed could be optional, all but @MessageDriven.

  • @MaxSessions and @MaxMessagesPerSession could be configured in the container (and have useful defaults).
  • @MessageType could be managed by the RA: If it's a text message, it could try to unmarshal it, e.g. by using a JAX-RS MessageBodyReader... this would probably require a Content-Type JMS message property. Even a MapMessage could be converted into an object when certain conventions are followed.
  • @DestinationType is a property of the destination. Adding it would just make sure it's correct; or it would allow the RA to actually create it on the fly.
  • @Destination could have a useful default: E.g. fully qualified class name of the MDB.

In the Message-API it's allowed to pass multiple arguments and the name of the method is used also, which is esp. handy when it's a verb with actual semantic (like delete). E.g. if the BuildTask has the properties jobName and revisionNumber and you want to start it, the method signature would be public void start(String jobName, long revisionNumber). If the message is a MapMessage, the names jobName and revisionNumber would be used to read a String and a long. If it's a TextMessage containing a xml body, it would look like <start><jobName>build</jobName><revisionNumber>1234243</revisionNumber></start>.

It's quite short, does it make sense? What do you think?

Comment by Nigel Deakin [ 28/Jul/15 ]

I have now published some proposals to address this issue.

The latest version (at the time of writing is)
https://java.net/projects/jms-spec/pages/JMSListener2

Comments are invited.





[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-113] Clarify the difference (if any) between JMSException.getLinkedException() and JMSException.getCause() Created: 08/Jan/13  Updated: 12/Feb/16

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

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

Tags: jms21-forreview-minor

 Description   

JMSException.getLinkedException() is usually containing the provider-specific Exception object, but there's also already the inherited Exception.getCause() method.
JMS Providers could potentially return different things in each method, which would be confusing.

Also, 'exception un-nesting code' would typically use Exception.getCause() multiple times until getCause() returns null to get to the root cause which then usually contains a better error description. Since this 'exception un-nesting code' could catch exceptions from multiple API's it would be nice if JMS behaves just like any other library (let getCause() return the cause of the exception).

My proposal would be to require JMS providers to implement JMSException.getCause() like this:

    @Override
    public Throwable getCause()
    {
        return getLinkedException();
    }

That way, JMS wouldn't play a special role when interpreting the cause of an exception.



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

Separately to this, the following comment was posted to users@jms-spec.java.net. I'm pasting it here so it can be considered as well. (Here's the direct link ):

I was wondering why JMSException does not support Java 1.4 exception chaining [1] (#getCause() vs. #getLinkedException()). It should be easy to retrofit (similar to InvocationTargetException) and reduce the confusion and potential for misuse. Also a constructor that takes a message string and a cause (like every other exception class) would be nice.

[1] http://docs.oracle.com/javase/1.4.2/docs/guide/lang/chained-exceptions.html

Cheers
Philippe

Comment by Nigel Deakin [ 11/Jan/13 ]

These are both interesting and valid comments. However now JMS 2.0 has reached the public draft stage we need to avoid adding new features if at all possible and as this feature is unrelated to any of the changes in JMS 2.0 I think we should defer considering until JMS 2.1. This will allow time for both issues to be considered properly.

Tagging appropriately.

Comment by braghest [ 01/Nov/15 ]

The following is an attempt at a patch:

  • implements #getCause() to return the linked exception, this is consistent the the proposal of axel_podehl and how InvocationTargetException has been retrofitted in 1.4
  • pass a cause to the super constructor, this is taken from InvocationTargetException and prevents calls to #initCause
  • add two new constructors which additionally take a cause/linked exception
  • the serialVersionUID is already present and remains unchanged
Index: jms2.1/src/main/java/javax/jms/JMSException.java
===================================================================
--- jms2.1/src/main/java/javax/jms/JMSException.java	(revision 345)
+++ jms2.1/src/main/java/javax/jms/JMSException.java	(working copy)
@@ -49,12 +49,15 @@
  *        the standard exception message and is available via the
  *        {@code getMessage} method.
  *   <LI> A provider-specific string error code 
- *   <LI> A reference to another exception. Often a JMS API exception will 
- *        be the result of a lower-level problem. If appropriate, this 
- *        lower-level exception can be linked to the JMS API exception.
  * </UL>
  * 
- * @version JMS 2.0
+ * <P><p>As of release 2.1, this exception has been retrofitted to conform to
+ * the general purpose exception-chaining mechanism. The "linked exception"
+ * that is accessed via the {@link #getLinkedException()} method is now known
+ * as the <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
+ * method, as well as the aforementioned "legacy method."
+ * 
+ * @version JMS 2.1
  * @since JMS 1.0
  * 
  **/
@@ -84,7 +87,7 @@
    **/
   public 
   JMSException(String reason, String errorCode) {
-    super(reason);
+    super(reason, null);  // Disallow initCause
     this.errorCode = errorCode;
     linkedException = null;
   }
@@ -96,10 +99,38 @@
    **/
   public 
   JMSException(String reason) {
-    super(reason);
+    super(reason, null);  // Disallow initCause
     this.errorCode = null;
     linkedException = null;
   }
+  
+  /** Constructs a {@code JMSException} with the specified reason 
+   *  error code and linked exception.
+   *
+   *  @param  reason        a description of the exception
+   *  @param  errorCode     a string specifying the vendor-specific
+   *                        error code
+   *  @param  ex            the linked {@code Exception}
+   **/
+  public 
+  JMSException(String reason, String errorCode, Exception ex) {
+    super(reason, null);  // Disallow initCause
+    this.errorCode = errorCode;
+    linkedException = ex;
+  }
+  
+  /** Constructs a {@code JMSException} with the specified reason and
+   * linked exception and with the error code defaulting to null.
+   *
+   *  @param  reason        a description of the exception
+   *  @param  ex            the linked {@code Exception}
+   **/
+  public 
+  JMSException(String reason, Exception ex) {
+    super(reason, null);  // Disallow initCause
+    this.errorCode = null;
+    linkedException = ex;
+  }
 
   /** Gets the vendor-specific error code.
    *  @return   a string specifying the vendor-specific
@@ -112,6 +143,10 @@
 
   /**
    * Gets the exception linked to this one.
+   * 
+   * <p>This method predates the general-purpose exception chaining facility.
+   * The {@link Throwable#getCause()} method is now the preferred means of
+   * obtaining this information.
    *
    * @return the linked {@code Exception}, null if none
   **/
@@ -128,4 +163,16 @@
   public void setLinkedException(Exception ex) {
       linkedException = ex;
   } 
+
+  /**
+   * Returns the cause of this exception (the thrown target exception,
+   * which may be {@code null}).
+   *
+   * @return  the cause of this exception.
+   * @since   2.1
+   */
+  @Override
+  public Throwable getCause() {
+    return (linkedException);
+  }
 }

Comment by braghest [ 12/Feb/16 ]

I just found out that EjbException#getCausedByException() was retrofitted in much the same way.





[JMS_SPEC-112] add Message.getJMSDeliveryCount() Created: 08/Jan/13  Updated: 11/Jan/13

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

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


 Description   

Since a JMSXDeliveryCount will be part of the JMS 2.0 requirement, also the Message interface should reflect this:

public long getJMSDeliveryCount() throws JMSException



 Comments   
Comment by Nigel Deakin [ 09/Jan/13 ]

JMS defines two different type of information which can be associated with a message (apart from the body): message headers and message properties. Message headers are accessed using specific javabean-like methods such as getJMSPriority whereas message properties are accessed using generic methods such as getIntProperty(name).

JMSXDeliveryCount was defined (though not made mandatory) in JMS 1.1 and is a message property, not a message header, which is why it is accessed using setIntProperty and getIntProperty rather than more specific methods. In JMS 2.0 all we are doing is making this existing property mandatory.

I can see a case for defining specific methods to access the JMS-defined properties (those starting with JMSX), or even just the mandatory one(s), but there is potential confusion in providing two ways to access the same value. And since JMSXDeliveryCount was defined in JMS 1.1 it has to remain a property.

So I propose we leave things as they are. However I'll leave this issue open for now to allow for other comments either via the issue or via the EG/user alias.

Comment by axel_podehl [ 09/Jan/13 ]

I see - yes, adding this method this would break existing code/be inconsistent (suggesting to close the issue).

I guess JMSX properties were meant to be provider-specific.

But with JMS 2.0, some of them are mandatory (=portable), correct?
Are there 'public static final Strings' for those ?

Comment by Nigel Deakin [ 11/Jan/13 ]

In JMS 1.1 all the JMSX properties were optional, making them provider-specific. In JMS 2.0 we're making one of them mandatory. This leaves it in a slightly anomalous position, but for the reasons mentioned above I think it's best to stick with the existing API for accessing it.

The JMS API does not define static constants for these properties. If you think it should please log it a separate issue.





[JMS_SPEC-111] add MessageConsumer.getDestination() and JMSConsumer.getDestination() methods Created: 08/Jan/13  Updated: 09/Jan/13

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

Type: New Feature Priority: Minor
Reporter: axel_podehl Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

TopicSubscriber.getTopic() and QueueReceiver.getQueue() exist, so I think also MessageConsumer.getDestination() should be there.

That way an unnecessary type cast could be avoided and the provider's implementation is trivial.



 Comments   
Comment by Nigel Deakin [ 09/Jan/13 ]

If we add MessageConsumer.getDestination() we should also add JMSConsumer.getDestination(). Amending the description to reflect this.





[JMS_SPEC-110] add JMS methods to access an Object's creator: Message.getSession(), Session.getConnection(), ... Created: 08/Jan/13  Updated: 09/Jan/13

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

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

Tags: jms21-forreview-minor

 Description   

I know this might be against the API strategy of 'create-and-forget' (Connection creates Session, thereafter only use Session), but in several places it would be convenient to be able to get to an object's creator even after creation.

For example JMS_SPEC-68 suggests a method Session.acknowledge() to acknowledge() the complete Session instead of a misleading Message.acknowledge(). This is a good change, but within a MessageListener's onMessage(), you have access to the Message only, not the Session

So to make proper use of Session.acknowledge(), I'm proposing a method Message.getSession() so that inside the onMessage() method you can simply call these, without having to remember the Session object:

  • Message.getSession().acknowledge()
  • Message.getSession().commit()

Once the API starts down this track, for consistency, it should probably go all the way:
Session.getConnection(), Connection.getFactory(), ...



 Comments   
Comment by Nigel Deakin [ 09/Jan/13 ]

This is ultimately a matter of API style. Depending on viewpoint, it's either desirable to be able to navigate "back" to the parent object, or it isn't. There isn't an absolute answer.

As for Message.getSession(): apart from the issue of whether this is a desirable API style, there is a problem here since the Message may have been created using JMSContext.createMessage() etc. In that case it is inappropriate to request a Session object. (The design of JMSContext deliberately does not have a getSession or getConnection method to keep the classic and simplified APIs separate).

You make a good point that the session (or context) is not automatically available in a message listener's onMessage, which makes it awkward to commit the local transaction.

At the time of writing JMS 2.0 has reached the public draft stage. This is not an urgent issue which required incorporation in JMS 2.0, so I will defer it for proper consideration for JMS 2.1. Tagging appropriately.

Comment by axel_podehl [ 09/Jan/13 ]

Yes, agreed. With the new API it's undefined which one to add:

Message.getSession()

or

Message.getJMSContext()

Since Message can be created from both APIs, it's better to leave this part alone and not add any method to navigate back.

As for session commit, maybe a Message.commit() - with a clear documentation that this would commit all messages within this session?
Although that doesn't sound great either...





[JMS_SPEC-109] add method Destination.getName() Created: 08/Jan/13  Updated: 09/Jan/13

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

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

Tags: jms21-forreview-minor

 Description   

JMS topics and queues both have names that are accessible with getTopicName() and getQueueName(), but for applications where the type of destination (topic or queue) is configurable - which I would consider a good application - it's difficult to get the actual destination's name.

An ugly typecast or something similar must be used:

  public static String getJMSDestinationName(Message msg) throws JMSException
  {
    Destination origDest = msg.getJMSDestination();
    if( origDest==null ) return null;
    
    if( origDest instanceof Topic) {
      return ((Topic)origDest).getTopicName();
    }
    else {
      return ((Queue)origDest).getQueueName();
    }
  }

What I'm proposing is simply a common Destination.getName() method so this code becomes nicer:

  public static String getJMSDestinationName(Message msg) throws JMSException
  {
    return msg.getJMSDestination().getName();
  }

The implementation of Destination.getName() is trivial for Topic and Queue.

I can understand the objection of saying: "'Destination' is just a marker interface and JMS abstracts from the actual topic/queue name, these names shouldn't matter."

But then, why is there getQueueName()/getTopicName() in the first place?

I find this name very useful in order to debug or sort message streams into buckets and it would be nice if this name will be simpler to get by.



 Comments   
Comment by Nigel Deakin [ 09/Jan/13 ]

I think this is a good proposal (thanks). I don't think it would break backwards compatibility (i.e. existing application code wouldn't need to be changed).

However now JMS 2.0 has reached the public draft stage we need to avoid adding new features if at all possible and as this feature is unrelated to any of the changes in JMS 2.0, and can be added to the next version without introducing any compatibility problems, I propose we defer adding it to the API until JMS 2.1.

Tagging accordingly.

Comment by axel_podehl [ 09/Jan/13 ]

Another motivation to use this admittedly non-portable destination name is this:

Especially when consuming from a wildcard such as TRADE.> you might want to know the actual topic name of the received message (e.g. TRADE.UNSETTLED.SYSTEMA.cusip712321) to log it or to branch on this type/originator or whatever the topic space was designed to contain.

Comment by axel_podehl [ 09/Jan/13 ]

Ok, thanks for the layout work. I try to remember that trick ('


')





[JMS_SPEC-108] add generics to methods currently returning raw types Created: 03/Jan/13  Updated: 01/Nov/15

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

Type: Improvement Priority: Major
Reporter: braghest Assignee: Unassigned
Resolution: Unresolved Votes: 4
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: enumeration, generics, jms, jms21-forreview-minor

 Description   

There are several methods that return raw java.util.Enumeration. Adding a type parameter would return the potential for misuse, produce cleaner and safer code and give a better development experience since you don't need to look up the the JavaDoc, the IDE automatically inserts the right type.

The affected methods are:

  • javax.jms.QueueBrowser.getEnumeration() should return Enumeration<Message>
  • javax.jms.Message#getPropertyNames() should return Enumeration<String>
  • javax.jms.JMSProducer#getPropertyNames() should return Enumeration<String>
  • javax.jms.MapMessage#getMapNames() should return Enumeration<String>
  • javax.jms.ConnectionMetaData#getJMSXPropertyNames() should return Enumeration<String>


 Comments   
Comment by Nigel Deakin [ 09/Jan/13 ]

I think this is a good proposal (thanks). I don't think it would break backwards compatibility (i.e. existing application code wouldn't need to be changed).

However now JMS 2.0 has reached the public draft stage we need to avoid adding new features if at all possible and as this feature is unrelated to any of the changes in JMS 2.0, and can be added to the next version without introducing any compatibility problems, I propose we defer adding it to the API until JMS 2.1.

(The exception to this is javax.jms.Message#getPropertyNames(), which is new in JMS 2.0 and we are separately considering changing to return a Set <String>).

Tagging accordingly.

Comment by braghest [ 01/Nov/15 ]

Here is a patch

Index: jms2.1/src/main/java/javax/jms/ConnectionMetaData.java
===================================================================
--- jms2.1/src/main/java/javax/jms/ConnectionMetaData.java	(revision 345)
+++ jms2.1/src/main/java/javax/jms/ConnectionMetaData.java	(working copy)
@@ -143,6 +143,6 @@
       *                         metadata due to some internal error.
       */
 
-    Enumeration
+    Enumeration<String>
     getJMSXPropertyNames() throws JMSException;
 }
Index: jms2.1/src/main/java/javax/jms/MapMessage.java
===================================================================
--- jms2.1/src/main/java/javax/jms/MapMessage.java	(revision 345)
+++ jms2.1/src/main/java/javax/jms/MapMessage.java	(working copy)
@@ -299,7 +299,7 @@
       *                         due to some internal error.
       */
 
-    Enumeration
+    Enumeration<String>
     getMapNames() throws JMSException;
 
 
Index: jms2.1/src/main/java/javax/jms/Message.java
===================================================================
--- jms2.1/src/main/java/javax/jms/Message.java	(revision 345)
+++ jms2.1/src/main/java/javax/jms/Message.java	(working copy)
@@ -1379,7 +1379,7 @@
       *                          names due to some internal error.
       */ 
      
-    Enumeration
+    Enumeration<String>
     getPropertyNames() throws JMSException;
 
 
@@ -1691,5 +1691,5 @@
 	 *                if the JMS provider fails to return a value due to some
 	 *                internal error.
 	 */
-	boolean isBodyAssignableTo(Class c) throws JMSException;    
+	boolean isBodyAssignableTo(Class<?> c) throws JMSException;    
 }
Index: jms2.1/src/main/java/javax/jms/QueueBrowser.java
===================================================================
--- jms2.1/src/main/java/javax/jms/QueueBrowser.java	(revision 345)
+++ jms2.1/src/main/java/javax/jms/QueueBrowser.java	(working copy)
@@ -111,7 +111,7 @@
       *                         due to some internal error.
       */
 
-    Enumeration 
+    Enumeration<String> 
     getEnumeration() throws JMSException;
 
 





[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-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-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-104] API javadocs need to conform to Oracle accessibility standards and W3C HTML validation standards Created: 29/Oct/12  Updated: 20/Mar/13

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

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

Tags: jms21-forreview-minor

 Description   

The JMS API javadocs need to conform to Oracle accessibility standards and W3C HTML validation standards

The W3C HTML validator is at http://validator.w3.org

The Oracle accessibility validator is at oac.us.oracle.com (Oracle internal only)



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

This has been confirmed as far as possible.

One possible issue remains in that the character encoding (which should be UTF-8) is incorrectly configured.

The javadocs define this as follows:

<!-- Generated by javadoc (version 1.7.0_17) on Tue Mar 19 14:40:26 GMT 2013 -->
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8">

whereas it should be

<META http-equiv="Content-Type" content="text/html; charset=UTF-8">

Note the different use of " and ; characters.

This is due to a bug in the javadoc program in Java SE 7. This has been logged with the JDK team (internal bug JDK-8006650).

This issue was therefore not completely resolved in JMS 2.0 and so has been left unresolved. Tagging for JMS 2.1.





[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-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-100] Allow Java EE components other than MDBs to consume messages asynchronously Created: 19/Sep/12  Updated: 02/Sep/13

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

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

Issue Links:
Dependency
depends on EJB_SPEC-60 Modernize Connector/MDB Resolved
Related
is related to JMS_SPEC-134 Declarative Annotation Based JMS List... Open
Tags: jms21-forreview-major

 Description   

This proposal suggests the addition of the following annotation: @MessageSelector, to be used on a @MessageDriven bean consumimng a Queue or as Topic Subscriber.

Example:

package sample;

// imports

@MessageDriven(mappedName = "jms/queue0")
public class MessageSelectorBean implements MessageListener {

  @Resource(lookup = "jms/connectionFactory")
  ConnectionFactory connectionFactory;

  @MessageSelector("(StockSector = 'Technology')")
  public void onMessage(Message message) {
    try (JMSContext context = connectionFactory.createContext()) {
      String request = ((TextMessage)message).getText();
      Destination replyDestination = message.getJMSReplyTo();
      TextMessage replyMessage = context.createTextMessage("Reply to: "+request);
      context.createProducer().send(replyDestination, replyMessage);
   } catch (JMSException ex) {
     // log an error here
   }
  }
}


 Comments   
Comment by Bruno Borges [ 19/Sep/12 ]

Same code o Gist (formatted)

https://gist.github.com/3750788

Comment by Bruno Borges [ 22/Apr/13 ]

Can someone close this issue as invalid? JMS 2 just got final, so I don't see this going forward.

Comment by John D. Ament [ 22/Apr/13 ]

Since we now have an updated RA spec, we can make something like this happen. I'd strongly recommend leaving this open, maybe something we can tackle in JMS 2.1.

Comment by Nigel Deakin [ 22/Apr/13 ]

I agree improvements to MDBs (and message listeners in Java SE as well) should be on the agenda for JMS 2.1, so I'll leave this open.

Comment by Bruno Borges [ 22/Apr/13 ]

Extension of this proposal (which I forgot to add when I submitted the issue):

  • allow MDBs to have N "onMessage" methods, annotated with @MessageSelector

Questions to be analyzed:
1) should container create an instance of MDB per "message selector"?
2) should fields be thread-safe?
3) how would this affect concurrency?
4) how should pool size be defined? Per MDB (as it is now), or per message selector?

PS: great to see interest in this

Comment by John D. Ament [ 22/Apr/13 ]

Note: the core MDB work is contained in the EJB spec. JMS does not define an MDB. JMS does define the endpoint interface (potentially the annotations that work with that interface as well).

Comment by Nigel Deakin [ 22/Apr/13 ]

Note that you can already (Java EE 6) specify the message selector of a MDB using annotations (the activation property messageSelector), though this can't be checked by the compiler.

From Bruno's last comment it sounds he is making a more general request, somewhat similar to JMS_SPEC-116 (logged by genomeprjct), of breaking the link between JMS MDBs and the javax.jms.MessageListener interface.

Perhaps we should combine this issue with that one.

Comment by John D. Ament [ 25/Apr/13 ]

I think we generally need an approach for RA handling and how the MDBs will work with that RA. Based on what I'm seeing in the specs, it seems like it's essentially luck that the current JMS MDB even works somewhat consistently across application servers; it's just not clear to me yet that we can move forward with a change like this ourselves. In JMS 2 some standard configuration was added, but this was done by pushing the EJB EG to make the changes. When the JMS spec voted on an RA, it was generally voted down (note: my vote was to make it optional, but if an implementation did decide to provide one it needed to work with a specific interface for app servers).

My vote is to generally start to formulate what the next version of the JMS MDB looks like (based on the new RA structure provided by David and the platform spec); but do we need to officially file for a JMS 2.1 JSR?

Comment by Bruno Borges [ 25/Apr/13 ]

Allowing any method to be defined as a consumer could lead to a new approach at integrating message consumption and business methods. For example, such code could be possible:

package sample;

// imports

@Stateless
public class MySessionBean {

  @Resource(mappedName = "jms/queue0")
  private Queue queue0;

  @Inject
  private JMSContext jmsContext;

  public String retrieveUserPassword(String userEmail) {
    ... // business logic, connection to EntityManager, etc...
    return foundPassword;
  }

  @DestinationConsumer(mappedName = "jms/queue0")
  @MessageSelector("(LostPasswordBy = 'email')")
  public void sendEmailPassword(Message message) {
      String email = ((TextMessage)message).getText();
      String password = retrieveUserPassword(email);
      ... // call mailSession and send an email with recovered password
  }

  // method called by managedbean on UI, etc...
  public void requestLostPassword(String email) {
     TextMessage message = context.createTextMessage(email);
     message..setStringProperty("LostPasswordBy", "email");
     jmsContext.createProducer().send(queue0, message);
  }
}

Comments?

Comment by Nigel Deakin [ 25/Apr/13 ]

When this issue was first logged, the summary was "Support for annotation @MessageSelector on message driven beans".

I think we should change this to make it more general. Bruno's not just asking about message selectors (which you can already define using an annotation). It's about making it possible for Java EE components other than MDBs to consume messages asynchronously, and to replace the existing requirement to implement MessageListener with the ability to annotate individual methods. (I don't think we need to worry too much about the actual annotations just yet, the point is made.)

I'll change the description to "Allow Java EE components other than MDBs to consume messages asynchronously".

Just like JMS MDBs are currently defined in the EJB spec, this would probably end up being defined in the EJB spec. But the JMS expert group and community should "own" the issue and decide what it wants.

Note that we're currently (April 2013) in an interregnum between two versions of JMS currently: this issue may well be one which we want to specifically mention on the JSR for the next version.

Comment by Bruno Borges [ 01/May/13 ]

Perhaps we should consider two things:

  1. Extend the use of @MessageSelector for MDBs as is today, letting a MDB to have N-annotated methods with @MessageSelector
    I think this proposal can be worked for JMS 2.1 without the need for further details and changes over the spec, and it does not involve EJB spec.
  2. Let any component/method connect to a Destination, using Message Selectors, Activation Configs, etc.

This should be considered, IMO, as a proposal for EJB 3.next or EJB 4.0. This change would fit better with what David Blevins proposed on EJB_SPEC-60 and with what has already been discussed with JMS_SPEC-116

Good example of usecase that could benefit of this proposal is described at GLASSFISH-20371





[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-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-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-95] Individual message acknowledge mode Created: 28/Jun/12  Updated: 25/Apr/16

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

Type: New Feature Priority: Major
Reporter: chris.barrow Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

n/a


Issue Links:
Related
is related to JMS_SPEC-176 Allow message acknowledgment outside ... Open
is related to JMS_SPEC-168 No-acknowledge mode Open
is related to JMS_SPEC-169 Vendor-defined acknowledgement modes Open
Tags: jms21-forreview-minor, pd20-forreview-major

 Description   

Currently the JMS 1.1 and 2.0 specifications only allow for one mode of operation for applications which wish to do their own message acknowledgment. This is CLIENT_ACKNOWLEDGE mode. This mode has the following characteristic, as defined in the spec: "Acknowledging a consumed message automatically acknowledges the receipt of all messages that have been delivered by its session.".

This Implicit acknowledgment of all messages is not only somewhat unexpected, because it's such a broad side effect, it is highly inconvenient in cases where message processing is being done by multiple threads asynchronously (message reception on one Session has to be in a single thread, per JMS spec rules, but I am talking about cases where the messages are then dispatched to one or more worker threads, or even other processes, for asynchronous processing). I realise this can be overcome to some degree by using a separate Session and MessageConsumer in each worker thread, but that imposes more overhead on the JMS provider. A better alternative, which is already offered by certain JMS providers (including Tibco EMS and ActiveMQ), is INDIVIDUAL_ACKNOWLEDGE mode, where acknowledging a message acknowledges only that message. This makes asynchronous processing of messages much easier to implement.

One can imagine other acknowledge modes that would be useful too, for example: CONSUMER_ACKNOWLEDGE where Message.acknowledge() would acknowledge only messages received up on a particular MessageConsumer, or CONSUMER_CHECKPOINT_ACKNOWLEDGE where Message.acknowledge() would acknowledge only messages received up to and including the Message instance on which the method was called.

But without embarking on all these various different possibilities, would it be possible to consider just adding INDIVIDUAL_ACKNOWLEDGE mode? This alone would make it possible for multithreaded applications to achieve whatever behaviors they need.



 Comments   
Comment by chris.barrow [ 10/Jul/12 ]

Note that the above use case would require relaxing the threading rules for a Session to allow <Message>.acknowledge() to be called in threads other than the JMS provider thread which is delivering messages, at least in the case where INDIVIDUAL_ACKNOWLEDGE mode is set on the session. So it would be desirable to include that relaxation along with this feature. I have now filed a separate ticket for this: JMS_SPEC-176: Allow message acknowledgment outside of the message delivery thread.

The relevant parts of the JMS 1.1 spec are 4.4 "Session" which states (in a footnote) that "the restriction is that the resources of a Session should not be used concurrently by multiple threads" and section 4.4.6 "Conventions for Using a Session" which explains "Once a connection has been started, all its sessions with a registered message listener are dedicated to the thread of control that delivers messages to them.".

Currently the only exception to this rule is that the Session.close method may be called outside the thread of control. The feature described by this ticket would require an additional exception: that the Message.acknowledge() method can be called outside the thread of control (at least when the session acknowledge mode is INDIVIDUAL_ACKNOWLEDGE).

Comment by chris.barrow [ 10/Jul/12 ]

It is perhaps worth pointing out that allowing the <Message>.acknowledge() method to acknowledge only that message would fit in nicely with the proposal to support the acknowledge () method on Session (see issue JMS_SPEC-68).

Comment by tom.barnes [ 10/Jul/12 ]

A potential alternate API to the proposed new acknowledge modes INDIVIDUAL_ACKNOWLEDGE and CONSUMER_CHECKPOINT_ACKNOWLEDGE could be new Session methods “acknowledgeOne(Message)” and “acknowledgeUpThrough(Message)”. These new methods, like the current "message.acknowledge()" and the proposed "session.acknowledge()", would only apply in CLIENT_ACKNOWLEDGE mode.

This would eliminate the need to add new acknowledge modes, and would preserve the semantics of the old "acknowledge()" verb so that it always had the same legacy behavior.

Comment by clebertsuconic [ 19/Sep/13 ]

This issue should be broken in two...one about INDIVIDUAL_ACKNOWLEDGE which is already implemented in a few implementation (I know for instance both hornetQ and ActiveMQ have it).

I'm ok with INDIVIDUAL_ACKNOWLEDGE... but I feel session.acknowledge() is a bit not doable.

by adding INDIVIDUAL_ACKNOWLEDGE mode you can change the semantic of message.acknowledge() as most providers already do. It's a minor change in semantic anyways as you only ack that message which is exactly what the user would expect in such case.

Of course this would only apply to non-transactional, same way as the CLIENT_ACKNOWLEDGE is done. INDIVIDUAL_ACKNOWLEDGE would just be a different CLIENT_ACK mode.

you could even maybe call it CLIENT_INDIVIDUAL_ACKNOWLEDGE but I guess a short name woud be better... INDIVIDUAL_ACKNOWLEDGE.

Comment by Nigel Deakin [ 19/Sep/13 ]

JMS providers which support individual acknowledgement as a non-standard extension:

GlassFish Message Queue
http://docs.oracle.com/cd/E18930_01/html/821-2440/aeqef.html#scrolltoc
(methods on the provider's message implementation: acknowledgeThisMessage() and acknowledgeUpThroughThisMessage())

ActiveMQ
http://activemq.apache.org/maven/apidocs/org/apache/activemq/ActiveMQSession.html#INDIVIDUAL_ACKNOWLEDGE
(new non-standard acknowledgement mode {[INDIVIDUAL_ACKNOWLEDGE}} which alters the behaviour of Message#acknowledge()

JBoss HornetQ
http://docs.jboss.org/hornetq/2.3.0.beta1/docs/user-manual/html/pre-acknowledge.html#individual-ack
(new non-standard acknowledgement mode INDIVIDUAL_ACKNOWLEDGE)

Comment by John D. Ament [ 19/Sep/13 ]

If we add INDIVIDUAL_ACKNOWLEDGE do we also need to add INDIVIDUAL_ACKNOWLEDGE_TX or equivalent, to individually change to TX mode.

Comment by clebertsuconic [ 19/Sep/13 ]

@John D. Ament: quick answero: no... there's no directly ack on messages on any TX mode. so no reason for that

Comment by chris.barrow [ 27/Dec/13 ]

Can we get this onto the plan for JMS 2.1? Anything I can do to help?

Comment by Nigel Deakin [ 23/Jan/14 ]

@Chris: Yes, I've just added it to that page (and added an appropriate tag). Thanks for spotting that this issue was in danger of being forgotten. This put the issue on the agenda for formal discussion for 2.1 - nothing has been decided yet.

Comment by chris.barrow [ 08/Jul/14 ]

Another JMS provider which supports individual acknowledgement is Tibco EMS:
https://docs.tibco.com/pub/enterprise_message_service/6.3.0-february-2012/doc/html/tib_ems_api_reference/api/javadoc/com/tibco/tibjms/Tibjms.html#EXPLICIT_CLIENT_ACKNOWLEDGE
(non-standard acknowledgement mode EXPLICIT_CLIENT_ACKNOWLEDGE which alters the behavior of message#acknowledge())

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

I like Clebert's suggestion of CLIENT_INDIVIDUAL_ACKNOWLEDGE. It goes nicely with CLIENT_ACKNOWEDGE,

Comment by Nigel Deakin [ 27/Feb/15 ]

The specification for Session#getAcknowledgementMode and JMSContext#getSessionMode would need to be extended to cover this new feature.

Comment by gemmellr [ 14/Oct/15 ]

Individual acknowledgement of messages would seem to be a useful thing to support. There is work ongoing on a AMQP mapping for JMS over at OASIS, and individual acknowledge is an area of functionality that there isn't currently a natural fit for in JMS. Supporting this would also allow enabling the behaviour I have seen several people actually think the existing method had until they use it and discover otherwise; the javadoc is perfectly clear on the behaviour of course, but requires that they read it first.

Between the mentioned routes for implementation thus far, I would personally prefer the route of adding a new ack mode such as CLIENT_INDIVIDUAL_ACKNOWLEDGE and using it to govern the behaviour of Message#acknowledge(). This seems the most intuitive to me given it is a different mode of acknowledgement, the acknowledge action is on the message, and doing so would enable the kind of behaviour that people often think is already offered by the method. From above, it also seems to be how more of the existing vendor extensions approach offering the functionality.

Comment by mattrpav [ 25/Apr/16 ]

Where does this issue currently stand? It would be great to see this get rolled into 2.1.





[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