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

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

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

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

 Description   

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

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

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






[JMS_SPEC-156] JMS does not adequately define the behaviour of getAcknowledgeMode, getTransacted and getSessionMode in Java EE Created: 01/Sep/14  Updated: 25/Mar/15

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

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

Tags: jms20-errata, jms21-forreview-major

 Description   

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

What the spec currently says about these methods

The javadoc for Session#getAcknowledgeMode state that this method

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

The javadoc for Session#getTransacted state that this method

Indicates whether the session is in transacted mode.

The javadoc for JMSContext#getSessionMode states that this method

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

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

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

Why this is ambiguous

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Proposed clarification

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

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


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

Description updated with a new proposal.

Comment by Nigel Deakin [ 25/Mar/15 ]

Deferred until JMS 2.1





[JMS_SPEC-154] Standardize Abstractions for Common Message Processing Patterns Created: 08/Jul/14  Updated: 06/Oct/14

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

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

Tags: jms21-forreview-major

 Description   

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

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

Batch processing messages is something we've already discussed:

@ApplicationScoped @Lock(WRITE)
public class MyListenerComponent {

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

}

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

@ApplicationScoped @Lock(WRITE)
public class MyListenerComponent {

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

}

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

@ApplicationScoped @MaxConcurrency(10)
public class MyListenerComponent {

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

}

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

@ApplicationScoped @MaxConcurrency(10)
public class MyListenerComponent {

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

}

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

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






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

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

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

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

 Description   

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



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

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





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

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

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

Tags: jms21-forreview-major

 Description   

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

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



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

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

Comment by Nigel Deakin [ 04/Feb/14 ]

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





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

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

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

Tags: jms21-forreview-major

 Description   

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

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



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

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





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

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

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

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

 Description   

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

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

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

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

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



 Comments   
Comment by lprimak [ 19/Nov/13 ]

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

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

This is the simplest way to implement this pattern.

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





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

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

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

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

 Description   

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

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

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

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

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

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

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

}
@Pooled
public class MyListenerComponent {

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

}

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

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

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

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



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

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

Comment by clebertsuconic [ 29/Aug/13 ]

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

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

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

Comment by reza_rahman [ 29/Aug/13 ]

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

Comment by reza_rahman [ 29/Aug/13 ]

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

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

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

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

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

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

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

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

@Inject
private JMSServerContext serverContext;

...

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

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

Comment by reza_rahman [ 02/Sep/13 ]

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

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

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

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

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

Comment by Nigel Deakin [ 02/Sep/13 ]

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

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

There are a number of significant ideas introduced here.

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

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

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

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

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

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

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

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

@Inject MyListenerBean myBean;

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

3. Annotations on the JMS listener bean class and methods

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

Relationship to JCA

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

Comment by reza_rahman [ 02/Sep/13 ]

Thanks indeed for correcting the formatting - my bad .

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

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

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

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

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

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

Comment by reza_rahman [ 02/Sep/13 ]

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

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

Comment by Nigel Deakin [ 03/Sep/13 ]

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

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

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

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

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

Comment by Bruno Borges [ 03/Oct/13 ]

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

Comment by clebertsuconic [ 03/Oct/13 ]

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

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

Comment by reza_rahman [ 03/Oct/13 ]

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

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

Comment by clebertsuconic [ 03/Oct/13 ]

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

We need something more programmers friendly like this IMHO.





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

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

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

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

 Description   

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

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

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

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



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

Historical background behind the current restrictions

The current restrictions precede JMS 2.0 and were defined in EJB 3.1 (and possible earlier versions). In EJB 3.1, section 13.3.5 "Use of JMS APIs in transactions" states that “because the container manages the transactional enlistment of JMS sessions on behalf of a bean, the parameters of the createSession... methods are ignored."

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

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

Rationale behind the current restrictions

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

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

Additional restriction when using an injected JMSContext

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

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

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





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

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

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

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

 Description   

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

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

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

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

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

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

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






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

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

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

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

 Description   

Case 1

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

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

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

Here's a simple example:

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

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

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

There appear to be three possibilities:

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

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

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

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

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

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

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

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

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

Case 2

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

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

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

Here's a simple example:

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

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

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

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

      context.close();
   }
}

There appear to be four possibilities:

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


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

Equivalently, what happens in EJB when this occurs?

Comment by Nigel Deakin [ 18/Jun/13 ]

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

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

Comment by Nigel Deakin [ 18/Jun/13 ]

Added some code examples to the initial issue description

Comment by Nigel Deakin [ 18/Jun/13 ]

Updated summary field.

Comment by Nigel Deakin [ 22/Aug/13 ]

The same issues arise for container-managed transactions.

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

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





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

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

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

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

 Description   

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

