<< Back to previous view

[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: Nigel Deakin and reza_rahman

 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 06:55 PM ]

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: 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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major
Participants: John D. Ament and Nigel Deakin

 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 11:06 AM ]

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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major
Participants: John D. Ament and Nigel Deakin

 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 10:59 AM ]

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 11:06 AM ]

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: 23/Jan/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: Nigel Deakin

 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 10:59 AM ]

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?





[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: Nigel Deakin

 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-141] Allow async delivery to temporary destinations in Java EE Created: 18/Nov/13  Updated: 19/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: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-major
Participants: lprimak and Nigel Deakin

 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 05:40 PM ]

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-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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: John D. Ament, mbwhite and Nigel Deakin

 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 10:55 AM ]

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 11:22 AM ]

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 11:40 AM ]

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 11:46 AM ]

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 11:55 AM ]

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 12:45 PM ]

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 01:43 PM ]

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: 01/Nov/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: Nigel Deakin

 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.






[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: John D. Ament

 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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: chris.barrow, John D. Ament and Nigel Deakin

 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 05:28 PM ]

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 04:00 PM ]

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 05:42 PM ]

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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-116 Take advantage of EJB 3.2's RA improv... Open
is related to JMS_SPEC-100 Allow Java EE components other than M... Open
Tags: jms21-forreview-major
Participants: Bruno Borges, clebertsuconic, John D. Ament, Nigel Deakin and reza_rahman

 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 08:52 PM ]

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 09:03 PM ]

@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 09:06 PM ]

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 09:09 PM ]

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

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

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 02:46 PM ]

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 03:10 PM ]

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 03:42 PM ]

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 04:50 PM ]

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 05:54 PM ]

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 09:05 AM ]

@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 05:13 PM ]

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 08:36 PM ]

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 09:04 PM ]

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 09:21 PM ]

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 amd TopicConnection#createTopicSession Created: 19/Aug/13  Updated: 19/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21doc-minor
Participants: Nigel Deakin

 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.






[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: John D. Ament and Nigel Deakin

 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 03:13 PM ]

(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
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
Participants: Nigel Deakin

 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 04:09 PM ]

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
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
Participants: Nigel Deakin

 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
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
Participants: John D. Ament and Nigel Deakin

 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 11:53 AM ]

Equivalently, what happens in EJB when this occurs?

Comment by Nigel Deakin [ 18/Jun/13 12:01 PM ]

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 01:12 PM ]

Added some code examples to the initial issue description

Comment by Nigel Deakin [ 18/Jun/13 04:14 PM ]

Updated summary field.

Comment by Nigel Deakin [ 22/Aug/13 05:00 PM ]

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.14 "Queue" Created: 06/Jun/13  Updated: 06/Jun/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 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.






[JMS_SPEC-127] Incorrect HTML in API documentation Created: 29/May/13  Updated: 29/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 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 02:40 PM ]

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 02:51 PM ]

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 02:51 PM ]

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 02:52 PM ]

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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: clebertsuconic, John D. Ament and Nigel Deakin

 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 02:57 PM ]

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 05:41 PM ]

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 05:43 PM ]

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 05:56 PM ]

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 01:03 PM ]

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 01:09 PM ]

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 04:45 PM ]

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: 22/May/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: John D. Ament and Nigel Deakin

 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. I'm talking about the message object in the sending program, not in the receiving program. There are three possibilities:

1. The JMS provider leaves the body in the same state as it was before the call to the send method. That is, it is in write-only mode with the stream positioned at the end. That allows the application at append data to the message after sending.

2. The JMS provider calls reset(). This leaves the BytesMessage in read-only with the stream positioned at the start.

3. Leave the behaviour undefined.

I would rather not adopt (3) if we can avoid it. The state that the message body is in affects the portability of applications between JMS providers so the required behaviour should be defined if possible.

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 message is what state the message is in when the CompletionListener callback is performed. Let's consider these separately.

Asynchronous send

Asynchronous send is a new feature, so although the JMS 2.0 spec is not specific about this, it's not too late to add define the required behaviour more specifically.

I think with an asynchronous send there is a clear benefit in adopting (2). It is possible that a CompletionListener callback method may want to read the message in order to identify the message that was successfully sent. After all, what the point is of passing a message to onCompletion() if its body is not readable?

Another reason for adopting (2) is that I don't think that it is practically possible to adopt (1). 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 (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, which means it will need to call reset() before doing so. That would leave the message in read-only mode.

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. I therefore think it is probably too late to define more specific behaviour.

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.



 Comments   
Comment by John D. Ament [ 21/May/13 11:30 PM ]

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

Comment by Nigel Deakin [ 22/May/13 08:33 AM ]

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.





[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 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: 08/May/13

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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 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.






[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
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
Participants: Bruno Borges, John D. Ament and Nigel Deakin

 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 11:20 AM ]

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 11:23 AM ]

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 07:15 PM ]

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 03:53 PM ]

Added link to WEBSOCKET_SPEC-196





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

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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 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 ().






[JMS_SPEC-119] Remove reference to password alias Created: 26/Apr/13  Updated: 26/Apr/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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms20-bug
Participants: Nigel Deakin

 Description   

The JMS 2.0 specification includes the following reference to password aliases in Java EE:

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.

Although password aliases were discussed for Java EE they were not included in the final release, so this reference is incorrect and should be removed.






[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: John D. Ament and Nigel Deakin

 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 08:37 PM ]

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
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
Participants: Nigel Deakin

 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 09:28 AM ]

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: 02/Sep/13

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: Unassigned
Resolution: Unresolved Votes: 0
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
Participants: John D. Ament and Nigel Deakin

 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 12:23 PM ]

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





[JMS_SPEC-113] Clarify the difference (if any) between JMSException.getLinkedException() and JMSException.getCause() 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: Improvement Priority: Major
Reporter: axel_podehl Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: axel_podehl and Nigel Deakin

 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 11:52 AM ]

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 11:56 AM ]

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.





[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: axel_podehl and Nigel Deakin

 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 06:34 PM ]

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 06:49 PM ]

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 12:09 PM ]

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-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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: axel_podehl and Nigel Deakin

 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 06:58 PM ]

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 07:26 PM ]

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: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: axel_podehl and Nigel Deakin

 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 06:05 PM ]

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 06:06 PM ]

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 06:09 PM ]

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: 09/Jan/13

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: 2
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: enumeration generics jms jms21-forreview-minor
Participants: braghest and Nigel Deakin

 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 05:44 PM ]

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.





[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
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: jms21-forreview-minor
Participants: Nigel Deakin

 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 12:07 PM ]

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-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
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
Participants: Bruno Borges, John D. Ament and Nigel Deakin

 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 05:07 PM ]

Same code o Gist (formatted)

https://gist.github.com/3750788

Comment by Bruno Borges [ 22/Apr/13 02:04 AM ]

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 02:10 AM ]

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 08:46 AM ]

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 10:09 AM ]

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 01:24 PM ]

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 04:12 PM ]

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 02:44 AM ]

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 06:58 AM ]

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 04:26 PM ]

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 04:51 PM ]

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-95] Individual message acknowledge mode Created: 28/Jun/12  Updated: 23/Jan/14

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: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

n/a


Tags: jms21-forreview-minor pd20-forreview-major
Participants: chris.barrow, clebertsuconic, John D. Ament, Nigel Deakin and tom.barnes

 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 05:08 PM ]

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.

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 05:16 PM ]

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 06:26 PM ]

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 01:13 PM ]

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 02:08 PM ]

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 02:12 PM ]

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 02:19 PM ]

@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 08:19 PM ]

Can we get this onto the plan for JMS 2.1? Anything I can do to help?

Comment by Nigel Deakin [ 23/Jan/14 11:06 AM ]

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





[JMS_SPEC-92] Session.commit() etc should require TransactionInProgressException to be thrown if called in a JTA transaction Created: 29/Mar/12  Updated: 29/Mar/12

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

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

Tags: pd20-veryminor
Participants: Nigel Deakin

 Description   

The JMS 1.1 javadoc for TransactionInProgressException
http://docs.oracle.com/javaee/6/api/javax/jms/TransactionInProgressException.html
states:

This exception is thrown when an operation is invalid because a transaction is in progress. For instance, an attempt to call Session.commit when a session is part of a distributed transaction should throw a TransactionInProgressException.

However the javadoc for Session.commit does not list this as a mandatory exception.
http://docs.oracle.com/javaee/6/api/javax/jms/Session.html#commit%28%29

This is inconsistent.

It is hereby proposed that the definition of Session.commit and Session.rollback should be modified to require a TransactionInProgressException to be thrown when the session is in a JTA transaction.

Note that the corresponding methods on XASession already require these exceptions.

(and inconsistent with XASession.commit.






[JMS_SPEC-91] New "relaxed message order" option Created: 28/Mar/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-minor
Participants: Nigel Deakin

 Description   

Not all JMS applications depend on the message ordering guarantees required by JMS 1.1. Some would work perfectly well if the existing guarantees were occasionally broken.

The need to satisfy the message ordering requirements of JMS 1.1 imposes a significant burden on the JMS provider. For example, the requirement to preserve the order of messages sent by a message producer during the lifetime of the client-side object places constraints on the way in which a clustered JMS provider may handle producer failover or on its ability to balance the message load across the cluster.

Whilst JMS providers will always need to be able to satisfy JMS 1.1 message ordering requirements, if JMS also defined a less onerous message order requirement then those applications which could use it may be able to benefit from better performance or increased scalability.

It is therefore proposed that a new "relaxed" message ordering option be available. In such a mode, JMS does not guarantee that messages will always be received by a consumer in the same order that they were sent by a given producer. Although JMS providers could not be permitted to ignore message order altogether, the strict requirement to deliver messages in order would be relaxed.

It is expected that this option would be of particular value in very large clusters and similar web-scale architectures. However it would be up to providers to decide whether, and how, to take advantage of this option. Although vendors would be required to allow "relaxed message order" as an option, it would be completely valid for this to be identical to normal message ordering.

The exact API to specify "relaxed ordering" is not yet proposed. It might be a property of the producer connection or of the destination itself.






[JMS_SPEC-90] Provide simpler mechanism to refer to queues and topics in a portable way Created: 27/Mar/12  Updated: 08/Jan/13

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

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

Tags: pd20-forreview-major
Participants: axel_podehl, chris.barrow and Nigel Deakin

 Description   

In the JMS 1.1 API, individual queues and topics are referred to not by name but by using javax.jms.Queue and javax.jms.Topic objects, where the javax.jms.Queue and javax.jms.Topic interfaces both extend the javax.jms.Destination interface.

This is because JMS 1.1 expects the way that a queue or topic is specified to be proprietary to a JMS provider. In order to allow these proprietary aspects to be isolated from the application, JMS 1.1 expects javax.jms.Queue and javax.jms.Topic objects to be "placed in a JNDI namespace by an administrator", for subsequent lookup by a portable application.

Another benefit of storing queue and topic objects in JNDI is that it allows an administrator (or, in Java EE, a deployer) to configure a mapping between the queue or topic JNDI name specified in the application with the actual queue or topic name used by the JMS provider which can be modified without the need to change the application code.

Applications can by-pass this mechanism by using the createQueue(String name) and createTopic(String name) methods on Session to convert a provider-specific queue or topic name to a javax.jms.Queue or javax.jms.Topic object. Since queue or topic names are not portable this usage is, however, not recommended.

There are two main reasons why an application might want to avoid the need to bind and lookup objects in JNDI. For a Java SE application which would otherwise have no use for JNDI, this is an additional complication for the application. For a Java EE application which uses many thousands of destinations (e.g. a market data application that uses a separate topic for every stock code on a stock exchange), then even though a JNDI provider comes built-in, having to create many thousands of administered object is an administrative burden.

This issue therefore raises the issue of whether JMS should be enhanced to allow applications to refer to queues and topics in a portable way without always having to create administered objects in JNDI. Possibilities include:

  • Perhaps defining a portable format for queue and topic names to allow the use of createQueue(String name) and createTopic(String name) methods on Session to be portable.
  • Perhaps providing methods on JMSContext which allow a queue or topic to be specified as a string (and which therefore call createQueue(String name) or createTopic(String name) internally) - though this might require the domain required (queue or topic) to be passed in as an additional parameter.
  • Perhaps adding some defaulting mechanism to the JNDI namespace to allow a javax.jms.Queue or javax.jms.Topic to be looked up in JNDI in some special namespace and for the administered object to be created dynamically.
  • There are other possibilities which might be considered as well.


 Comments   
Comment by chris.barrow [ 06/Dec/12 07:47 PM ]

I would vote for the first option (defining a portable format for queue and topic names to allow the use of createQueue and createTopic). The portable format just needs to specifiy a minimum set of characters which are valid in a topic or queue name. This is very similar to JMS_SPEC_94 (for durable or shared subscription name).

I think this would be a very useful enhancement and we should try to get it into JMS 2.0.

Comment by axel_podehl [ 08/Jan/13 03:50 PM ]

I think createTopic/createQueue is already used in many applications and the real behaviour differs from provider to provider.

How about adding a method like this one, similar to the properties of the JMSDestinationDefinition annotation:

Session.createTopic( String jndiName, String destinationName, String description, String[] properties)

or along the lines of ConnectionMetaData:

Session.createTopic( String jndiName, DestinationMetaData destDefinition )

and Session.createTopic( String name ) would then use the method above, and each provider should comment on the actual arguments used.





[JMS_SPEC-89] Define standard API to create and configure a ConnectionFactory in Java SE applications and by a Java EE container Created: 27/Mar/12  Updated: 30/Mar/12

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

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

Tags: pd20-underreview
Participants: Nigel Deakin

 Description   

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

The proposal below is intended to be used by Java SE applications and by Java EE container code such as resource adapters, but not by Java EE applications themselves. This is not intended to provide an alternative to Java EE configuration via JNDI.

It replaces the proposal made in JMS_SPEC-46 and is being logged as a separate JIRA issue to avoid confusion.

Background

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

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

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

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

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

However the specification does not define:

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

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

  • it is not possible to develop standard tools for creating connection factories (and binding them in JNDI) which work with multiple JMS providers
  • it means that a generic JMS resource adapter, which wraps the connection factories of third-party JMS providers, cannot instantiate those connection factories directly but must instead look then up from JNDI
  • it requires Java SE applications which use JMS to use JNDI as the only way to keep provider-specific configuration separate from their code. Applications cannot manage configuration their own way, such as by using properties files.

Proposed standard for instantiating a connection factory and setting properties

It is proposed that for Java SE applications, and for Java EE container code only, but not for Java EE applications, a ConnectionFactory can be instantiated and configured by invoking a constructor which takes a Properties object as an argument:

Properties props = new Properties();
props.setProperty("javax.jms.url","jms://localhost:1234"};
props.setProperty("javax.jms.user","admin"};
props.setProperty("javax.jms.password",password);
ConnectionFactory cf = new com.acme.jms.AcmeConnectionFactory(properties props);

Note that since properties are passed into the constructor rather than be set after the object has been created in order this allows connection factories to be implemented as immutable objects which cannot be changed after creation. That's why this proposal does not suggest setting properties directly on the connection factory.

(Another reason why this proposal does not suggest setting properties directly on the connection factory is that it would require changes to the javax.jms.ConnectionFactotry interface which would be inappropriate for connection factories in a Java EE environment.)

Even though this approach is intended to avoid the need to use JNDI it remains the goal of JMS to allow the creation of applications which are portable between JMS providers. This means that declaring provider-specific classes in the application is discouraged. Instead, a new utility class javax.jms.ConnectionFactoryCreator will be provided by JMS which allows the provider-specific connection factory class name to be passed in as just another property. This could be used as follows:

Properties props = new Properties();
props.setProperty("javax.jms.connectionFactoryClassName","com.acmejms.AcmeConnectionFactory"};
props.setProperty("javax.jms.url","jms://localhost:1234"};
props.setProperty("javax.jms.user","admin"};
props.setProperty("javax.jms.password",password);
ConnectionFactory cf = javax.jms.ConnectionFactoryCreator.create(properties props);

In the above example, the property values are hardcoded just to make the example clearer. However it would be recommended that they be defined separately from the application.

Why is this not proposed for Java EE applications?

Note that this proposal does not cover Java EE applications. This is because in the Java EE web and application container a connection factory cannot be created in isolation because it needs to participate in the connection pooling facilities of the container. The JCA API defines two methods on javax.resource.spi.ManagedConnectionFactory to create a connection factory: createConnectionFactory() and createConnectionFactory(ConnectionManager cxManager).

This also provides another reason why the above proposal passes properties to the connection factory constructor rather than allowing them to be set on the connection factory instance. If we had allowed the latter this would have added new methods to the Connectionfactory interface whose use we would have needed to explicitly disallow for Java EE applications.

Proposed standard properties:

The following standard properties may be used to configure the connection factory.

Property name Constant Type Description
javax.jms.user ConnectionFactoryCreator.USER String user name used when the connection factory method createConnection() (with no arguments) is called
javax.jms.password ConnectionFactoryCreator.PASSWORD String password used when the connection factory method createConnection() (with no arguments) is called
javax.jms.clientId ConnectionFactoryCreator.CLIENT_ID String clientId that will be used when a connection is created
javax.jms.url ConnectionFactoryCreator.URL String Opaque string which defines how to connect to the JMS provider. Whether this property is used, and what it is set to, is defined by the JMS provider.

This proposal deliberately keeps the list of standard properties to a bare minimum, and abandons the longer list proposed in JMS_SPEC-46. It is expected that JMS providers will define their own additional properties.

The following standard property must always be supplied to the ConnectionFactoryCreator create method in addition to any of the properties specified in the previous table:

Property name Constant Type Description
javax.jms.connectionFactoryClassName ConnectionFactoryCreator.
CONNECTION_FACTORY_CLASS_NAME
String Class name of connection factory





[JMS_SPEC-88] Bind JMS to CDI events and/or business interfaces Created: 24/Mar/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-major
Participants: rdohna

 Description   

The simplified API is a huge leap forward in terms of simplicity to create and consume messages. But when writing a real service (probably an MDB) that consumes multiple messages coming in from a queue or topic, then unpacking them and dispatching calls to the right method is still rather tedious, error prone, and difficult to test.

Take this example of a service that handles two different xml messages, one to create a customer and one to delete a customer. Using text messages that contain xml is a good option, if you want to exchange complex objects and need tools to look into messages in transit. I don't show the Create/DeleteCustomer data objects here.

@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destination", propertyValue = "CustomerService") })
public class ReceiverMdb implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            String xml = ((TextMessage) message).getText().trim();
            StringReader reader = new StringReader(xml);
            if (xml.endsWith("</createCustomer>")) {
                CreateCustomer create = JAXB.unmarshal(reader, CreateCustomer.class);
                createCustomer(create.getFirstName(), create.getLastName());
            } else if (xml.endsWith("</deleteCustomer>")) {
                DeleteCustomer delete = JAXB.unmarshal(reader, DeleteCustomer.class);
                deleteCustomer(delete.getId());
            } else {
                throw new RuntimeException("unknown message type: " + xml);
            }
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    private void createCustomer(String firstName, String lastName) {
        System.out.println("create customer " + firstName + " " + lastName);
    }

    private void deleteCustomer(String id) {
        System.out.println("delete customer " + id);
    }
}

 


