users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: (JMS_SPEC-70) Define annotations for injecting MessagingContext objects

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Fri, 10 Feb 2012 13:00:10 +0000

On 10/02/2012 04:10, Reza Rahman wrote:
> This looks pretty good I think.

Thanks for the feedback.

> Personally, I would have preferred the greater granularity of the transaction scope. However, I'll also acknowledge that
> it can be difficult to comprehend and most probably overkill.

As you know, transaction scope isn't one of the CDI 1.0 built-in scoped and I don't think it is defined anywhere. I'm
not sure whether JMS should be taking the initiative to define transaction scope or whether it is something we should be
asking the CDI or Java EE EGs to define.

One thing that we would need to bear in mind is that it is valid to use JMS (in a Java EE web or EJB container) when
there isn't a current JTA transaction, so transaction scope couldn't (I presume) be used then,

I'm happy to continue a discussion about scopes.

> I do hope the request scope has a sensible definition in
> Java SE/non-web contexts.

This would be CDI request scope, as defined in CDI 1.0, which CDI only defines in terms of Java EE. I'm not sure how
this scope behaves in Java SE. My current proposal is for Java EE only (i.e. supporting injection is only required in
Java EE) since we know that both CDI and JNDI resources are available in Java EE. I'd like to make it available to Java
SE but I'm not sure exactly what the spec actually needs to say. Perhaps we can add that later.

It may be worth pasting what CDI says about request scope:

6.7.1. Request context lifecycle

The request context is provided by a built-in context object for the built-in scope type @RequestScoped. The request
scope is active:
• during the service() method of any servlet in the web application, during the doFilter() method of any servlet filter
and when the container calls any ServletRequestListener or AsyncListener,
• during any Java EE web service invocation,
• during any remote method invocation of any EJB, during any asynchronous method invocation of any EJB, during any
call to an EJB timeout method and during message delivery to any EJB message-driven bean, and
• during any message delivery to a MessageListener for a JMS topic or queue obtained from the Java EE component
environment.

The request context is destroyed:
• at the end of the servlet request, after the service() method, all doFilter() methods, and all requestDestroyed()
and onComplete() notifications return,
• after the web service invocation completes,
• after the EJB remote method invocation, asynchronous method invocation, timeout or message delivery completes, or
• after the message delivery to the MessageListener completes.

> Similarly, I personally like the hierarchical model of the JMS 1.x API slightly better and
> feel it can be fit fairly nicely into a DI based solution.

I too like the existing JMS 1.1 API, but I'm surprised to hear you suggest that it can "fit fairly nicely into a DI
based solution". As you know, we did spend quite a lot of time last year trying to devise such a solution and my feeling
was that we all came to the conclusion that there was not a simple way to adequately represent the relationship between
injected objects.

> However, I'll acknowldge that the DI approach would not
> necessarily be very simple

Yes, I think that's the important thing here. There's no point in offering an approach which is more complicated than
using normal variables and plain old Java factory methods.

> and most folks don't seem to have issues with a flatter "Spring JMS template" style messaging API.

Indeed, though I am aware that we are really just moving the complexity around (we are replacing a set of small,
single-purpose objects with a essentially a single multi-purpose object with lots of methods).

> I suggest socializing the API with the larger community soon. I can certainly help if needed.

Yes please! I think the early draft is the perfect milestone to do this. In fact, that's really all the early draft is:
a formal invitation for comments at an early stage. Now we have a draft API and spec we have something for the community
to look at. Note that the JCP process expressly encourages the early draft to be published at a stage when there still
are unresolved issues and unfinished topics.

I have a few caveats of my own about the simplified API itself (second thoughts on various details) which I'll circulate
separately. We don't necessary have to resolve every issue before the early draft: in fact we could circulate a list of
open questions to accompany the draft and ask the community for comments.

I propose to add this proposal on injection to the early draft, if there are no objections. Even though I am trying to
freeze its content, I think the addition of injection makes the simplified API proposal more complete.

I'll let you know when I've done that.

Nigel