Possible behaviour that might be required is:

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

No doubt there are other possibilities.

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



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

Comment from colleague TB:

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

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

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

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





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

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

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

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

 Description   

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

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

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

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

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

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

Some down sides:

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



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

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

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

Comment by dblevins [ 26/Apr/15 ]

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

Before

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

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

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

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

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

            final ObjectMessage objectMessage = (ObjectMessage) message;

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

            doSomethingUseful(buildTask);

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

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

After

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

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

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

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

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

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

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

}

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

Comment by rdohna [ 01/May/15 ]

David,

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

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

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

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

Comment by Nigel Deakin [ 28/Jul/15 ]

I have now published some proposals to address this issue.

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

Comments are invited.





[JMS_SPEC-100] Allow Java EE components other than MDBs to consume messages asynchronously Created: 19/Sep/12  Updated: 02/Sep/13

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

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

Issue Links:
Dependency
depends on EJB_SPEC-60 Modernize Connector/MDB Resolved
Related
is related to JMS_SPEC-134 Declarative Annotation Based JMS List... Open
Tags: jms21-forreview-major

 Description   

This proposal suggests the addition of the following annotation: @MessageSelector, to be used on a @MessageDriven bean consumimng a Queue or as Topic Subscriber.

Example:

package sample;

// imports

@MessageDriven(mappedName = "jms/queue0")
public class MessageSelectorBean implements MessageListener {

  @Resource(lookup = "jms/connectionFactory")
  ConnectionFactory connectionFactory;

  @MessageSelector("(StockSector = 'Technology')")
  public void onMessage(Message message) {
    try (JMSContext context = connectionFactory.createContext()) {
      String request = ((TextMessage)message).getText();
      Destination replyDestination = message.getJMSReplyTo();
      TextMessage replyMessage = context.createTextMessage("Reply to: "+request);
      context.createProducer().send(replyDestination, replyMessage);
   } catch (JMSException ex) {
     // log an error here
   }
  }
}


 Comments   
Comment by Bruno Borges [ 19/Sep/12 ]

Same code o Gist (formatted)

https://gist.github.com/3750788

Comment by Bruno Borges [ 22/Apr/13 ]

Can someone close this issue as invalid? JMS 2 just got final, so I don't see this going forward.

Comment by John D. Ament [ 22/Apr/13 ]

Since we now have an updated RA spec, we can make something like this happen. I'd strongly recommend leaving this open, maybe something we can tackle in JMS 2.1.

Comment by Nigel Deakin [ 22/Apr/13 ]

I agree improvements to MDBs (and message listeners in Java SE as well) should be on the agenda for JMS 2.1, so I'll leave this open.

Comment by Bruno Borges [ 22/Apr/13 ]

Extension of this proposal (which I forgot to add when I submitted the issue):

  • allow MDBs to have N "onMessage" methods, annotated with @MessageSelector

Questions to be analyzed:
1) should container create an instance of MDB per "message selector"?
2) should fields be thread-safe?
3) how would this affect concurrency?
4) how should pool size be defined? Per MDB (as it is now), or per message selector?

PS: great to see interest in this

Comment by John D. Ament [ 22/Apr/13 ]

Note: the core MDB work is contained in the EJB spec. JMS does not define an MDB. JMS does define the endpoint interface (potentially the annotations that work with that interface as well).

Comment by Nigel Deakin [ 22/Apr/13 ]

Note that you can already (Java EE 6) specify the message selector of a MDB using annotations (the activation property messageSelector), though this can't be checked by the compiler.

From Bruno's last comment it sounds he is making a more general request, somewhat similar to JMS_SPEC-116 (logged by genomeprjct), of breaking the link between JMS MDBs and the javax.jms.MessageListener interface.

Perhaps we should combine this issue with that one.

Comment by John D. Ament [ 25/Apr/13 ]

I think we generally need an approach for RA handling and how the MDBs will work with that RA. Based on what I'm seeing in the specs, it seems like it's essentially luck that the current JMS MDB even works somewhat consistently across application servers; it's just not clear to me yet that we can move forward with a change like this ourselves. In JMS 2 some standard configuration was added, but this was done by pushing the EJB EG to make the changes. When the JMS spec voted on an RA, it was generally voted down (note: my vote was to make it optional, but if an implementation did decide to provide one it needed to work with a specific interface for app servers).

My vote is to generally start to formulate what the next version of the JMS MDB looks like (based on the new RA structure provided by David and the platform spec); but do we need to officially file for a JMS 2.1 JSR?

Comment by Bruno Borges [ 25/Apr/13 ]

Allowing any method to be defined as a consumer could lead to a new approach at integrating message consumption and business methods. For example, such code could be possible:

package sample;