I can see two alternatives to reduce the unpacking and dispatching to the bare minimum:

1) Binding to CDI events

The same example would look like this:

@Stateless
public class CustomerService {
    public void createCustomer(@Observes CreateCustomer create) {
        System.out.println(create);
    }

    public void deleteCustomer(@Observes DeleteCustomer delete) {
        System.out.println(delete);
    }
}

Note that the Create/DeleteCustomer classes would have to be annotated as @MessageEvent, so the container can create an appropriate binding from JMS.

2) Binding to a business interface

For the same example, the Create/DeleteCustomer classes would not be necessary. Instead there would be a business interface and the service implements it:

@MessageApi
public interface CustomerService {
    public void createCustomer(String firstName, String lastName);
    public void deleteCustomer(String id);
}

public class CustomerServiceBean implements CustomerService {
    @Override
    public void createCustomer(String firstName, String lastName) {
        System.out.println("create: " + firstName + " " + lastName);
    }

    @Override
    public void deleteCustomer(String id) {
        System.out.println("delete: " + id);
    }
}

 


Both binding methods would help with sending messages as well, but the difference is bigger when receiving them.

A lot of questions still need to be answered: How do you define message properties, destination name, delivery mode, time-to-live, delay, etc.? All would have useful defaults, but sometimes they need to be specified, and sometimes they even need to be dynamic. How do you bind to other message types, like mapped messages?

I've started to collect some possible answers to most of these questions here as part of an experimental implementation for both binding types here. I'm aware of the CDI binding implementation in the Seam JMS module here.






[JMS_SPEC-85] Clarify how Message.receiveNoWait() is expected to behave Created: 09/Mar/12  Updated: 18/Jul/13

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

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

Issue Links:
Dependency
blocks GLASSFISH-7279 receiveNoWait should poll broker Open
Tags: jms21-forreview-minor
Participants: clebertsuconic, David Zhao and Nigel Deakin

 Description   

The javadoc for the java.jms.MessageConsumer method receiveNoWait() states that this method "Receives the next message if one is immediately available."

Several, if not most, JMS providers interpret the meaning of "immediately" (and "no wait") literally and only return a message is one is already available on the client. They do not attempt to contact the server to fetch a message from the server, even if there is one available.

This means that the effect of calling receiveNoWait() is unpredictable and experience suggests that developers are best advised never to use it.

It is proposed that the behaviour of this method should be clarified to state what it says above, and to recommend the use of the other receive methods in most cases.

Edit Following comments, this issue has been broadened to consider all possible interpretations of this method. See below



 Comments   
Comment by David Zhao [ 18/Jun/13 01:33 AM ]

GLASSFISH-7279 was created for that too.

Comment by Nigel Deakin [ 17/Jul/13 01:05 PM ]

Whilst the JMS expert group and others are considering this issue they may also wish to consider whether a new method (called, say, receiveIfAvailable) should be added which blocks for as long as is required to determine whether there are any messages in the queue or topic subscription.

Comment by clebertsuconic [ 17/Jul/13 01:17 PM ]

I thought most implementors would do a roundtrip to the server these days. Can't we just clarify that receiveNoWait should make a roundtrip to the server?

We used to do that on earlier implementations of Messaging products at JBoss, but our latest implementations are doing the round trip.

Comment by Nigel Deakin [ 17/Jul/13 04:13 PM ]

Yes, the alternative (to my initial suggestion) would be to clarify the definition of receiveNoWait to allow it to wait for as long as is required to determine whether there are any messages on the queue or topic subscription. It's helpful to hear that this is what JBoss products do.

Comment by clebertsuconic [ 17/Jul/13 04:19 PM ]

Yes, FYI: we used to only look at the client buffer on older implementations but we were hammered by users complaints.. .so we switched the implementation.

So, that's probably what most users would expect... so I would favour users' interpretation here as opposed to implementors interpretation.

just IMHO

Comment by Nigel Deakin [ 18/Jul/13 08:35 AM ]

Indeed. Let me reword the description of this issue as follows, to offer three alternatives. Here it is:

The javadoc for the java.jms.MessageConsumer method receiveNoWait() states that this method "Receives the next message if one is immediately available."

Some JMS providers interpret the meaning of "immediately" (and "no wait") literally and only return a message is one is already available on the client. They do not attempt to contact the server to fetch a message from the server, even if there is one available. This means that the effect of calling receiveNoWait() is unpredictable and experience suggests that developers are best advised never to use it.

Some other JMS providers interpret the meaning of "immediately" (and "no wait") more leniently and always contact the server to see if a message is available. This makes the method more predictable and more useful to users, and is probably closer to what users would expect.

It is proposed that the behaviour of this method should be reviewed and clarified if possible. There are three options:

1. To clarify that the receiveNoWait() should only return a message is one is already available on the client.

2. To clarify that the receiveNoWait() may wait for as long as is required to determine whether there is a message on the queue or topic subscription, and to remove the words "if one is immediately available" which is ambiguous.

3. To leave the interpretation open to vendors to decide.

As Clebert says, users probably expect (2).

If we adopt (1) then we might want to define a new method which behaves as in (2).

Comment by clebertsuconic [ 18/Jul/13 01:49 PM ]

>> If we adopt (1) then we might want to define a new method which behaves as in (2).

for me, this point narrow us on (2)... because:

  • Any option given to vendors will make them implement a method that will have to perform (2). There won't be a choice, right?

I would say: lets just make sure receiveNoWait is such method.

I mean... for me, in logical terms (1) == (2)... I would then just make this into two options:

(2) and (3)

and I vote for (2)





[JMS_SPEC-84] Clarify when acknowledged persistent messages may be dropped Created: 09/Mar/12  Updated: 28/Mar/12

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

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

Tags: pd20-veryminor
Participants: Nigel Deakin

 Description   

The javadoc for javax.jms.DeliveryMode (http://docs.oracle.com/javaee/6/api/javax/jms/DeliveryMode.html) states:

Delivery mode covers only the transport of the message to its destination. Retention of a message at the destination until its receipt is acknowledged is not guaranteed by a PERSISTENT delivery mode. Clients should assume that message retention policies are set administratively. Message retention policy governs the reliability of message delivery from destination to message consumer. For example, if a client's message storage space is exhausted, some messages may be dropped in accordance with a site-specific message retention policy.

A message is guaranteed to be delivered once and only once by a JMS provider if the delivery mode of the message is PERSISTENT and if the destination has a sufficient message retention policy.

This introduces several important features of JMS which are not described in such explicit terms in the JMS specification itself, in particular the statement that a JMS provider may drop (delete from storage) an unacknowledged message if the client is somehow running out of resources. The expression "message retention policy" is not used in the spec.

Section 4.10 "Reliability" is the relevant section. This states that "Once-and-only-once message delivery, as described in this specification... does not cover loss due to resource restrictions" but does not mention that messages may be dropped from the server because the client was short of resources.

This should be clarified.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:21 PM ]

This will be evaluated by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.





[JMS_SPEC-79] New factory methods to create BytesMessage and MapMessage and set the payload Created: 20/Feb/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-minor
Participants: Nigel Deakin

 Description   

In JMS 1.1 the following methods on Session can be used to create a ObjectMessage or TextMessage and set the payload at the same time:

createObjectMessage(Serializable object)
createTextMessage(String text)

However there are no equivalent methods for BytesMessage and MapMessage. It is therefore proposed that the following new methods be added to Session (and MessagingContext):

createBytesMessage(byte[] bytes)
createMapMessage(Map map)





[JMS_SPEC-75] Ambiguous javadocs for Connection.createConnectionConsumer and createDurableConnectionConsumer Created: 15/Feb/12  Updated: 20/Mar/13

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

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

Tags: jms21doc-minor
Participants: Nigel Deakin

 Description   

The JMS 1.1 javadocs for Connection.createConnectionConsumer lists the following possible exceptions:

JMSException - if the Connection object fails to create a connection consumer due to some internal error or invalid arguments for sessionPool and messageSelector.
InvalidDestinationException - if an invalid destination is specified.
InvalidSelectorException - if the message selector is invalid.

The JMS 1.1 javadocs for Connection.createDurableConnectionConsumer lists the following possible exceptions:

JMSException - if the Connection object fails to create a connection consumer due to some internal error or invalid arguments for sessionPool and messageSelector.
InvalidDestinationException - if an invalid destination is specified.
InvalidSelectorException - if the message selector is invalid.

So what exception is thrown if a invalid message selector is supplied? An InvalidSelectorException (since the message selector is invalid) or a JMSException (invalid argument for messageSelector).

Since a InvalidSelectorException is a subtype of JMSException then it would be safe to return a InvalidSelectorException, but the javadocs as they stand are contradictory.



 Comments   
Comment by Nigel Deakin [ 20/Mar/13 12:27 PM ]

This didn't make it into JMS 2.0 and so is carried forward to JMS 2.1.





[JMS_SPEC-74] Define lifecycle of durable subscriptions used by MDBs Created: 15/Feb/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-major
Participants: Nigel Deakin

 Description   

This issue was raised on the JMS forum:
https://forums.oracle.com/forums/thread.jspa?threadID=2124418
and is being logged here on behalf of that contributor

How durable are durable topic subscriptions?

Non durable subscribers receive topic messages only if they are active at the time when the message is received and processed by the JMS engine. Durable subscribers are more complicated, they receive messages if the durable subscription is active when the message is received and processed by the JMS engine.

How do I know when messages are kept or discarded? Simply put, what is the lifecycle of the subscription?

When using synchronous receptions or message listeners, the durable subscription lifecycle is managed by the developper using Session:createDurableSubscriber and Session:unsubscribe.

