[cdi-dev] JMS 2.1: Proposal to allow any CDI managed bean in a Java EE application to listen for JMS messages

Nigel Deakin nigel.deakin at oracle.com
Wed Aug 26 08:03:10 EDT 2015


On 26/08/2015 12:10, John D. Ament wrote:
>
>
> On Wed, Aug 26, 2015 at 6:53 AM Nigel Deakin <nigel.deakin at oracle.com <mailto:nigel.deakin at oracle.com>> wrote:
>
>     On 26/08/2015 10:51, arjan tijms wrote:
>      > On Wed, Aug 26, 2015 at 11:09 AM, Romain Manni-Bucau
>      > <rmannibucau at gmail.com <mailto:rmannibucau at gmail.com>> wrote:
>      >> Agree for provided scope but JMS + short time scopes will not match well in
>      >> practise so i would worry more about not "default" scopes which can miss
>      >> these events.
>      >
>      > Short lived scopes like @RequestScoped may not be the best match indeed.
>      >
>      > Additionally, @RequestScoped is kinda assumed to be an "@ThreadScoped"
>      > thing, e.g. there's the expectation that only the current thread will
>      > access it. If the JMS provider will asynchronously call a method on
>      > the bean instance from another thread, then this breaks this
>      > assumption.
>
>     That's an interesting point. Is there anything in the CDI spec which would forbid the use of a @RequestScoped JMS
>     listener bean from another thread?
>
>
> The CDI spec still mandates that a request scope is started for delivery to MDBs.  See
> http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#request_context
>
> The JMS provider would be responsible for retrieving a contextual reference to the bean and then invoking the method.
> The container should still be responsible for starting the request context (If I read this correctly).

In the case of a "JMS listener bean" with @RequestScoped (or any scope, really) then the JMS consumer (the thread which 
receives a message from the JMS server and invokes the listener) is associated with the actual bean instance. We should 
think of it as an extension to that instance. The bean instance would be created when the request (e.g. the HTTP 
request) started, and will be destroyed when the request ends. Likewise the JMS consumer is created when the request 
starts and will be destroyed when the request ends. The consumer thread that is calling the listener doesn't "retrieve a 
contextual reference to the bean" since it is already associated with a specific instance.

However once you're inside the callback method then this request scope (which relates to a different thread) is not 
available. As John suggests, we should probably define that a request scope is started when the callback method is 
invoked, and ended when the callback method returns. The listener method itself could inject @RequestScoped objects 
(including JMSContexts, which are request-scoped if there were no transaction), where the request scope used is the one 
associated with this particular callback.

> Likewise, we could say that a @TransactionScoped bean also applies here, since a JTA transaction should have been
> started by the RA.

If the listener bean were @TransactionScoped then the JTA transaction would (by definition) have been started before the 
bean was created, and before the consumer was created. That would be separate from any transaction started by the 
resource adapter (which would be in a different thread).

Once again, the bean instance being used would be the one associated with the consumer, and which lives for as long as 
the first (application's) transaction.

However the callback method would be called in the context of the second transaction (since that it's in the same thread 
as that transaction). The listener method itself could inject @TransactionScoped objects (including JMSContexts), where 
the transaction used would be the one started and ended by the JMS provider/RA.

Nigel


More information about the cdi-dev mailing list