// imports

@Stateless
public class MySessionBean {

  @Resource(mappedName = "jms/queue0")
  private Queue queue0;

  @Inject
  private JMSContext jmsContext;

  public String retrieveUserPassword(String userEmail) {
    ... // business logic, connection to EntityManager, etc...
    return foundPassword;
  }

  @DestinationConsumer(mappedName = "jms/queue0")
  @MessageSelector("(LostPasswordBy = 'email')")
  public void sendEmailPassword(Message message) {
      String email = ((TextMessage)message).getText();
      String password = retrieveUserPassword(email);
      ... // call mailSession and send an email with recovered password
  }

  // method called by managedbean on UI, etc...
  public void requestLostPassword(String email) {
     TextMessage message = context.createTextMessage(email);
     message..setStringProperty("LostPasswordBy", "email");
     jmsContext.createProducer().send(queue0, message);
  }
}

Comments?

Comment by Nigel Deakin [ 25/Apr/13 ]

When this issue was first logged, the summary was "Support for annotation @MessageSelector on message driven beans".

I think we should change this to make it more general. Bruno's not just asking about message selectors (which you can already define using an annotation). It's about making it possible for Java EE components other than MDBs to consume messages asynchronously, and to replace the existing requirement to implement MessageListener with the ability to annotate individual methods. (I don't think we need to worry too much about the actual annotations just yet, the point is made.)

I'll change the description to "Allow Java EE components other than MDBs to consume messages asynchronously".

Just like JMS MDBs are currently defined in the EJB spec, this would probably end up being defined in the EJB spec. But the JMS expert group and community should "own" the issue and decide what it wants.

Note that we're currently (April 2013) in an interregnum between two versions of JMS currently: this issue may well be one which we want to specifically mention on the JSR for the next version.

Comment by Bruno Borges [ 01/May/13 ]

Perhaps we should consider two things:

  1. Extend the use of @MessageSelector for MDBs as is today, letting a MDB to have N-annotated methods with @MessageSelector
    I think this proposal can be worked for JMS 2.1 without the need for further details and changes over the spec, and it does not involve EJB spec.
  2. Let any component/method connect to a Destination, using Message Selectors, Activation Configs, etc.

This should be considered, IMO, as a proposal for EJB 3.next or EJB 4.0. This change would fit better with what David Blevins proposed on EJB_SPEC-60 and with what has already been discussed with JMS_SPEC-116

Good example of usecase that could benefit of this proposal is described at GLASSFISH-20371





[JMS_SPEC-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
Labels: None
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

 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 ]

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 ]

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 ]

Tagged for review for JMS 2.1

Comment by Nigel Deakin [ 22/Mar/13 ]

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





[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
Labels: None
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

 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 ]

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 ]

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 ]

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 ]

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 ]

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 ]

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

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-25] Standardise the interface between a JMS provider and a Java EE application server Created: 06/Jul/11  Updated: 07/Feb/13

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

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

Tags: jms21-forreview-major

 Description   

We need to standardise the interface between a JMS provider and a Java EE application server, to allow portability of JMS providers between application servers.

The frontrunner here is to mandate the provision of a JCA resource adapter, though an alternative may be to extend and make mandatory the existing Chapter 8 API.



 Comments   
Comment by John D. Ament [ 06/Jul/11 ]

If we setup CDI integration, +1 maybe to standardize on the CDI extension approach?

Comment by Nigel Deakin [ 21/Jul/11 ]

Following discussions in the expert group mailing list the expert group has agreed in principle to make it mandatory for a JMS vendor to provide a JCA resource adapter to allow their JMS client to be used from any Java EE application server.

Comment by Nigel Deakin [ 07/Feb/13 ]

Following a further discussion , the JSR 343 expert group has changed its view and decided that it should not be mandatory for a JMS vendor to provide a JCA resource adapter.

Comment by Nigel Deakin [ 07/Feb/13 ]

Given that the EG has rejected making it mandatory to provide a resource adapter, should it be mandatory to implement some other API for application server integration, such the optional chapter "JMS application server facilities" in the JMS 2.0 spec? Or is it OK for vendors to continue to develop JMS implementations that can't used in a Java EE application?

Tagging for further review in JMS 2.1.





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

Tags: jms21-forreview-major

 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 ]

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 ]

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

Comment by fribeiro [ 18/May/11 ]

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 ]

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 ]

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 ]

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 ]

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 ]

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 ]

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 ]

+1 for a separate spec.

Comment by Nigel Deakin [ 02/Mar/12 ]

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 ]

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 ]

You may want to go ahead and close the issue.

Comment by Nigel Deakin [ 10/May/13 ]

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.





Generated at Sun Feb 26 11:42:17 UTC 2017 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.