When using MDB, the durable subscription lifecycle is unspecified and is application server dependant.

With JBoss 4.2, the subscription lifecyle is the same than the MDB. This means that if the application is redeployed (for example copy the new .ear over the old one in the deploy folder), there is a time frame when the subscription in non existent, so messages are lost.

WebLogic 10 also seems to associate the subscription lifecycle to the MDB. WebLogic 10 offers a flag, "durable-subscription-deletion", to allow or not the durable subscription deletion when the MDB is undeployed or removed. True means that when the application is redeployed the subscription is deleted and messages are lost. When false is used (it is the default value) the subscription remains even when the MDB is undeployed. I hope this does not mean that if we permanently undeploy the application, the subscription will stay and messages will continue to stack.

With WebSphere 6 the situation is different. The subscription is not associated to the MDB but to an activation spec that is an administred object. The MDB is merely a client of the activation spec. This way messages are kept as long as the activation spec is active, regardless of application starts/stops/redeploys/etc. Messages are not lost.

We need a portable way to use durable topics subscriptions.






[JMS_SPEC-73] Define how messages from a topic are delivered to clustered application server instances Created: 15/Feb/12  Updated: 22/Mar/13

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

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

Issue Links:
Dependency
blocks JMS_SPEC-103 A JMS 2.0 resource adapter needs to b... Closed
Tags: jms21-forreview-major
Participants: Nigel Deakin

 Description   

This issue was raised on the JMS forum:
https://forums.oracle.com/forums/thread.jspa?threadID=2124417
and is being logged here on behalf of that contributor

How many times are topic messages delivered ?

This may seem to be a trivial question, but when clustering is involved, it's not.

JEE has strong support for clustering, but many JEE specifications do not define what is actually supported, and leaves room for application server specific features. This is the case for JMS in the various specifications involved (JMS, JEE, EJB, JCA).

The question is how many times are messages delivered and treated (e.g. once per cluster or once per application server)?

Note that to simplify the problem I will not address selectors, delivery modes or acknowledgement considerations. I will also only address business application clustering, not JMS implementation clustering.

When Queues are used the situation is quite clear, the message is delivered once whether you use clustering or not. But when Topics are used, there is no simple answer.

When a message is sent to a Topic, each currently active non-durable subscriber should receive the message once. If the receiving application is clustered, the message should be received one time per application server instance in the cluster. That's what we get with JBoss 4.2.3.

This is actually not always the case. One example with WebSphere 6.1:

  • A business application is deployed to a cluster of two application servers
  • The JMS message engine is also deployed to a cluster of two application servers
  • The application uses a MDB with a non-durable subscription to a Topic
  • A message is sent to that Topic
    If the two clusters are different, then the message is received by one MDB on each application instance, so the message is treated twice. But if the two clusters are actually the same, then the message is only received by one MDB instance on the application server where the message engine instance runs, so the message is treated once instead of twice. Painful.

For reliability considerations, enterprise applications often use durable subscriptions to Topics. This makes the situation even more complicated.

Durable subscriptions are identified by a subscription name. This defines the number of deliveries, meaning that the message should be delivered once per distinct subscription name.

JMS offers three ways to receive messages: Message Driven Beans (MDB), synchronous receptions using MessageConsumer:receive and explicit message listeners using MessageConsummer:setMessageListener. We won't address message listeners as they are forbidden on the server side by the JEE specifications.

When doing synchronous receptions or message listeners, the durable subscription name is managed by the developper using Session:createDurableSubscriber. This way it is possible (it is actually required by the JMS specification) to give a different name per application instance in the cluster to choose the number of times the messages are received.

With MDB we cannot officially manage the subscription name, so there is not portable control of the number of messages delivery. Note that we cannot manage the client ID either. In more details, both client ID and subscription name are valid parameters as per the JCA specification, but they are not according to the EJB specification.

We need precise, portable and cluster compliant semantics about the number of time JMS messages get delivered.



 Comments   
Comment by Nigel Deakin [ 07/Feb/13 04:40 PM ]

The JMS 2.0 public draft (Jan 2013) specified a new feature called "subscription scope" to address this issue. This was configured using a new MDB activation property subscriptionScope. The activation properties clientId and subscriptionName were also amended to support this new feature. Here's the text that the public draft contained:

MDB Activation properties

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

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

If subscriptionScope is not set and the subscriptionDurability property is set to NonDurable then the subscriptionName property may be left unset.

If subscriptionScope is set (to Instance or Cluster) then the subscriptionName property may be left unset. A suitable subscription name will be generated automatically if needed.

If subscriptionScope is set to Instance and the subscriptionName property has been specified then the value of the subscriptionName property will be used as part of the subscription name.

If subscriptionScope is set to {[Cluster}] and the subscriptionName property has been specified then the value of the subscriptionName property will be used as the subscription name.
subscriptionScope The subscriptionScope property only applies to message-driven beans that receive messages published to a topic. It applies to both durable and non-durable subscriptions, as specified using the subscriptionDurability property.

Setting the subscriptionScope property is optional. If this property is set then it must be set to either Instance or Cluster.

For both durable and non-durable subscriptions, setting this property allows the deployer to specify the scope of the subscription that will be used.

instance scope

If the scope is Instance then the resource adapter will create a separate topic subscription for each application server instance into which the message-driven bean is deployed.

cluster scope

If the scope is Cluster, and the message-driven bean is deployed into a clustered application server, then the resource adapter will create a single shared topic subscription for the entire cluster.
If the scope is Cluster, and the application server is not clustered, then the resource adapter will create a separate topic subscription for each application server instance into which the message-driven bean is deployed.

Generation of subscription name

The resource adapter will generate a suitable subscription name in the cases where a shared subscription is used.

If the scope is Instance, the subscriptionDurability is Durable and the subscriptionName property has been specified then the resource adapter will use the subscriptionName property as part of the subscription name.

If the scope is {[Cluster}}, the {{subscriptionDurability}] is Durable and the subscriptionName property has been specified then the the resource adapter will use the subscriptionName property as the subscription name. In this case the deployer is responsible to ensuring that the specified subscriptionName is unique to this cluster.

Client identifier

If the subscriptionScope property is specified then clientId must not be specified. Otherwise a deployment error will occur.

Implementation of topic subscriptions

This section contains some additional recommendations as to how the specified ActivationSpec properties should be used in a resource adapter implementation.

When subscriptionScope is not specified

This section applies if the subscriptionScope property is not specified.

It is not defined whether a subscriptionDurability of NonDurable should be implemented using a shared or unshared non-durable subscription. If an unshared durable subscription is used then any subscriptionName specified will be ignored.

It is also not not defined whether a subscriptionDurability of NonDurable should be implemented using a shared or unshared durable subscription.

When subscriptionScope is set to Cluster

This section applies if the subscriptionScope property is set to Cluster.

It is recommended that a subscriptionDurability of NonDurable be implemented using a shared non-durable subscription.

It is recommended that a subscriptionDurability of Durable be implemented using a shared durable subscription.

If the message-driven bean is deployed into a clustered application server, then the subscription name that is generated should be the same for the same endpoint in each application server instance within the cluster but otherwise unique.

When subscriptionScope is set to Instance

This section applies if the subscriptionScope property is set to Instance.

It is not defined whether a non-durable subscription should be implemented using a shared or unshared non-durable subscription, or whether a durable subscription should be implemented using a shared or unshared durable subscription.

If the subscriptionScope property is set to instance, and the message-driven bean is deployed into a clustered application server, then the subscription name that is generated must be different for every endpoint and for every application server instance.

When subscriptionScope is set to Instance or Cluster

This section applies if the subscriptionScope property is set to either Instance or Cluster.

It is recommended that the subscription name that is generated includes a unique identifier to ensure that it is unique across other clusters or across other application server instances that are not part of the cluster.

If the application server instance into which the message-driven bean is deployed is not part of a cluster, then that the subscription name that is generated must be must be different for every endpoint and for every application server instance.

In this case it is recommended that the subscription name that is generated includes a unique identifier to ensure that it is as unique as possible across all application server instances.

Requirements for generated subscription names

The subscription name generated by the resource adapter must be a valid JMS subscription name. This means that it must be no longer than 128 characters and must consist only of Java letters or digits (as defined in the Java Language Specification) or the underscore (_), dot (.) or minus characters.

Since a durable subscription can be used to store messages indefinitely it is recommended that its name remains unchanged even if the application server is restarted or reconfigured, or if the application is redeployed.

Since a subscription name may be visible to the user or administrator it is recommended that the subscription name is at least partly human-readable.

Implementation in a resource adapter

The Java EE Connector Architecture (JCA) specification defines a method getInstanceName on javax.resource.spi.BootstrapContext and a method getActivationUniqueName on MessageEndpointFactory. If a scope of Cluster is specified then a suitable subscription name may be obtained by calling the getActivationUniqueName method. If a scope of Instance is specified then a suitable subscription name may be obtained by calling the getInstanceName and getActivationUniqueName methods and concatenating the results.

However if the subscriptionName property and the subscription is durable then the value of this property should be used instead of the value returned by getActivationUniqueName.

The term "application server instance" as used in this section refers to a single application server JVM. The exact meaning of the term "application server cluster" as used in this section is left to the application server to define but is intended to refer to a group of co-operating application server JVMs to which an identical Java EE application may be deployed.

Comment by Nigel Deakin [ 07/Feb/13 04:48 PM ]

For the reasons described here and here this feature has been dropped from JMS 2.0 and deferred until a later version of JMS.

Comment by Nigel Deakin [ 07/Feb/13 04:52 PM ]

Tagged for review for JMS 2.1

Comment by Nigel Deakin [ 22/Mar/13 05:05 PM ]

Removing "fix version=2.0" as this issue was removed from the spec





[JMS_SPEC-72] Poison message management Created: 15/Feb/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-major
Participants: Nigel Deakin

 Description   

This issue was raised on the JMS forum:
https://forums.oracle.com/forums/thread.jspa?threadID=2124413
and is being logged here on behalf of that contributor

Poison messages are messages that are redelivered again and again when an untreated error occurs, possibly resulting in CPU eating long lasting loops.

This is a well known messaging related issue, but it is not fully adressed by the JMS specification. The Message:getJMSRedelivered method can tell if a message is being redelivered. But this is not good enough and application servers implement their own solutions. Such solutions are based, for example, on redelivery limit and error destinations.

With WebSphere 6, it is possible to specify, at the SI Bus destination level, an exception destination and a maximum failed deliveries threshold. When messages consumption fails more than the threshold allows, messages are moved to the exception destination.

JBoss 4 has equivalent features, with a dead letter queue where messages that reached the redelivery limit are moved. It is also possible to use the specific 'JMS_JBOSS_REDELIVERY_DELAY' message property to specify a redelivery delay from the message producer side. JBoss 5 has the same features with the 'dead-letter-address', 'max-delivery-attempts' and 'redelivery-delay' destination configuration parameters.

WebLogic has equivalent features, see 'Error Destination', 'Redelivery Limit' and 'Redelivery Delay' parameters.

A portable mechanism should be defined.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:13 PM ]

JMS_SPEC-42 (already included in the JMS 2.0 Early Draft) makes support for JMSXDeliveryCount mandatory, which should make it easier for applications and frameworks to do their own poison message handling. However this does not itself define how poison messages are handled.

I will raise this with the expert group for possible inclusion in the JMS 2.0 Public Draft. Tagging accordingly.





[JMS_SPEC-71] Change XAConnectionFactory to extend ConnectionFactory Created: 15/Feb/12  Updated: 01/Jul/13

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

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

Issue Links:
Dependency
blocks GENERICJMSRA-55 genericjmsra gets ClassCastException ... Open
Tags: pd20-forreview-minor
Participants: Nigel Deakin

 Description   

JMS 1.1, includes the following three interface definitions:

public interface XATopicConnectionFactory extends XAConnectionFactory, TopicConnectionFactory

public interface XAQueueConnectionFactory extends XAConnectionFactory, QueueConnectionFactory 

public interface XAConnectionFactory 

why does XAConnectionFactory not extend ConnectionFactory? This is inconsistent.

Please consider changing XAConnectionFactory to extend ConnectionFactory.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:24 PM ]

We would need to consider whether changing an object's superclass is a permitted change in conformance with the Backwards Compatibility Requirements for Java EE Specifications . This interface is not intended for use by normal applications so there may be more scope to change it.

This will be evaluated by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.





[JMS_SPEC-68] Add new method Session.acknowledge() Created: 16/Jan/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-minor
Participants: crowne and Nigel Deakin

 Description   

When a session is created with an acknowledgement mode of Session.CLIENT_ACKNOWLEDGE, messages are acknowledged by calling the acknowledge() method on the Message object.

However this method is potentially misleading because calling it causes all messages delivered to the Session to be acknowledged,. It doesn't just acknowledge the Message on which the acknowledge method is called. JMS 1.1 recognised this issue and clarified the spec and javadocs to make this clear.

However the fact that the acknowledge method is on the Message is still potentially confusing. Although we can never remove this method because of the need to maintain compatibility, adding an acknowledge method to the Session would allow application code to reflect the true behaviour.

It is therefore proposed that a new method acknowledge() be added to the Session interface which causes all messages delivered to the Session to be acknowledged (i.e. identical behaviour to the existing method).



 Comments   
Comment by Nigel Deakin [ 16/Jan/12 03:38 PM ]

The proposed simplified API {JMS_SPEC-64) provides an acknowledge method on MessagingContext. Adding a similar method on Session would be consistent with this.

Comment by Nigel Deakin [ 16/Jan/12 03:41 PM ]

eg

Comment by crowne [ 17/Jan/12 07:08 AM ]

Why not be specific about the intention of the method on Session and name it acknowledgeAll();

Comment by Nigel Deakin [ 05/Mar/12 04:54 PM ]

This will be reviewed by the JSR 343 expert group. Adding appropriate tag.





[JMS_SPEC-67] Relaxing the requirement to throw an exception if a message is sent to a deleted temp destination Created: 10/Jan/12  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-minor
Participants: Nigel Deakin

 Description   

This was raised by Hiram Chirino:

As an implementor of the JMS 1.1 spec one of the things that bother me about that version of the spec is the need to throw an exception when a client attempts to send a message to a temporary destination which has been deleted.

This isn't explicitly required in the JMS spec, but it appears to be required by the TCK tests. Hiram added:

If I recall correctly, I first encountered the requirement was when I was testing Geronimo against the JMS TCK. The TCK has a test case which checked the requirement I described. I guess the TCK implementors justify the test assertion due to the API documentation on send method that states throws 'InvalidDestinationException - if a client uses this method with a QueueSender with an invalid queue.'

