users@jms-spec.java.net

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

From: Pete Muir <pmuir_at_bleepbleep.org.uk>
Date: Tue, 14 Feb 2012 21:49:02 +0000

I'll try to prototype something for you :-)

On 13 Feb 2012, at 12:47, Nigel Deakin wrote:

> Pete,
>
> What would we need to add to the (JMS 2.0) spec to support this, if anything?
>
> Nigel
>
> On 11/02/2012 17:32, Pete Muir wrote:
>> If we wanted to make the scoping of the JMS resources user controllable, I think the best way to do this is to specify slightly more about the "factories" and "managers" (note that these aren't true factories, but rather what comes out of a factory after DI is added), and allow these factories and managers to be overridden by the user. To do this, we would likely want to juggle responsibility for various aspects of the code around from the prototypes we have today, but, I can see no conceptual problem with this. It's nice because the spec can then provide some built in approaches, which can be enabled by a user. A user can then provide an approach, and enable it in the same way.
>>
>> On 10 Feb 2012, at 15:01, Nigel Deakin wrote:
>>
>>> My prototype implementation (much the same as a prototype by Pete) provides request scope by using an object internally which is itself request-scoped.
>>>
>>> I think this means that if we wanted to allow the injected MessagingContext to behave like some other scope we would need to extend the implementation to support this as an option. I think that would be straightforward enough.
>>>
>>> I suppose we could define the default scope of an injected MessagingContext to be request scope (slightly modified as I describe below), but if an alternative scope was specified at the injection point the implementation would take account of this.
>>>
>>> Even if we only support request scope initially I'd like to be sure that the API definition would allow other scopes to be specified.
>>>
>>> How might we specify that an alternative scope was desired? We couldn't use, say,
>>>
>>> @Inject
>>> @SessionScoped
>>> MessagingContext context;
>>>
>>> because the injected object needs to remain a dependent-scoped proxy (because the implementation needs to be able to access the injection point).
>>>
>>> Perhaps we would need something custom like
>>>
>>> @Inject
>>> @JMSScope(SESSION)
>>> MessagingContext context;
>>>
>>> Nigel
>>>
>>>
>>>
>>> On 10/02/2012 10:48, Pete Muir wrote:
>>>> The underlying work that I worked on with Nigel would work fine with any scope (including a possible transaction scope).
>>>>
>>>> Nigel and I discussed whether a transaction scope would be sensible, but we were concerned that whilst it seemed like a good fit when there was a transaction running, the cases when there is no transaction, the semantics of the scope become messy.
>>>>
>>>> IMO the best thing is to produce a general transaction scope proposal that addresses edge cases. JMS could then pick this up if it wants.
>>>>
>>>> On 10 Feb 2012, at 04:10, Reza Rahman wrote:
>>>>
>>>>> This looks pretty good I think.
>>>>>
>>>>> 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. I do hope the request scope has a sensible definition in Java SE/non-web contexts. 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. However, I'll acknowldge that the DI approach would not necessarily be very simple and most folks don't seem to have issues with a flatter "Spring JMS template" style messaging API.
>>>>>
>>>>> I suggest socializing the API with the larger community soon. I can certainly help if needed.
>>>>>
>>>>> 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
>>>>>>
>>>>>>
>>