jsr343-experts@jms-spec.java.net

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

From: Rüdiger zu Dohna <ruediger.dohna_at_1und1.de>
Date: Mon, 13 Feb 2012 21:06:18 +0100

Nigel,

It would be easiest to implement, if a TransactionScope was available. But if the MessagingContext was DependentScope, then just the actual connection pooling would have to be implemented "by hand". So, if the spec wants to specify the scope of the implementation, it should explain why. Thinking about it, maybe it would be better to just describe the behavior and leave the actual scope up to the implementation.


Rüdiger

On 2012-02-13, at 19:36, Nigel Deakin wrote:

> Rüdiger,
>
> You wrote "I think it would be useful, if the spec would explain, why you'd want to have a scope other than dependent"
>
> What you have described corresponds to how a MessagingContext would behave if it was transaction-scoped.
>
> Nigel
>
>
> On 13/02/2012 14:59, Rüdiger zu Dohna wrote:
>> Nigel,
>>
>> The MessagingContext only needs a _logical_ connection, doesn't it? The _physical_ connection can be taken out of the pool when it enters a transaction context, and put back, when it leaves (by commit or rollback). IIRC, any guarantees about message order, etc., are only given within one transaction, so pooling the physical connection after a commit with the MessagingContext instance still in place would comply, wouldn't it?
>>
>>
>> Regards
>> Rüdiger
>>
>> On 2012-02-13, at 13:56, Nigel Deakin wrote:
>>
>>> Rüdiger,
>>>
>>> If MessagingContext were dependent scope then it would exist for the lifetime of the component which declared it. So for
>>> a session bean this might be for the entire lifetime of the application server. Whilst this might work in JMS terms it
>>> would defeat the connection pooling of the application server. It would mean that even an inactive session bean instance
>>> would be holding on to JMS connections, and so increase the number of connections used overall. I think we need a scope
>>> that supports the recommended Java EE pattern of obtaining a connection from the pool, using it, and returning the
>>> connection to the pool as soon as possible.
>>>
>>> Nigel
>>>
>>> On 13/02/2012 06:33, Rüdiger zu Dohna wrote:
>>>> I think it would be useful, if the spec would explain, why you'd want to have a scope other than dependent... it's not
>>>> really obvious. As long as only one bean with a MessagingContext is involved, dependent scope would be just fine. Only
>>>> when different beans with their own MessagingContext are involved, it is useful, if they can share one context within
>>>> the same transaction, so message-ordering, etc. work as you would expect. I assume this to be not the standard case, so
>>>> the extra complexity may not be expected.
>>>>
>>>>
>>>> On 2012-02-11, at 16:39, John D. Ament wrote:
>>>>
>>>>> I've been thinking on this subject a bit. I think the issue is that for JMS to work right with injection and
>>>>> annotations, the annotations need to act like the annotations in JPA when injection is supported (e.g.
>>>>> @PersistenceContext). I don't think CDI has this supported quite well yet. Pete, any comment on this?
>>>>>
>>>>> John
>>>>>
>>>>>
>>>>> On Wed, Feb 8, 2012 at 10:27 AM, Nigel Deakin<nigel.deakin_at_oracle.com<mailto:nigel.deakin_at_oracle.com>> 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<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<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);
>>>>> }
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>