Hiram gave the following as his justification:

You either have do an RPC against the server for each send to verify the temp destination is still around (which is slow since your working with non-persistent messages anyways) or the client has to monitor all temp destinations on the server which increases complexity of the client and the amount of memory it uses.

It also provides very little value to the end user application since NOT getting an exception does not guarantee the message will get processed. You could have a scenario where the producer sends a message to a temp destination and then the temp destination gets deleted which means the sent message gets dropped.

Hopefully the next version of the spec will be changed so that sending to a deleted temp destination does not throw a JMSException but instead the message gets dropped by the server.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:28 PM ]

This will be reviewed by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.





[JMS_SPEC-66] Define how MessageConsumer.receive should handle a thread interrupt Created: 03/Jan/12  Updated: 08/Jan/13

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

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

Tags: pd20-forreview-minor
Participants: axel_podehl, brecht_yperman and Nigel Deakin

 Description   

The Java SE API allows an application to interrupt a running thread by calling the interrupt method on the Thread object.

I'm logging this issue to raise the question of whether JMS should define how a JMS provider should handle a thread interrupt during a call to MessageConsumer.receive() or MessageConsumer.receive(timeout), which will both block whilst waiting for a message to arrive.

There's a useful article by Brian Goetz here:
http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html

Possibilities are:

1. Leave this up to the JMS provider (which is the current situation in JMS 1.1)
2. Define that a thread interrupt should cause the receive method to throw a JMSException
3. Define that a thread interrupt should cause the receive method to throw a InterruptedException
4. Define that a thread interrupt should be ignored

Note that it would not be possible to change the signature of the existing receive methods (as in (3)) since this would break backwards compatibility.

In cases 1,2 and 4 (the ones that don't throw a InterruptedException) Brian Goetz's article recommends that the method should re-enable the interrupted status of the thread (even if the interrupt was swallowed or converted a JMSException) to allow the calling code to detect whether an interrupt had occurred.

In logging this issue I'm not proposing any change, but the topic is worth recording and I'd welcome comments.



 Comments   
Comment by brecht_yperman [ 03/Jan/12 03:27 PM ]

Having encountered this issue with JMS 1.1 and OpenMQ, I'd personally prefer option 2.

MessageConsumer.receive() is an operation very similar to a blocking read, described in the API

"If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException."
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#interrupt()

I also think, but this is of course guessing, that most JMS clients do a blocking socket read anyway, so they can easily handle the InterruptedException thrown by that read.

Just my two cents.

Comment by Nigel Deakin [ 08/Mar/12 12:28 PM ]

This issue will be considered by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging appropriately.

Comment by axel_podehl [ 08/Jan/13 12:56 PM ]

I would prefer 3 (throw InterruptedException)- if it wouldn't break the API.
So choice 2 (throw JMSException) is the second best alternative

Probably the JMS Provider should set JMSException.setLinkedException() to be the InterruptedException





[JMS_SPEC-59] Basic metadata/management via JMS Created: 17/Nov/11  Updated: 11/Sep/12

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

Type: New Feature Priority: Major
Reporter: koen.serneels Assignee: Unassigned
Resolution: Unresolved Votes: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by JMS_SPEC-15 Queue Depth Resolved
is duplicated by JMS_SPEC-16 Depth of messages for a durable subsc... Closed
is duplicated by JMS_SPEC-17 Durable subscription iterator Closed
Tags: pd20-forreview-major
Participants: koen.serneels, Nigel Deakin, nwright and rdohna

 Description   

Possibility for metadata in JMS API. Ex. retrieving Queue depth.
Although providers will probably not be able to supply real-time accurate readings, it can be very handy to read out the current depth even if not 100% accurate.
Currently the only way is to browse a queue and count messages (or use provider specific commands).
Other suggestions are: max queue depth, max queue message size and so forth

Management like moving data between objects or deleting messages in one time.
The latter one has currently be accomplished by doing (destructive) reads which is of course not not performant.
(alternatives are provider custom commands, which we would like to avoid for very basic management things like described)



 Comments   
Comment by rdohna [ 21/Nov/11 08:08 AM ]

@Koen: I think this suggestion needs to be more specific before it can be reasonably evaluated. Could you provide more information of what you are interested in... and why?!? The current and maximum number of messages in a destination look like monitoring to me. Or do you do load balancing with that?

Comment by koen.serneels [ 23/Nov/11 02:14 PM ]

I did not mean it from the point of load balancing.

The JMS metadata API (I compare it with the JDBC metadata API) would allow users to obtain information about the object they are working with. The example I gave is queue depth.
Just look to a Q object in for example MQ and see what kind of metadata you can retrieve of it.
I understand that some of them are provider specific, but queue depth is something very universal.

The reason to obtain queue depth could be from a "monitoring" point of view.
It could also be from a debug point of view.
Fact is that such data could be interesting to retrieve via de JMS metadata API, which is now all provider specific. Another one would be to get a list from existing MOM objects.

Which is also possible via the JDBC metadata API, you can also ask the question "why do you want to know which tables are in a db, or which are the columns of a given table?"
It is just handy in some circumstances and imho should be part of the JMS api (as metadata)

Fact is that MOM's are mostly used in asynch systems, any help of getting information about status or processing progress is welcome. This now all needs to be done via provider specific APIs

Comment by rdohna [ 23/Nov/11 02:44 PM ]

Okay... fair enough. I only see monitoring and management clearly out of the scope of JMS.

Comment by koen.serneels [ 24/Nov/11 11:25 AM ]

What's in name.
You see queue depth for monitoring, I see it for other use cases.
Management; the JMS API currently allows to create temporary queue's, that is also management for me.

The goal of the JMS API is to make developers as easy as possible to access a broad set of MOM related features in an non obscure way.
Imho the JMS API is currently:

  • Very obscure
  • Very limited in functionality

Just look at the JDBC API, why would the JMS API just limit itself to putting and reading messages?

There are techniques in which you can clearly separate these kind of functions from the core JMS API (again , see the JDBC API).
You now have the chance to enchance this API so that a lot of functionality will become standerd instead of falling back to provider specific APIs.

Afaik I don't see any good reason why meta data about the MOM objects would form a problem to incorporate as part of the JMS API.

Comment by Nigel Deakin [ 09/Dec/11 10:29 AM ]

For project management reasons I'll ask the expert group to consider this after the JMS 2.0 Early Draft.

Comment by Nigel Deakin [ 09/Mar/12 04:33 PM ]

This issue should consider the following specific requirements:

JMS_SPEC-14 - a durable subscription browser
JMS_SPEC-15 - API to return queue depth
JMS_SPEC-16 - API to return durable subscription depth
JMS_SPEC-17 - API is a way to find out the names/clientIDs of all durable subscriptions

Comment by Nigel Deakin [ 06/Sep/12 04:54 PM ]

This issue should also consider a feature to allow users to obtain information about those messages on a queue or topic subscription which have not yet reached their delivery time and so are not yet eligible for delivery to consumers.

Comment by Nigel Deakin [ 07/Sep/12 04:22 PM ]

Here's another suggestion from a EG member:

Maybe it's worth adding a completely new QueueBrowser-Interface called DestinationBrowser. This would allow it to:
a) fetch current and future messages (getCurrentMessages and getFutureMessages, boolean arguments always have the potential of getting mixed up)
b) return an Iterator instead of an Enumeration
c) delete messages through the Iterator
d) return future messages in a topic as well!
e) return a Destination with getDestination, not only a Queue with getQueue.

The QueueBrowser-Interface would be soft-deprecated, i.e. only in the comment.

Comment by nwright [ 11/Sep/12 11:52 AM ]

Maybe it's worth adding a completely new QueueBrowser-Interface called DestinationBrowser. This would allow it to:
a) fetch current and future messages (getCurrentMessages and getFutureMessages, boolean arguments always have the potential of getting mixed up)
b) return an Iterator instead of an Enumeration
c) delete messages through the Iterator
d) return future messages in a topic as well!
e) return a Destination with getDestination, not only a Queue with getQueue.

The QueueBrowser-Interface would be soft-deprecated, i.e. only in the comment.

As discussed, were this to be implemented I'd like clarify that it includes full durable/non durable topic browsing.





[JMS_SPEC-58] New method Message.copyMessage() to create a mutable copy of a received message Created: 17/Nov/11  Updated: 28/Mar/12

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

Type: New Feature Priority: Major
Reporter: koen.serneels Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-forreview-major
Participants: koen.serneels, Nigel Deakin and rdohna

 Description   

javax.jms.Message is mutable when first created.
On a TextMessage you can set for example 'the text'.You can also set properties.
However, after receiving a message, setting a property does not work anymore before clearing the properties explicitly
This means that if you want to re-send the same message + extra properties, you need to read them, store temporary, clear message and set them again.

Suggestion is to foresee somekind of copy constructor, or another way of creating a new message from an existing one.
Another way could be to let the properties be mutable.



 Comments   
Comment by rdohna [ 21/Nov/11 08:10 AM ]

I like the copy-constructor... this may also help resolve JMS_SPEC-60

Comment by Nigel Deakin [ 09/Mar/12 04:22 PM ]

The reason you need to call clearProperties() before setting individual properties on a received message is given in section 3.10. "Changing the value of a received message" of the JMS 1.1 spec. This states:

When a message is received, its header field values can be changed; however, its property entries and its body are read-only, as specified in this chapter.

The rationale for the read-only restriction is that it gives JMS Providers more freedom in how they implement the management of received messages. For instance, they may return a message object that references property entries and body values that reside in an internal message buffer rather than being forced to make a copy.

A consumer can modify a received message after calling either the clearBody or clearProperties method to make the body or properties writable. If the consumer modifies a received message, and the message is subsequently redelivered, the redelivered message must be the original, unmodified message (except for headers and properties modified by the JMS provider as a result of the redelivery, such as the JMSRedelivered header and the JMSXDeliveryCount property).

I think that explanation is still valid and so the existing behaviour is justified.

The proposal for a copy constructor is worth considering and will be considered by the expert group for inclusion in the JMS 2.0 early draft. Tagging appropriately.

Comment by Nigel Deakin [ 09/Mar/12 04:23 PM ]

Description of this issue changed from "Immutability Message properties" to "New method Message.copyMessage() to create a mutable copy of a received message" to better describe the proposal.





[JMS_SPEC-57] Add Java EE 7 multi-tenancy support Created: 11/Nov/11  Updated: 30/Aug/12

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

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

Tags: ed21
Participants: Nigel Deakin

 Description   

The JMS 2.0 specification needs to be extended to support multi-tenancy as defined in Java EE 7.

This is a placeholder issue: proposals are contained in this document:
http://java.net/projects/jms-spec/downloads/download/JMS20MTv3.pdf



 Comments   
Comment by Nigel Deakin [ 30/Aug/12 10:34 PM ]

The Java EE platform spec lead has announced "that we defer to Java EE 8 the areas of PaaS enablement and multitenancy support".

I am therefore deferring this issue as well from JMS 2.0 until the next version. Tagging for consideration for JMS 2.1.





[JMS_SPEC-47] Deprecate domain-specific APIs and propose for removal Created: 15/Aug/11  Updated: 24/Feb/12

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

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

Tags: eg pd20-underreview
Participants: Nigel Deakin

 Description   

Summary

In version 1.0b of the JMS specification, applications had to use a completely separate set of interfaces when working with queues as they did when working with topics.

Specifically, applications working with queues had to use the interfaces QueueConnectionFactory, QueueConnection, QueueSession, QueueSender and QueueReceiver, whilst applications working with topics had to use the interfaces TopicConnectionFactory, TopicConnection, TopicSession, TopicPublisher and TopicSubscriber.

Although these two sets of interfaces shared common supertype interfaces ConnectionFactory, Connection, Session, MessageProducer and MessageConsumer, these were effectively abstract classes, and applications were forced to use the interfaces specific for the messaging domain (queue or topic) that they were using.

In version 1.1, new API methods were added to the common superclass, domain-independent, interfaces to allow them to be used directly by client applications. This offered a simpler programming model, and for first time allowed queues and topics to participate in the same local transaction, now that they could be accessed using the same session.

In JMS 1.1 all of the domain-specific interfaces were retained to provide backwards compatibility, but it was stated in Section 1.5 that "in the future, some of the domain-specific APIs may be deprecated".

For 2.0 it is time to take this to the next stage, and to formally announce that these interfaces are now deprecated and that they will be removed from a future version of the specification.

This would remove 15 interfaces from JMS and reduce the total number of interfaces by 34%, from 44 to 28.

Detail

This change would affect the following interfaces:

XAQueueConnection
XAQueueConnectionFactory
XAQueueSession
XATopicConnection
XATopicConnectionFactory
XATopicSession
QueueConnection
QueueConnectionFactory
QueueReceiver
QueueSender
QueueSession
TopicConnection
TopicConnectionFactory
TopicPublisher
TopicSession
TopicSubscriber

There would be two changes:

  • These interfaces would be formally marked as deprecated, by use of the @java.lang.Deprecated annotation. This would cause compilers to issue a warning when a deprecated method was used.
  • These interfaces would be formally marked in the specification as being "proposed for removal", with the expectation that they would be made optional in the next release.

There do not appear to be any binding policies on how to deprecate or remove classes from a Java EE API, which means that the final decision is up to the expert group. However the Java EE Specification, section EE.6.1.3 "6.1.3Pruned Java Technologies" (which discusses a different issue, that of removing entire technologies from Java EE), links to a Java SE policy described at http://mreinhold.org/blog/removing-features, which appears to be a suitable policy to offer.

That policy states that a particular version of a spec may state that a feature is "proposed for removal". This means that the following version can remove it.

However that policy also states that "removal" of a feature does not mean actually deleting it. Instead the feature will remain in the specification but will become optional. This means that implementers are not required to implement it. Its tests will remain in the TCK to allow those who decide to implement it to verify that it has been implemented correctly.

Other issues

Before making this change we should confirm that the "domain-independent" interfaces are a complete replacement for the "domain-specific" interfaces.

It has been noticed that Session.createDurableSubscriber() returns a TopicSubscriber, not a MessageConsumer. This looks to me like a mistake which would need to be fixed before we could remove TopicSubscriber. The solution would be for this method to return a MessageConsumer. Since this is a supertype of TopicSubscriber it should not break existing applications. (Edit: This has now been raised separately as JMS_SPEC-51 )