>
> On 2/8/2012 10:27 AM, Nigel Deakin wrote:
>> I created this new issue a couple of days ago to allow us to track the injection of MessagingContext objects
>> separately from the rest of the simplified API:
>> http://java.net/jira/browse/JMS_SPEC-70
>>
>> Currently, the simplified API is in the Early Draft but the injection of MessagingContext objects is not. However if
>> there is general agreement on what is proposed below I propose to include this in the Early Draft as well (since
>> supporting this was the main reason for defining the simplified API):
>>
>> Any comments? (If you don't understand what I am proposing, please let me know either directly or via the list)
>>
>> If it's hard to read the text below, the same content may be found in the JIRA issue.
>>
>> I described the requirement as follows:
>>
>> --------------------------------------------------------
>> The simplified API (JMS_SPEC-64) defines a single object, javax.jms.MessagingContext, which provides methods for
>> sending and receiving messages.
>>
>> It is proposed that the JMS API define some standard annotations that can be used to inject MessagingContext objects
>> into application code.
>>
>> * The injection point should allow the application define the two parameters needed to create a MessagingContext: JNDI
>> name (of the connection factory) and sessionMode. Both should be optional with suitable defaults.
>>
>> * The implementation should ideally be implemented using CDI and have behaviour consistent with it. However this is
>> not essential.
>>
>> * It must be possible to use injection in Java EE applications. It is desirable but not essential to be able to use
>> injection in Java SE applications.
>>
>> * Injected MessagingContexts must have an appropriate scope and must be automatically closed when they fall out of scope.
>> --------------------------------------------------------
>>
>> I've now drafted a new section for the JMS spec that defines how users will inject MessagingContext objects. I've
>> added this text, and the proposed new annotation interfaces, to the JIRA issue:
>> http://java.net/jira/browse/JMS_SPEC-70
>>
>> I've pasted the same text below. (To see the actual annotation definitions, see the JIRA issue).
>>
>> I'd like to thank Pete Muir, CDI spec lead, helping me define a mechanism for injecting MessagingContext objects which
>> * Allow JNDI name and sessionMode to be specified in the injection point
>> * Ensures injected objects are closed at the end of the request
>> * Is consistent with CDI style
>> * Is capable of being implemented
>>
>> I have a working prototype which implements this, based on a proposal from Pete, and which I'm happy to share.
>>
>> I'd also like to acknowledge the help I was given earlier by Reza (Rahman) and John (Ament).
>>
>> --------------------------------------------------------
>>
>> This section relates to application classes which run in the Java EE web, EJB or application client containers and
>> which support injection. Section EE.5 of the Java EE specification lists the application classes that support injection.
>>
>> Applications may declare a field of type javax.jms.MessagingContext and annotate it with the javax.inject.Inject
>> annotation:
>>
>> @Inject
>> private MessagingContext context;
>>
>> The container will inject a MessagingContext. It will have request scope and will be automatically closed when the
>> request ends. However, unlike a normal CDI request-scoped object, a separate MessagingContext instance will be
>> injected for every injection point.
>>
>> The annotation javax.jms.JMSConnectionFactory may be used to specify the JNDI lookup name of the ConnectionFactory
>> used to create the messaging context. For example:
>>
>> @Inject
>> @JMSConnectionFactory("jms/connectionFactory")
>> private MessagingContext context;
>>
>> If no lookup name is specified or the JMSConnectionFactory annotation is omitted then the platform default JMS
>> connection factory will be used.
>>
>> The annotation javax.jms.JMSSessionMode may be used to specify the session mode of the messaging context:
>>
>> @Inject
>> @JMSConnectionFactory("jms/connectionFactory")
>> @JMSSessionMode(MessagingContext.AUTO_ACKNOWLEDGE)
>> private MessagingContext context;
>>
>> The meaning and possible values of session mode are the same as for the ConnectionFactory method
>> createMessagingContext(int sessionMode):
>>
>> * In the Java EE application client container, session mode may be set to any of MessagingContext.SESSION_TRANSACTED,
>> MessagingContext.CLIENT_ACKNOWLEDGE, MessagingContext.AUTO_ACKNOWLEDGE or MessagingContext.DUPS_OK_ACKNOWLEDGE. If no
>> session mode is specified or the JMSSessionMode annotation is omitted a session mode of
>> MessagingContext.AUTO_ACKNOWLEDGE will be used.
>>
>> * In a Java EE web or EJB container, when there is an active JTA transaction in progress, session mode is ignored and
>> the JMSSessionMode annotation is unnecessary.
>>
>> * In a Java EE web or EJB container, when there is no active JTA transaction in progress, session mode may be set to
>> either of MessagingContext.AUTO_ACKNOWLEDGE or MessagingContext.DUPS_OK_ACKNOWLEDGE. If no session mode is specified
>> or the JMSSessionMode annotation is omitted a session mode of MessagingContext.AUTO_ACKNOWLEDGE will be used.
>>
>> For more information about the use of session mode when creating a messaging context, see section 10.3 of the JMS 2.0
>> Early Draft, "Behaviour of JMS sessions in the Java EE web or EJB container" and the API documentation for the
>> ConnectionFactory method createMessagingContext(int sessionMode).
>>
>> --------------------------------------------------------
>>
>> Here are three simple examples:
>>
>> 1. Sending a TextMessage in a Java EE web or EJB container.
>>
>> @Inject
>> @JMSConnectionFactory("jms/connectionFactory")
>> private MessagingContext messagingContext;
>>
>> @Resource(mappedName = "jms/inboundQueue")
>> private Queue inboundQueue;
>>
>> public void sendMessageNew(String payload) {
>> messagingContext.send(inboundQueue, payload);
>> }
>>
>> 2. Receiving a message synchronously in a Java EE web or EJB container.
>>
>> @Inject
>> @JMSConnectionFactory("jms/connectionFactory")
>> private MessagingContext messagingContext;
>>
>> @Resource(lookup="jms/inboundQueue")
>> Queue inboundQueue;
>>
>> public String receiveMessageNew() {
>> SyncMessageConsumer syncMessageConsumer = messagingContext.createSyncConsumer(inboundQueue);
>> return syncMessageConsumer.receivePayload(String.class);
>> }
>>
>> 3. Receiving a message synchronously from a durable subscription in a Java EE web or EJB container.
>>
>> @Inject
>> @JMSConnectionFactory("jms/connectionFactory2")
>> private MessagingContext context;
>>
>> @Resource(lookup="jms/inboundTopic")
>> Topic inboundTopic;
>>
>> public String receiveMessageNew() {
>> SyncMessageConsumer syncMessageConsumer = context.createSyncDurableConsumer(inboundTopic, "mysub");
>> return syncMessageConsumer.receivePayload(String.class);
>> }
>>
>>
>>
>>
>>
>>
>>
>> -----
>> No virus found in this message.
>> Checked by AVG - www.avg.com
>> Version: 2012.0.1913 / Virus Database: 2112/4796 - Release Date: 02/08/12
>>
>>
>