[JMS_SPEC-41] Support topic hierarchies Created: 05/Aug/11  Updated: 08/Jan/13

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

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

Tags: pd20-underreview
Participants: axel_podehl and Nigel Deakin

 Description   

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

It is proposed that the JMS specification supports "topic hierarchies". These are also known as subject hierarchies or wildcard subscriptions.

The JMS 1.1 specification states that a topic is a "well-known node in a content-based hierarchy" but does not specify how this hierarchy is used, how topics are named, or define any special functionality to operate on more than one node of the hierarchy at the same time.

It is proposed that new features are added to JMS to explicitly support the use of topic hierarchies. More detailed proposals will follow: this JIRA issue is a placeholder.

Most JMS vendors and (and other pub/sub products) already support topic hierarchies, and they are integral to a variety of standards, including AMQP, Web Services Event Notification, and the Bayeaux protocol. They provide an intuitive solution for optimized message filtering, routing, and replication. Support for topic hierarchies would also be helpful for simplifying the integration of JMS applications into messaging environments that already depend on topic hierarchies.



 Comments   
Comment by axel_podehl [ 08/Jan/13 03:18 PM ]

I would think it'll be difficult and cumbersome to specify and use a provider-unspecific topic hierarchy. The ways wildcards actually work with different JMS providers are more diverse than you would initially think (or hope).

E.g. MQSeries Topics:

"Sport/#/Results" matches "Sport/Football/Spurs/Results"
while
"Sport/+/Results" only matches "Sport/Football/Results"
but also
"Sport/#" matches "Sport"

with TIBCO EMS and ActiveMQ, separators (. instead of /) and wildcards are different,
but also their meaning:

"Sport.>.Results" is invalid
"Sport.*.Result" would work as well
"Sport.>" does not match "Sport"

Also leaving it up to individual providers on how exactly topic names or hierarchies work is a great differentiator, leaving room for innovation. A simple String as topic name can be used to define additional properties of a topic on the fly, e.g. in ActiveMQ: "temp-queue://TEST?consumer.prefetchSize=10"

Nice-to-have though, when writing provider-unspecific code, would be these methods:

public boolean Destination.isWildcard()
public boolean Destination.isMatching(String wildcard)





[JMS_SPEC-36] Allow messages to be delivered asynchronously in batches Created: 29/Jul/11  Updated: 19/Sep/13

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

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

Issue Links:
Dependency
blocks JMS_SPEC-56 Enhance the EJB specification to supp... Closed
Tags: ed21 jms21-forreview-major
Participants: colincrist and Nigel Deakin

 Description   

It is proposed that the JMS API be extended to allow messages to be delivered to a MessageListener in batches rather than individually as in JMS 1.1.

Currently, messages are delivered asynchronously by calling the javax.jms.MessageListener method onMessage(Message message).

However some applications could process messages more efficiently if they were delivered in batches. Applications would define a new listener class javax.jms.BatchMessageListener with a callback method onMessages(Message[] messages).

It would be necessary to configure this by adding a new method to javax.jms.MessageConsumer:

void setBatchMessageListener(BatchMessageListener listener, int batchSize, long batchTimeOut)

Sets the message consumer's batch message listener. Attempting to set both a message listener and a batch message listener on the same MessageConsumer would cause a javax.jms.IllegalStateException.

  • listener The BatchMessageListener being set
  • batchSize If set to a value greater than zero, messages will be delivered in batches of up to batchSize messages. The actual batch size used may be smaller than this, but it may never be larger.
  • batchTimeOut The maximum number of milliseconds that the JMS provider may defer message delivery for in order to assemble a batch of messages that is as large as possible but no larger than the batch size.

Acknowledgement:

  • If auto-acknowledgement was being used, all messages in the batch would be acknowledged together. Section 4.4.12 "Duplicate Delivery of Messages" of the JMS 1.1 spec explains that when auto-acknowledgement is being used, if a failure occurs, clients can't know for sure whether the message has been successfully acknowledged, and so the last consumed message may may be redelivered. This section would need to be extended to state that in the case of batch delivery, if a failure occurs, all messages in the last batch may be redelivered.
  • If dups-ok acknowledgement was being used, message acknowledgement would follow existing semantics.
  • If client acknowledgement, or local or global transactions, were being used then message acknowledgement would follow existing semantics, which is that a call to acknowledge(), or the commit of the transaction, would acknowledge all unacknowledged messages delivered by the session.


 Comments   
Comment by Nigel Deakin [ 26/Sep/11 11:14 AM ]

Updated description to specify that a new kind of listener would be used BatchMessageListener which was set by calling setBatchMessageListener(listener, batchSize, batchTimeout).

Comment by Nigel Deakin [ 13/Dec/11 12:47 PM ]

Corrected formatting errors and typos above.

I considered whether there should be a method setbatchMessageListener(BatchMessageListener listener) which used values of batch timeout and batch size that were set using new setter methods setBatchTimeout and setBatchSize.

I decided that decided that this was not appropriate since

  • you can only set a single listener on a given MessageConsumer so setting the batch timeout and batch size on the MessageConsumer does not avoid any repetition of values.
  • there is no sensible default batch size or batch timeout. Offering a default batch size of 1 is safe but unhelpful, and there is no sensible default batch timeout. So it is appropriate and reasonable to expect the application to set these in the call to setBatchMessageListener(BatchMessageListener listener, int batchSize, long batchTimeOut).
Comment by Nigel Deakin [ 14/Dec/11 12:55 PM ]

In order to allow the existing "Chapter 8 API" to use the BatchMessageListener interface it will be necessary to add a new method to javax.jms.Session:

void setBatchMessageListener(BatchMessageListener listener, int batchSize, long batchTimeOut)

This would be optional just as the existing setMessageListener method is.

Comment by Nigel Deakin [ 15/Dec/11 05:51 PM ]

I've now updated the javadocs and the draft spec with details of this new feature (these changes are additive, so those docs include other changes).

The updated Javadocs are here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar
(See two new methods on MessageProducer, two new methods on MessagingContext, and a new interface CompletionListener)

The updated draft spec is here:
http://java.net/projects/jms-spec/sources/repository/content/jms2.0/specification/word/JMS20.pdf
(All changes are highlighted clearly with changebars. The main changes now are a new BatchMessageListener interface and new methods on MessageConsumer and MessagingContext. I've also added new methods to Session for use with the ConnectionConsumer API)

Comment by colincrist [ 12/Jan/12 03:32 PM ]

I'd like to add a comment on a specific use case I've seen from time to time with queues and durable subscriptions - mostly the latter - and I think it probably fits here.

Consider a service (MDB or plain JMS) starting up and there are a bunch of messages on a queue or durable subscription for it to process. The simple way is to begin processing then one by one.

However this can be quite inefficient if the processing for each message is time consuming and there is a big backlog of messages. Often there are many changes in the batch for the same entity (e.g. order/trade etc) and earlier versions of the update messages can either be skipped or merged together to result in a single update to each entity for the batch.

An optimisation is to:

*) consumer all the messages available (or in large batches) in a transaction [I've seen this done by going behind the JMS API to JMX or a custom API and get the queue depth or durable subscription depth - often requiring different authentication - ikky]
*) pre-process all the messages coalescing or discarding messages no longer relevant.
*) process the resulting batch of updates.

Couple of questions:

1) Reading the current version of the spec for batch delivery can you confirm that it is the intention that this pattern can be used? If I were to setBatchMessageListener(foo, 1000, 0) and there were X thousand messages pending then I'd then those messages in batches of 1000 and then very small batch message delivery depending on the implementation/message rate etc after that.

2) There seems to be no matching synchronous Message[] MessageConsumer.receiveBatch(int batchSize, long batchTimeout). Is this intentional and if so what's the rational for not including it?

Comment by Nigel Deakin [ 13/Mar/12 05:30 PM ]

@colincrist: Please note that the best place for general discussion is users@jms-spec.java.net

(1) Calling setBatchMessageListener(foo, 1000, 0) would means that the application was requesting messages to be delivered in batches of no more than 1000. A timeout of 0 means that the JMS provider is allowed to delay message delivery as long as it wanted in order to assemble a batch of the required size. I think a shorter timeout than that would almost always be preferable.

So if this was called when there were 3500 messages on the queue, three batches of 1000 would be delivered and then the server would wait, potentially for ever, for a fourth batch to be assembled.

If a smaller tineout were specified (say 1000ms) then the server would wait for 1 second and then deliver a batch of 500.

The JMS provider is allowed to deliver a smaller batch size than is requested, and to use a shorter timeout than that requested. However the basic idea is that specifying a batch size of 1000 means that they application would prefer batches of 1000 if possible. So although a JMS provider could probably legally offer the behaviour you describe, this would be contrary to what is intended.

(2) Yes this was intentional, since in this case an application could assemble a batch of 1000 simply by calling receive() 1000 times, which would not be possible in the async case. However I can see merit in allowing batches to be delivered to sync consumers as well. Watch this space...

Comment by Nigel Deakin [ 20/Apr/12 02:36 PM ]

Following discussions on the JSR 343 expert group it is clear that there is insufficient support for this change, so I'm removing all references to batch delivery from JMS 2.0.

There does appear to be some support for looking at this again in the Java EE 8 timescale, when changes to the JCA spec may allow a more generic way of defining async message listeners that does not rely on implementing a specific interface. This would allow the delivery of batches of messages without complicating the API unduly.

We'll look at this again for JMS 2.1. Tagging accordingly.





[JMS_SPEC-24] Clarify classloader used in ObjectMessage.getObject() and/or provide new method getObject(ClassLoader classLoader) Created: 04/Jul/11  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-minor
Participants: F.Degenaar and Nigel Deakin

 Description   

It is specified neither in the spec nor in the API JavaDoc which ClassLoader is to be used, when the object gets deserialized in ObjectMessage.getObject().
This omission lead to different implementations (and bugs) among JMS providers, as can be seen here:
http://www-01.ibm.com/support/docview.wss?uid=swg1IC72855
http://www.coderanch.com/t/313402/EJB-JEE/java/Exception-receiving-ObjectMessage-JMS
http://forums.oracle.com/forums/thread.jspa?threadID=738545
http://community.jboss.org/message/437144#437144

Alternatively, if it isn't possible to specify the class loader, add a method "Serializable getObject(ClassLoader classLoader) to ObjectMessage.



 Comments   
Comment by Nigel Deakin [ 08/Mar/12 12:25 PM ]

Would the person who raised this issue like to propose what kind of clarification they would want to see?

Standard Java deserialization uses the java.io.ObjectInputStream.readObject() method.

The default behaviour of ObjectInputStream.readObject() is described in the javadoc for ObjectInputStream.resolveClass() here. This states that the class loader loader is determined as follows:

if there is a method on the current thread's stack whose declaring class was defined by a user-defined class loader (and was not a generated [class] to implement reflective invocations), then loader is [the] class loader corresponding to the closest such method to the currently executing frame; otherwise, loader is null

However some JMS providers appear to override this behaviour, perhaps to use the context class loader if using the class loader provided by default cannot load the class.

Trying the context class loader is more flexible, though it still relies on the context class loader being configured appropriately, which is not under direct application control in a MDB or message listener where the thread is created by the JMS provider or application server. In addition, the first of the four examples given above suggest that even when messages are consumed synchronously using a application thread, the deserialization may still be performed in a separate JMS provider thread. So requiring the deserialization to try the context class loader may not always solve the problem.

The submitted proposes a new method getObject(ClassLoader classLoader) on java.jms.ObjectMessage. This would be simple to implement and not impact on existing JMS providers or applications, so seems a good candidate for consideration.

I'll raise this topic with the expert group. Tagging appropriately.

Comment by Nigel Deakin [ 12/Mar/12 04:21 PM ]

Description changed from:
Clarify, which ClassLoader to use when invoking ObjectMessage.getObject()
to:
Clarify classloader used in ObjectMessage.getObject() or provide new method getObject(ClassLoader classLoader)

Comment by F.Degenaar [ 13/Mar/12 05:41 PM ]

My take on the first example was a different one: the problem was, that the object was deserialized internally before getObject() was called. So, using the context class loader should have helped avoiding the issue.
Still, neither spec nor javadoc mention the default behaviour from ObjectInputStream.resolveClass(). Defining it as default will not resolve all problems, but most of them. I still see this as an improvement, especially when an alternative classloader can be chosen with the overloaded version.

Comment by Nigel Deakin [ 13/Mar/12 05:55 PM ]

@F.Degenaar: In the first example, the object was deserialized in an internal JMS thread. How would it help to mandate that it should use the context class loader, since the application has no way to configure the context class loader of an internal JMS thread?

Comment by F.Degenaar [ 13/Mar/12 11:44 PM ]

@Nigel Deakin: A new method getObject(ClassLoader classLoader) alone cannot solve the problem described in the first example. The ClassNotFoundException will be thrown either which way, because the the deserialization happens independently in an internal thread.
At present it is impossible to predict, if ObjectMessage can be used to transport non-JDK classes even with a certified JMS provider.
If the context class loader (or the one specified as an parameter) is mandated as the only one to use, the control will be in the hands of the application or the application server.
Anything else would than be a vendor extension, which can be used at will.

Comment by Nigel Deakin [ 14/Mar/12 10:11 AM ]

F.Degenaar writes:

A new method getObject(ClassLoader classLoader) alone cannot solve the problem described in the first example. The ClassNotFoundException will be thrown either which way, because the the deserialization happens independently in an internal thread.

We would define getObject(ClassLoader classLoader) as meaning that the object must be deserialised using the specified class loader. So if a suitable class loader is specified it will not fail.

If the provider also deserialises the object eagerly in a separate thread created by the JMS provider (to improve the performance of a subsequent call to the existing getObject()) then how are you suggesting we specify which class loader it uses? Specifying that it uses the context class loader isn't a help, since the application doesn't have any way to configure the context class loader if a provider-created thread.

I'm not sure exactly what you are asking for here. Please do suggest some text!

Comment by F.Degenaar [ 14/Mar/12 06:40 PM ]

Please keep in mind, that English is not my native language. That said:
As an addition to the Returns:-JavaDoc of ObjectMessage.getObject():
"Any deserialization necessary must only happen using the context class loader of the thread, in which this method was invoked."
For the proposed method getObject(ClassLoader classLoader) the JavaDoc for the parameter classLoader would read:
"The class loader to be exclusively used for any deserialization necessary."

What I am trying to achieve here?

  • If no deserialization is necessary, the class loader obviously doesn't matter (think in-memory provider).
  • If a deserialization happens, the developer or an application server have control over which class loader is used by setting the context class loader beforehand.
  • Every spec-compliant optimization is transparent to the application.
  • Any optimization violating the spec will be explicit by a cast to a vendor-specific class or interface, in the configuration of the provider or the initialization of factory objects etc.
Comment by Nigel Deakin [ 15/Mar/12 11:04 AM ]

Thanks for clarifying what you are asking for. My goal at this stage is simply to ensure that this issue is clearly described. Now it is, we can now leave it for later review by the expert group.





[JMS_SPEC-21] Support for pre-acknowledge ack mode Created: 08/Jun/11  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-major
Participants: Nigel Deakin and timlfox

 Description   

Many messaging systems allow messages to be automatically acknowledged on the server before they are delivered to their consumers. This feature is useful for transient messaging use cases where it does not matter if some messages are lost on failure (e.g. stock pricing information).

JMS does not currently provide an acknowledgment mode which supports pre-acknowledgment on the server, so there's extra (unnecessary) traffic due to acks having to be sent from client--server.

In reality most JMS implementations provide pre-ack as an extension to the set of JMS ack modes. I would like to propose that pre-ack is added to the list of standard ack modes in JMS.



 Comments   
Comment by Nigel Deakin [ 08/Jun/11 03:34 AM ]

Can you give more information about what you mean by "pre-acknowledgment on the server"?

Comment by timlfox [ 08/Jun/11 03:48 AM ]

In JMS messages are not removed from the server, and are available for redelivery until they are acknowledge by the client. This occurs by the client either:

a) Committing a transaction
b) Explicitly acking CLIENT_ACKNOWLEDGE
c) Acks being sent from the client when either DUPS_OK_ACKNOWLEDGE or AUTO_ACKNOWLEDGE is used

In all above cases it requires traffic from the client to the server for the acks

In many cases (e.g. transient messaging, stock prices), the messages are dispensable, it doesn't matter if a few are lost on event of failure. In such a case it makes sense for the server to automatically ack the message before delivery to the consumer.

This can result in less traffic and less work to do on the client, also the server can get rid of the message immediately after delivery and does not have to retain it for possible future redelivery.

This is already implemented by messaging systems including HornetQ and Weblogic JMS. Would be nice to have this in the JMS spec since it's such a common extension.

Comment by timlfox [ 08/Jun/11 03:50 AM ]

In weblogic this is called NO_ACKNOWLEDGE http://download.oracle.com/docs/cd/E13222_01/wls/docs81/javadocs/weblogic/jms/extensions/WLSession.html#NO_ACKNOWLEDGE

In HornetQ it's called pre-acknowledge
http://docs.jboss.org/hornetq/2.2.2.Final/user-manual/en/html/pre-acknowledge.html

Comment by Nigel Deakin [ 22/Feb/12 12:00 PM ]

The fact that two vendors support this already makes this a good candidate for inclusion in JMS. I will formally raise this with the Expert Group for possible inclusion in the Public Draft. Setting appropriate tag.





[JMS_SPEC-18] Standard set of server JMX MBeans Created: 24/May/11  Updated: 28/Mar/12

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

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

Issue Links:
Duplicate
is duplicated by JMS_SPEC-15 Queue Depth Resolved
is duplicated by JMS_SPEC-16 Depth of messages for a durable subsc... Closed
is duplicated by JMS_SPEC-17 Durable subscription iterator Closed
Tags: pd20-forreview-major
Participants: colincrist and Nigel Deakin

 Description   

A JMS implementation typically consists of one or more server processes.

As a monitoring client I would like to connect to these processes and discover a standard set of statistics (connections, queues, subscriptions, durables...) and for it to expose a standard set of administrative operations. such as JMS_SPEC_14,15,16 and 17.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:20 PM ]

This will be evaluated by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.

Comment by Nigel Deakin [ 09/Mar/12 07:09 PM ]

JMS_SPEC-14 is a durable subscription browser
JMS_SPEC-15 is a way to return queue depth
JMS_SPEC-16 is a way to return durable subscription depth
JMS_SPEC-17 is a way to find out the names/clientIDs of all durable subscriptions





[JMS_SPEC-14] Durable subscription browser Created: 24/May/11  Updated: 28/Mar/12

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

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

Tags: pd20-forreview-major
Participants: colincrist and Nigel Deakin

 Description   

Many if not all JMS providers give the ability to programmatically browse messages undelivered to a client on a durable subscription. Some do it via a custom API, some via JMX.

A standard way of doing this for all providers would make tooling easier.



 Comments   
Comment by Nigel Deakin [ 09/Mar/12 02:19 PM ]

I'm going to handle this as a request for a feature analogous to the existing JMS queue browser API which would allow a durable subscription to be browsed.

An alternative would be to provide a JMX API, but since JMS does not currently offer a JMX API this is a bigger issue which will be considered separately in JMS_SPEC-18, and not here.

This will be evaluated by the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.





[JMS_SPEC-11] Support for STOMP messaging Created: 18/May/11  Updated: 10/May/13

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

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

Tags: pd20-forreview-vague
Participants: abien, fribeiro and Nigel Deakin

 Description   

Just like with AMQP in JMS_SPEC-9, the STOMP protocol should be taken into consideration in the next release of the spec.

It should continue to be a goal of this specification, though, to make it easier to implement the API on top of whatever wire protocol is chosen by the vendor.



 Comments   
Comment by abien [ 18/Jun/11 12:48 AM ]

Could you please be more precise? JMS is just an API, not a wire protocol. Could you give a concrete example?

But :+1 for every JMS-API change which would improve interoperability with STOMP or any other relevant messaging product.

Comment by Nigel Deakin [ 12/Mar/12 03:14 PM ]

This needs some specific proposals.

This general topic will be raised with the expert group for possible inclusion in the JMS 2.0 public draft. Tagging accordingly.

Comment by fribeiro [ 10/May/13 12:53 AM ]

You may want to go ahead and close the issue.





[JMS_SPEC-9] Support for AMQP messaging Created: 17/May/11  Updated: 10/May/13

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: Unassigned
Resolution: Unresolved Votes: 4
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: pd20-forreview-vague
Participants: abien, bsnyder, clebertsuconic, fribeiro, John D. Ament, Nigel Deakin, rdohna, timlfox and tom.barnes

 Description   

http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol

AMQP adds support for a number of the same things that JMS supports today, and adds to that model. I believe that by JMS 2.0 supporting the AMQP model it allows for cross-system integration, as well as cross-language integration.



 Comments   
Comment by clebertsuconic [ 17/May/11 06:48 PM ]

AMQ*P* (as the name says) it's a protocol.

I don't think many providers will like the idea on having them implement any given protocol as part of the JMS spec.

Comment by tom.barnes [ 18/May/11 07:54 AM ]

If we want to strengthen the JMS API interop story with projects like AMQP, I think we should consider (A) adding to the specification so that it forms a superset of AMQP capabilities, and (B) spinning-off a seperate specification for C and .NET APIs.

Comment by fribeiro [ 18/May/11 11:06 AM ]

I think AMQP needs to be taken into consideration in JMS 2.0, even though it should continue not to require a specific wire protocol.

For a start, you shouldn't need to use a vendor API to define which wire protocol must be used by a connection factory.

I don't think we need to create JMS bindings for other platforms, which AMQP allows to continue to have whatever API they want.

Comment by clebertsuconic [ 18/May/11 01:23 PM ]

<sarcasm>Lets add stomp then! </sarcasm>

Comment by clebertsuconic [ 18/May/11 01:52 PM ]

Let me explain my sarcasm:

Protocols are part of design choices. They are the secret sauce sometimes on the message system.

You start to infer how a message system will have to be implemented.. you start to lose attraction to this specification.

I believe in interoperability, but I don't think the JMS API is a place to define wire protocol or implementation specifics on configuration.

I believe wire protocol is beyond the scope of the proposed draft anyway. And I don't see anything needed at the API level.

If there's something that can be done at API in a generic fashion... then lets do it.. but you would need to make a concrete proposition instead of an abstract approach on supporting AMQP.

That's just IMO anyway.

I will let other expert members to chime in on this subject

Comment by fribeiro [ 18/May/11 02:24 PM ]

Again, I think the spec should continue not to specify a wire protocol, but I don't think it is a bad thing to look at the new protocol and see if there is anything that we can do in the API to make it easier to implement JMS on top of AMQP.

Regarding STOMP, since the API has been implemented on top of it as well (http://stomp.codehaus.org/Stomp+JMS), I really think it should receive the same whatever treatment we choose to give to AMQP.

Comment by bsnyder [ 18/May/11 04:12 PM ]

I had a long discussion with Nigel a couple weeks ago regarding my interest in AMQP and STOMP and seeking better points of supporting various wire-level formats underneath the JMS API. I don't believe that the JMS spec should specify a wire-level format, but I do agree that we should understand these formats enough to make sure that the JMS APIs can accommodate them. The same can be said for WebSockets. I've received questions about all of these technologies and how best to use and/or integrate JMS with them. I think it would be worthwhile for this group to discuss this topic and provide some support and possibly examples.

This is another topic regarding integration. I'm seeing a theme here .

Comment by fribeiro [ 18/May/11 08:23 PM ]

Agreed.

Comment by timlfox [ 19/May/11 12:32 AM ]

1) The AMQP model from 0.8/0.9/0.10 is not rich enough to support JMS. The only implementation that does do "JMS over AMQP" (Qpid), IIRC can only do so by introducing extensions over and above that specified by AMQP. So, JMS over AMQP is really a myth. With AMQP 1.0 there isn't a broker model at all! So this is really a non started unless the AMQP spec changes considerably

2) AMQP as a protocol is far too verbose and clunky to create high speed JMS implementations. The high performers in the JMS space, e.g. TibcoEMS, HornetQ, SonicMQ etc owe a lot of their performance to highly optimised wire protocols. They would have to sacrifice that performance if they were to transport over AMQP. Why would they want to do this?

3) So far, interoperability between implementations (the raison d'etre) of AMQP has largely been a fantasy. Perhaps this will change with 1.0, if enough systems implement it. Also, as mentioned before, AMQP 1.0 does not specify a broker model so if interoperability occurs, it's scope is very limited and certainly not enough to support JMS semantics.

Comment by rdohna [ 19/May/11 05:43 AM ]

I agree that we should take a look at AMQP and STOMP and maybe other wire protocolls in order to learn, but not endorse any of them for the JMS spec... that's a completely separate snake pit that we should avoid to get into.

BTW: RabbitMQ supports AMQP and JMS, doesn't it?

Comment by fribeiro [ 19/May/11 07:12 AM ]

Let me respond to Tim's comments in particular.

1) I think we should look at these "extensions over and above" to see if we can change anything in JMS 2.0 to make it easier to use JMS on top of AMQP (which is the purpose of this issue).

2) Again, the suggestion is not that they drop their stuff for AMQP (or STOMP, for that matter).

3) AMQP remains as the most successful attempt of interoperability in MQ systems, including with platforms other than Java EE, and should be supported.

Comment by timlfox [ 19/May/11 09:02 AM ]

>> 1) I think we should look at these "extensions over and above" to see if we can change anything in JMS 2.0 to make it easier to use JMS on top of AMQP

If you wanted to make JMS really work over AMQP, you would need to make the changes in AMQP, not JMS 2.0. The correct place for recommending such changes would be the AMQP working group, not the JCP.

>> 3) AMQP remains as the most successful attempt of interoperability in MQ systems, including with platforms other than Java EE, and should be supported.

What's your measure of success? If you measure success by the number of messaging systems that really interoperate then STOMP is the most successful example of messaging interoperability so far.

Don't get me wrong, I think AMQP has it's place. The 0.9.1 spec is a good solid spec for implementing a message broker, the excellent RabbitMQ is a case in point. But AMQP is not rich enough to support JMS semantics, and AMQP 1.0 shows no sign of improving in that area (in fact AMQP 1.0 doesn't provide any broker semantics at all), so going down that road is likely to result in a dead-end.

Comment by fribeiro [ 19/May/11 09:31 AM ]

I was really referring to the fact that Microsoft is in the AMQP game, but I really don't think we should discuss the merits of the new protocol too much, but rather only find out if any experiences when implementing JMS on top of AMQP called for improvements to the API.

It has also been mentioned here that adding protocol metadata would be a good idea and perhaps a new separate "generic" issue should be created for it.

One more thing to discuss here seems to be whether the specification should define how to select the wire protocol in use, given that more libraries can should to support two or more protocols in the future, what do you think about that?

Comment by rdohna [ 20/May/11 03:18 AM ]

The improvement to JMS could be that we'd have to define profiles, so some messaging system can conform only to a defined subset of JMS... e.g. without support for stream messages.

I think the wire protocol should be kept completely out of JMS. If an implementation can handle more than one, the admin should have to configure it, probably for the queue (with useful defaults).

Comment by fribeiro [ 20/May/11 11:08 AM ]

The profile idea sounds good, perhaps you should open a separate ticket for it (you have my vote there!).

Regarding the wire protocol, I wouldn't like to be required to use the API of a specific vendor to specify it, maybe there should be a standard way to configure it in the connection factory, how about that?

Comment by rdohna [ 20/May/11 01:50 PM ]

Why would you want to configure something like this in your code? You may even want to deploy your software in different environments with different messaging providers and different wire protocols. I think this should be the job of the admin creating the destination, while the programmer should concentrate on other things... like the business code.

Comment by fribeiro [ 20/May/11 01:59 PM ]

That's probably the right thing, my bad, should be a configuration option in the provider, are the names/default values of such options out of the scope of the spec?

Comment by abien [ 18/Jun/11 12:47 AM ]

Could you add a concrete example, what is to change in JMS?

Comment by Nigel Deakin [ 05/Mar/12 12:20 PM ]

AMQP is a wire protocol, and I think there's a general consensus that JMS should remain as an API and shouldn't define a wire protocol.

However AMQP is clearly a prominent and successful standard and it's definitely within the scope of JMS to consider whether new JMS features would make it easier for vendors to implement JMS providers that use AMQP as a wire protocol.

I think what we need to take this issue forward is some concrete proposals as to what this might involve. Without specific proposals this will remain just an expression of desire.

So please take this as an invitation to make some proposals. Depending on the scale of changes proposed, these could be for JMS 2.0 or a later revision.

Tagging for review by the expert group.

Comment by fribeiro [ 10/May/13 12:50 AM ]

You may want to go ahead and close the issue.





[JMS_SPEC-7] Provide HTTP Binding Created: 17/May/11  Updated: 10/May/13

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

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

Tags: jms21-forreview-major
Participants: abien, bsnyder, clebertsuconic, fribeiro, John Harby, Nigel Deakin and rdohna

 Description   

If none is available from another organization, I think the JCP should provide (maybe in a separate JSR) a standard HTTP binding for JMS, given how often these technologies are used together.



 Comments   
Comment by bsnyder [ 18/May/11 03:51 PM ]

This is exactly what I meant with my comment in JMS_SPEC-5. Providing specifications for binding JMS to other various technologies would really help out users.

Comment by clebertsuconic [ 18/May/11 04:01 PM ]

Maybe a new message type? for this and spec-5?

Comment by fribeiro [ 18/May/11 04:15 PM ]

I like the idea of a new message type for HTTP but think it is complementary, not supplementary, to a standard mapping between HTTP and JMS.

Vendors have long used non-standard things like "HTTP-Content-Type", for example, that make it difficult to integrate with other systems.

Comment by rdohna [ 19/May/11 05:56 AM ]

I don't quite understand. HTTP is a synchronous protocoll, JMS is asynchronous. What is the use case to transport an HTTP request via JMS? Load balancing? Routing? Pipes-And-Filters? Any of the EAI patterns? Can't you do these things with plain vanilla EJBs, for example? And the programming model would be much simpler, wouldn't it?

Comment by fribeiro [ 19/May/11 08:11 AM ]

I've seen HTTP being properly used more than once to allow communication from platforms without JMS client libraries, for example, not to mention a HTTP request may need to be transformed to JMS as explained in my most recent comment in JMS-SPEC-9.

Comment by rdohna [ 19/May/11 09:08 AM ]

Did I get your scenario right: You have some client that can't directly produce messages for your JMS system. You provide it a generic adapter that converts any http request into a JMS message. The adapter replies to the client as soon as the message is sent. You use some message routing to get the request to some service. If there is any feedback from the service to the client, it's in a separate channel. The important thing to note is that almost all HTTP header fields could be required for the routing, while the body is simply the HTTP body, i.e. eventually even binary.

I'd prefer a direct feedback for the client, when the request is invalid. But you may have use cases where this is okay.

So I guess that the binding this issue requests is to standardise the mapping of the HTTP field names to the JMS headers/properties, right? I assume most fields would just map one to one, but e.g. the first line would have to be split into properties for the method (e.g. GET), the path (e.g. "/"), and the protocol version (e.g. "HTTP/1.1").

To cut a long story short, I think this is either a bridge between two different messaging solutions or just one specific application protocol. In both cases, I'd say that it should not be part of this spec.

Comment by fribeiro [ 19/May/11 09:40 AM ]

You got it right, and I can agree if doesn't necessarily fit in the JMS spec itself (which should perhaps focus only on the API), but, if not there, where do you think it should be standardized?

Comment by rdohna [ 20/May/11 01:10 AM ]

I have no idea other that what you've suggested: Another JSR.

But this issue should be closed, shouldn't it?

Comment by fribeiro [ 20/May/11 11:05 AM ]

I can't do it myself and also want to wait for Nigel's comments about this matter, he can probably help with the new JSR or point me to another venue for that standard.

Comment by abien [ 18/Jun/11 12:47 AM ]

+1 for a separate spec.

Comment by Nigel Deakin [ 02/Mar/12 04:45 PM ]

I think that this proposal is is essentially proposing that JMS defines some kind of HTTP binding (protocol, really) to a JMS provider. I can well imagine that this is a common requirement: I know at least two JMS providers that provide a HTTP protocol and I'm sure there are others.

I think there are a number of issues here:

1. Whether a standard HTTP protocol to JMS is required
2. If so, whether it belongs in JMS or in some other specification

Defining a standard HTTP protocol sounds, on the face of it, a good idea. It would be necessary to decide what JMS features could be made available using HTTP - some, like message order or transactions, would probably rely on the concept of there being some kind of client state maintained between requests.

Then there's the question of whether this is should be defined as part of JMS, as a separate JCP specification, or under the auspices of some other body.

As a general rule the JCP is "for developing standard technical specifications for Java technology", but defining a HTTP protocol for JMS is certainly not out of the question. Some would probably recommend that it be defined at OASIS, or even IETF. But if it needs to align strongly with the Java API then that might be enough justification to develop it as part of JMS.

We would need to consider what the compatibility requirements would be for the HTTP protocol? Would all JMS products be required to include a REST server that supported the protocol?

We would also need to consider where the HTTP protocol would sit the JMS architecture. Would the JMS server support the HTTP protocol or would we be defining a separate server that accepted HTTP requests and translated them to the native network protocol for the JMS server, perhaps by just translating them into JMS API calls?

My feeling is that we would never want to make it mandatory for a JMS provider to directly support the HTTP protocol, and that it should be possible to implement it as a separate component interfacing with the JMS provider using the standard JMS API (if it requires proprietary API then it isn't really a JMS binding). This suggests to me that this belongs in a separate JSR.

I'm also mindful that this would be a significant piece of work and there's not going to be time to deliver in the JMS 2.0 timescales in any case.

So my proposal is that we take the decision to not attempt to define a HTTP protocol for JMS 2.0. We can leave the issue open, but it is likely that a HTTP protocol would need to be delivered as a separate JSR.

Irrespective of this, there may be scope to enhance the existing JMS (Java) API to make it easier to deliver a HTTP binding. I think we already have one in JMS_SPEC-5, and there may be others).

Comment by John Harby [ 01/May/12 05:23 PM ]

I agree with Nigel that a thorough specification for this is probably not feasible for this release. We may want to consider a couple of items to add that would be basic common features of current REST/JMS implementations such as publishing use POST and consuming using DELETE or GET, etc. These could be specified for those who wish to support REST, not mandated for any JMS provider.

Comment by fribeiro [ 10/May/13 12:49 AM ]

You may want to go ahead and close the issue.

Comment by Nigel Deakin [ 10/May/13 10:38 AM ]

Comment noted - but I think this is an issue which deserves further discussion for a further version of JMS. So I'll leave this open. Tagging for review for 2.1.





[JMS_SPEC-5] Multi-Value Support in Properties Created: 17/May/11  Updated: 10/May/13

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

Type: Improvement Priority: Major
Reporter: fribeiro Assignee: Unassigned
Resolution: Unresolved Votes: 2
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

All JMS environments


Issue Links:
Duplicate
is duplicated by JMS_SPEC-13 New JMS header type: a Set Resolved
Tags: pd20-forreview-major
Participants: abien, bsnyder, clebertsuconic, fribeiro, John D. Ament, Nigel Deakin and rdohna

 Description   

It is desirable to be able to store multiple values with the same key in a JMS message, like in a HTTP request, for example.



 Comments   
Comment by clebertsuconic [ 17/May/11 01:23 PM ]

I don't think that would be a good idea.

you still have the body of the message to store anything you like (Object Message, TextMessage.. maybe we could extend other types of messages).

Properties are usually meant for filters and other controls. So this is most likely a won't fix IMO.

Allowing multi-value on properties would only complicate understanding of the spec and I believe should actually simplify it.

Comment by fribeiro [ 17/May/11 01:44 PM ]

I think it would make it easier to transform between technologies that support having multiple values with the same key (e.g HTTP) and JMS, and that is a good thing to have there, don't you agree?

Comment by clebertsuconic [ 17/May/11 02:34 PM ]

I'm not sure about others on the group, but I don't agree.

Message systems are not meant to be cache systems. In my experience using any messaging system as a database will create issues.

Besides you have the message body to store data.

You add something like this, how would you make a filter clause on a message?

Comment by fribeiro [ 17/May/11 02:53 PM ]

I think the use of JMS in ESBs like Progress Sonic ESB is a better use case. JMS is used there to transfer messages across services and, if any of them uses HTTP, you end up with a message that you can't transform to JMS without resorting to Property-1, Property-2, ...

SIP is another big protocol that can't be mapped for that reason, will think of others to mention here.

Comment by clebertsuconic [ 17/May/11 03:09 PM ]

You won't be able to use selection clauses if you add something like that.

IMO that's because you're using properties to add plain data.

I will let other to comment on this

Comment by John D. Ament [ 17/May/11 04:17 PM ]

I have mixed feelings about this. I don't believe that supporting multi-value properties will exclude the idea of having filters on them, as you should be able to do in/contains checks as well. However, they should still continue to be treated as metadata. One recent case I saw in richfaces included using properties to set sub-topics within the topics, and this would enable setting multiple sub-topics in that case.

Comment by fribeiro [ 17/May/11 04:25 PM ]

I also understand the impact and don't think it makes a good argument not to add multi-valued properties.

Comment by bsnyder [ 18/May/11 03:44 PM ]

This is a common issue for integration scenarios either with or without an ESB to translate a message from one protocol to another. Were I to solve this problem manually, I would develop some sort of reusable adapter class. This is not a core problem with the JMS spec, therefore, IMO the JMS spec should not be changed. I do, however, see value in providing some convenience classes to ease the task of message conversation. But this is a matter of implementation, not specification.

That being said, the topic of integration is something that is not addressed by Java EE as a whole and I'd like to see that change. There are many other languages and technologies out there that have a need to integrate with Java EE, and messaging is typically a common place people look when such integration needs arise.

Comment by clebertsuconic [ 18/May/11 04:03 PM ]

We could create a new message type, and leave properties alone. I'm concerned about moving semantics of the property methods. Currently they mean replace and there are application using that semantic.

If we add a new message type for cases like this, you would have scnearios like this covered.

Some providers have HTTPMessages as a common extension I think. I'm not 100% sure but I think I have seen things like this.

Comment by fribeiro [ 18/May/11 04:03 PM ]

I think it is a specification spec when no adapter class can convert multi-valued properties in other technologies commonly used with JMS in a standard way and resort to things like Property-1, Property-2, etc.., which are hard to use in message selection, for example, as Clebert pointed out.

Comment by fribeiro [ 18/May/11 04:09 PM ]

I think that adding a new message type or changing the current methods to return the first occurrence wouldn't quite cut it, and this is really a breaking change.

That said, I also think it would fit in a major release that updates a standard after 9 years.

Comment by rdohna [ 19/May/11 05:30 AM ]

Repeating keys in order to store multiple values is not very elegant, agreed. But maybe you also want to structure your keys, e.g. you want to store the start and end timestamp of two phases A and B. You'd then too have to resort to some naming convention like "A/start", "A/end", "B/start", and "B/end". Maybe you even would then like to filter your messages with a certain timestamp within phase A or phase B. There are lots of things that could be expressed more easily.

If went down that road, maybe we better represented the properties as an xml document. E.g.

<properties>
  <my-property>value-1</my-property>
  <my-property>value-2</my-property>
  <phase-A>
    <begin>...</begin>
    <end>...</end>
  </phase-A>
</properties>

This would allow us to have arbitrarily structured properties as well as to validate them against an xml schema. One could think of an XPath mapping to access these parameters with the "old" syntax, so you'd get value-2 with the key "my-property(2)" or the end of phase A with "phase-A/end".

Cool stuff, but I'd personally rather stick to the simple parameters that already exist. I generally find it good enough to put more complex things into the body. The example you describe seem a little bit esoteric in the context we use JMS for. I believe that complex filtering and routing at an ESB level often leads to difficult to maintain system. I prefer a controlling process manager instead. But maybe you can find a real use case that helps to better understand your idea.

Comment by fribeiro [ 19/May/11 08:08 AM ]

This issue really comes from experience in projects where messages previously transported over protocols that support multi-valued properties are sent to JMS endpoints - there is a mismatch there that pushes you to do the wrong thing.

It is usual in the integration space to take that data that doesn't actually belong to the information being transported shouldn't be mixed with it, but rather stored in message properties, which are often carried across several services before they are consumed.

Let me take an example from one of my projects:

1) A client sends an order to an ESB in a SOAP request with a username in a WS-Security header
2) A service extracts the username
3) A service transforms the body of the SOAP request to the format required by a JMS connector to an ERP. The username is transformed to a JMS message property
...

If it wasn't a string, but a list, I would end up resorting to the Property-1, Property-2, etc... idiom or worse.

Comment by rdohna [ 19/May/11 09:20 AM ]

Which HTTP header do you want to split into separate values. Typical headers like the Accept headers or cookies could be split, but they are strings, so you could simply leave them in one property.

Only for cookies I can think of a reasonable use case: That you want to route/select all messages with one cookie to one service instance. But wouldn't it be enough to route according to a substring?

Comment by fribeiro [ 19/May/11 09:36 AM ]

It is not only about HTTP, really, only used it as an example, but about any technologies that support multi-valued properties that may need to be transformed to JMS in an integration context.

Anyway, I think message selection is generally superior to substrings, and would like to use it instead.

Comment by rdohna [ 20/May/11 01:43 AM ]

I agree that using substrings for message selection is inferior to direct matching. But I'm still looking for a use case, where you need a message selector with a "contained in a list" semantics. Even if you are interested only in one of your cookies (or other tokens), wouldn't it be better to store them in dedicated properties like "user-id", "session-id", "country-id", etc.? Then they would be easy to select.

I try to stick to very simple message selectors, e.g. the version of the message format. For more complex things I use dedicated Destinations. If you don't want the sender (or adapter in your case) to know about these Destinations, you'll need something like an ESB with a Content Based Router. I think that this issue requests support for advanced message selection mechanisms. I see those mainly in the context of complex message routing, where simple message selection is not good enough.

That line is definitely difficult to draw, but I would like to have the JMS spec stay clear of that complexity. KISS and contain the complexity to where you can't avoid it.

Comment by fribeiro [ 20/May/11 11:42 AM ]

I think the real argument here is that it should be easy to map to/from as many technologies as possible given that JMS has been so widely used in integration solutions in the last years.

HTTP and SIP were the first examples that came to mind, but LDAP also uses multi-valued properties that can't be transformed to/from JMS messages today without the same Property-1, Property-2, etc idiom or something like it. Adding new message types wouldn't quite cut it.

I understand the impact, but don't you think it should fit in this next update?

Comment by rdohna [ 20/May/11 01:26 PM ]

If you just want to transport these meta fields, you can wrap them around the body. If you want to use it for message selection, I'd suggest to use something more feature complete for such a job: An ESB.

No, I don't think it should go into the spec... but maybe I just miss a realistic use case.

Comment by fribeiro [ 20/May/11 01:40 PM ]

I don't really think it is a good practice to store information usually in headers with the content of the body, do you?

I wouldn't mind extracting a few "realistic" use cases from work, glad to help.

Also, let me try to improve the argument first, though: "JMS is commonly used in integration solutions where one or more endpoints based on technologies like HTTP, SIP, LDAP and others can produce messages with multi-valued headers that can't be properly stored in Message objects" – how about that instead?

Comment by clebertsuconic [ 20/May/11 01:53 PM ]

Yes..Properties on JMS are meant for Meta-data, and information that is used for routing (filters.. etc). That's been a common sense on the discussions here.

For the real data, you have to place them at the body somehow. MapMessage maybe? (Maybe we could add Array support on MapMessage what would give what you want).

Comment by fribeiro [ 20/May/11 02:02 PM ]

If some protocol takes a multi-valued header as metadata, shouldn't it continue to be taken as so when transformed to JMS? I think so, and that is the support that we are currently missing.

Comment by clebertsuconic [ 20/May/11 02:12 PM ]

just add the data to the body of the message (or to one of the sub-messages that will encapsulate the body into some form of data, like MapMessage, etc).

as I said, using message properties to store data is a common anti-pattern on JMS.

Comment by fribeiro [ 20/May/11 02:29 PM ]

I guess we are saying the very same thing with different words: body is not for metadata, metadata in HTTP, SIP, LDAP transformed to JMS is still metadata, and those protocols support multi-valued properties that JMS doesn't – is the point clear?

Comment by clebertsuconic [ 20/May/11 06:50 PM ]

No, the properties on the HTTP are really data. Properties on JMS are not meant to store user data unless it's meant for routing, filters.. etc.

Comment by clebertsuconic [ 20/May/11 06:59 PM ]

Realistically nobody will change any of the methods on properties. You can't change semantics on the method calls as you have applications out there using the current API.

If you change the proposal to add array properties on MappedMessage you would get some attraction and people talking about it and considering it.

I don't think this would pass a group of people who implement JMS systems otherwise (Expert Group).

Comment by fribeiro [ 20/May/11 07:18 PM ]

I don't think the semantics of HTTP headers and JMS is any different, really, they are both used to carry metadata that doesn't belong in the body of the message.

Anyways, I see your point about how breaking of a change it would be to the API, but think it is a separate issue than opposing to multi-valued properties.

As long as the API goes, I think we could just add get<Type>PropertyValues / set<Type>PropertyValues, just like in the Servlet API. Instead of returning arrays, though, we could use lists, which would probably be used in the Servlet API as well if it was designed today – how about that?

Comment by rdohna [ 23/May/11 11:03 AM ]

I'd say that there can be an arbitrary number of nested metadata levels. Take an xml message: It contains an xml header, which itself is metadata, too. So it's normal to nest metadata, isn't it?

I think we should stick to the use cases that arise from the messaging domain itself, i.e. message selectors. If the only use case for multi-value properties is mapping other protocols, then I'd say that's not worth the added complexity.

Comment by clebertsuconic [ 23/May/11 12:18 PM ]

@rdohna +1

Comment by abien [ 18/Jun/11 12:47 AM ]

+1
HTTP-protocol interoperability (because of REST and JAX-RS), becomes more and more important. Although the two paradigms (HTTP / REST and JMS) do not follow the same idea, interoperability becomes crucial in the "clouds"

Comment by Nigel Deakin [ 02/Mar/12 02:54 PM ]

Tagging for review for the JMS 2.0 Public Draft

Comment by Nigel Deakin [ 07/Mar/12 03:54 PM ]

(Comment copied from JMS_SPEC-13, which has been closed as a duplicate of this)

As a JMS client I would like to populate a set in the message header and have it take part in selectors. The set would be generic somehow and the filter expressions available would "contains" and "not contains"

I cannot come up with a good looking API change to the Message interface to allow this set to be manipulated cleanly other than getStringHeaderSet, getDoubleHeaderSet etc. There must be a better way, perhaps via a builder pattern.

What I really would find useful is the selector:

"MyProperty contains 'AAA' or MyProperty contains 'BBB'"

Use Case:

Consider a multi national orgianisation with many offices (legal entities) and therefore many back office systems and they are all connected via messaging. A single "deal" can span many offices and many clients. When the deal has been agreed a notification would be sent with a "header set" containing all the offices involved in the deal with each back office subscribing to deals where it is a participant and therefore its identifier is in the header set.

Topics and wild carding do not work in this scenario as the number of participating offices is variable.

Comment by rdohna [ 19/Mar/12 03:17 PM ]

@Nigel: In your use-case, you could also use one boolean property for each office or client involved. "la-office" = true, "ny-office" = true, etc. The selector would also be quite simple (e.g., fast). You can always map any multi-value property to a set of single-value properties... but when you have sets, you also may want to have lists... and maps... and lists of sets of maps, etc. If you can't limit this to what's in http headers, you will always have to argue about the next step... I'd leave it out.

Comment by fribeiro [ 10/May/13 12:52 AM ]

You may want to go ahead and close the issue.





[JMS_SPEC-3] Fix JavaDocs to reflect missing NumberFormatException from API methods Created: 11/Apr/11  Updated: 20/Mar/13

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

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

N/A


Tags: jms21doc-minor
Participants: alanf760 and Nigel Deakin

 Description   

---------------------------
NumberFormatException tests
---------------------------

For javax.jms.MapMessage and javax.jms.StreamMessage the JavaDoc's need to be updated for the string to numeric conversions. The String to numeric conversions must throw a
java.lang.NumberFormatException if the numerics valueOf() method does not accept the the String value as a valid representation.

Tests for (NumberFormatException) which is not listed in JavaDoc for the getXXX() methods. Test in question is: MapMessageConversionQTestsInvFormatString. The
(NumberFormatException) is mentioned in spec but missing in JavaDoc.

The JavaDoc's for the following methods below of class javax.jms.MapMessage and class javax.jms.StreamMessage need to be modified to add the NumberFormatException.

getBoolean, getByte, getShort, getInt, getLong, getFloat, getDouble, etc



 Comments   
Comment by Nigel Deakin [ 11/Apr/11 06:44 AM ]

A big thank you to Alan for logging our first issue!

Comment by Nigel Deakin [ 28/Feb/12 12:14 PM ]

The JMS 1.1 spec, section 3.11.3 "Conversions provided by StreamMessage and MapMessage" states:

Both StreamMessage and MapMessage support the following conversion table. The marked cases must be supported. The unmarked cases must throw a JMS MessageFormatException. The String to numeric conversions must throw a java.lang.NumberFormatException if the numeric’s valueOf() method does not accept the String value as a valid representation.

This means that the methods this return a numeric: getShort, getLong, getDouble, getInt must throw a java.lang.NumberFormatException in the case described. This seems clear.

However I'm not sure about the methods which don't return a numeric, such as getBoolean. getByte and getBytes. Where does it say that these must throw a java.lang.NumberFormatException?

Tagging for review for the Public Draft.

Comment by Nigel Deakin [ 20/Mar/13 12:27 PM ]

This didn't make it into JMS 2.0 and so is carried forward to JMS 2.1.





[JMS_SPEC-2] Fix JavaDocs to reflect missing IllegalStateException from API methods Created: 11/Apr/11  Updated: 20/Mar/13

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

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

N/A


Tags: jms21doc-minor
Participants: alanf760 and Nigel Deakin

 Description   

IllegalStateException tests

The JavaDocs for the following methods below need to be updated to reflect that IllegalStateException can be thrown. In particular IllegalStateException is being thrown in the case of these methods being called on closed connection objects. There could be more methods than those listed below.

    javax.jms.QueueSession.commit}}  
    javax.jms.QueueSession.getTransacted  
    javax.jms.QueueSession.rollback 
    javax.jms.QueueSession.recover
    javax.jms.QueueConnection.getClientID
    javax.jms.QueueConnection.getMetaDataTest
    javax.jms.QueueConnection.createQueueSession
    javax.jms.QueueConnection.start
    javax.jms.QueueSession.createBrowser(*)
    javax.jms.QueueSession.createQueue
    javax.jms.QueueSession.createSender()
    javax.jms.QueueSession.createTemporaryQueue()
    javax.jms.QueueSession.createMessage()
    javax.jms.QueueSession.createBytesMessage()
    javax.jms.QueueSession.createMapMessage()
    javax.jms.QueueSession.createObjectMessage(*)
    javax.jms.QueueSession.createStreamMessage()
    javax.jms.QueueSession.createTextMessage(*)
    javax.jms.QueueSession.createStreamMessage()
    javax.jms.QueueReceiver.getMessageSelector()
    javax.jms.QueueReceiver.receive(*)
    javax.jms.QueueReceiver.receiveTimeout()
    javax.jms.QueueReceiver.receiveNoWait()
    javax.jms.QueueReceiver.getQueue()
    javax.jms.QueueSender.getDeliveryMode()
    javax.jms.QueueSender.getDisabledMessageID()
    javax.jms.QueueSender.getDisabledMessageTimeStamp()
    javax.jms.QueueSender.getPriority()
    javax.jms.QueueSender.getTimeToLive()
    javax.jms.QueueSender.setDeliveryMode()
    javax.jms.QueueSender.setDisabledMessageID()
    javax.jms.QueueSender.setDisabledMessageTimeStamp()
    javax.jms.QueueSender.setPriority()
    javax.jms.QueueSender.setTimeToLive()
    javax.jms.QueueSender.getQueue()
    javax.jms.QueueSender.send(*)
    javax.jms.TopicSession.commit  
    javax.jms.TopicSession.rollback 
    javax.jms.TopicSession.recover
    javax.jms.TopicSession.createTopic
    javax.jms.TopicSession.createSubscriber(*)
    javax.jms.TopicSession.createDurableSubscriber(*)
    javax.jms.TopicSession.createPublisher()
    javax.jms.TopicSession.createTemporaryTopic()
    javax.jms.TopicSession.unsubscribe()
    javax.jms.TopicSession.createMessage
    javax.jms.TopicSession.createBytesMessage
    javax.jms.TopicSession.createMapMessage
    javax.jms.TopicSession.createObjectMessage
    javax.jms.TopicSession.createStreamMessage
    javax.jms.TopicSession.createTextMessage
    javax.jms.TopicSession.getTransacted
    javax.jms.TopicSubscriber.getMessageSelector
    javax.jms.TopicSubscriber.receive(*)
    javax.jms.TopicSubscriber.receiveNoWait()
    javax.jms.TopicSubscriber.getNoLocal()
    javax.jms.TopicSubscriber.getTopic()
    javax.jms.TopicConnection.getClientID
    javax.jms.TopicConnection.getMetaDataTest
    javax.jms.TopicConnection.start
    javax.jms.TopicConnection.createTopicSession
    javax.jms.TopicPublisher.getDeliveryMode()
    javax.jms.TopicPublisher.getDisabledMessageID()
    javax.jms.TopicPublisher.getDisabledMessageTimeStamp()
    javax.jms.TopicPublisher.getPriority()
    javax.jms.TopicPublisher.getTimeToLive()
    javax.jms.TopicPublisher.setDeliveryMode()
    javax.jms.TopicPublisher.setDisabledMessageID()
    javax.jms.TopicPublisher.setDisabledMessageTimeStamp()
    javax.jms.TopicPublisher.setPriority()
    javax.jms.TopicPublisher.setTimeToLive()
    javax.jms.TopicPublisher.getTopic()
    javax.jms.TopicPublisher.publish(*)

Tests for IllegalStateException

The JavaDocs should be updated for all of the above method calls to specify that an IllegalStateException can be thrown on closed connection objects. Currently it doesn't. Only the JMS spec specifies that IllegalStateException must be thrown. The JavaDoc should be in sync with the spec and should mention it as well.

The JMS spec references for this is in the following sections:

  • 4.3.5 Closing a Connection
  • 4.4.1 Closing a Session
  • 4.11 Method Inheritance across Messaging Domains
  • Table 4-1 Methods That Must Throw an IllegalStateException
  • 7.3 Standard Exceptions
  • 11.2.21 JMS Source Java API documentation Clarifications
  • Table 11-2 Domain Dependent Interfaces

The CTS JMS test directories which are testing for IllegalStateException to be thrown on closed QueueConnection, closed QueueReciever, closed QueueSender, etc. objects are listed below:

    jms/ee/all/closedQueueConnection
    jms/ee/all/closedQueueReceiver
    jms/ee/all/closedQueueSender
    jms/ee/all/closedQueueSession
    jms/ee/all/closedTopicConnection
    jms/ee/all/closedpublisher
    jms/ee/all/closedsubscriber
    jms/ee/all/closedtopicsessiontests


 Comments   
Comment by Nigel Deakin [ 15/Apr/11 02:31 AM ]

Added formatting to description.

Comment by Nigel Deakin [ 28/Feb/12 11:56 AM ]

In the JMS 1.1 spec, section 4.3.5 "Closing a Connection" states that

Once a connection has been closed, an attempt to use it or its sessions or their message consumers and producers must throw an IllegalStateException (calls to the close method of these objects must be ignored).

In addition, JMS 1.1 section 4.4.1 "Closing a Session" states that

Once a session has been closed, an attempt to use it or its message consumers
and producers must throw an IllegalStateException (calls to the close method of
these objects must be ignored). It is valid to continue to use message objects
created or received via the session, with the exception of a received message’s
acknowledge method.

(The corresponding sections in the JMS 2.0 spec are 6.1.8. "Closing a connection" and 6.2.16. "Closing a session")

Furthermore, JMS 1.1 section 11.2.21 "JMS Source Java API documentation Clarifications" states:

The IllegalStateException has been noted as a required exception for several
more error conditions. they are acknowledging a message received from a
closed session; attempting to call the recover method of a transacted session;
attempting to call any method of a closed connection, session, consumer or
producer (with the exception of the close method itself);

The text about "attempting to call any method on a closed consumer or producer" causing an IllegalStateException doesn't seem to have made it into the body of the JMS 1.1 spec, and so at the time of writing there is no mention in the JMS 2.0 spec. This needs to be corrected.

In addition, the javadoc for all methods except close on a connection, session, producer or consumer should be updated to mention that an IllegalStateException may be thrown if the connection, session, consumer or producer is closed.

Comment by Nigel Deakin [ 20/Mar/13 12:28 PM ]

This didn't make it into JMS 2.0 and so is carried forward to JMS 2.1.





Generated at Thu Apr 17 01:55:06 UTC 2014 using JIRA 4.0.2#472.