jsr343-experts@jms-spec.java.net

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

From: Rüdiger zu Dohna <ruediger.dohna_at_1und1.de>
Date: Wed, 15 Feb 2012 08:41:17 +0100

Reza

The life-cylcle/CDI scope of the MessagingContext definitely has to be dependent... that's undisputed. But the draft draft has specified this to be a proxy that forwards calls to an additional, "hidden" MessagingContext, which in turn has request scope; and the discussion started about whether this hidden context should use transaction scope, when it was available.

But I think this is actually a question of optimization for the implementation. The user only ever sees the directly injected MessagingContext, and this always seems to him to be dependent scope; so this has to be in the spec. (Specs can also be overspecified ;-)

JMS providers actually have several alternatives to the proxy solution. They can pool the physical connections behind the Connection and/or Session (as they apparently already do for JMS 1.1); or they may not need any pooling at all, when the cost to leave connections open is negligible, e.g., when no real connection is required for a JMS provider running in the same JVM. In that case, no hidden MessagingContext would be required whatsoever... the whole thing would just be premature optimization.

I say that we should leave that to the implementors, the users will never know.


On 2012-02-14, at 19:04, reza_rahman_at_lycos.com wrote:

> I think it's best to be as specific as possible in the spec (pun intended). Otherwise, you have needless non-portable behavior. In this case, that can be easily avoided, just as JPA avoids such ambiguities and makes clear what the life-cycle of the persistence context is.
>
> Feb 14, 2012 09:47:54 AM, jsr343-experts_at_jms-spec.java.net wrote:
>
> ===========================================
>
> I discussed this on the phone with Rüdiger.
>
> Rüdiger and I agree that the MessagingContext instance that is injected into the application code would need to be a
> dependent scope proxy to a real MessagingContext. The real MessagingContext would have a shorter lifespan and would be
> closed (and any connection returned to the pool) when it was no longer needed.
>
> In the proposal I wrote for the Early Draft I suggested that the "real" MessagingContext should be request-scoped in
> that it could be closed when the request was complete.
>
> Rüdiger pointed out that a transaction could sometimes span multiple requests. In this case request scope would be too
> short and some kind of transaction scope would be needed.
>
> Rüdiger suggested that although the spec should say that the injected MessagingContext proxy object has dependent scope
> it doesn't need to specify exactly what lifecycle the underlying real MessagingContext would have. So we didn't need to
> mention request scope or transaction scope or any other scope in the spec. The lifecycle of the underlying real
> MessagingContext could be left to the container to manage. From a functional point of view a dependent scope would be
> fine, even if wasteful of resources. It was up to the container if it wanted to close the underlying real
> MessagingContext at some earlier point.
>
> I observed that this is somewhat analogous to the way that JMS doesn't require connection pooling or define how it
> works. Although a JMS connection is sometimes a proxy to a "real" connection this is not defined in the spec. It is up
> to the container to decide if connection pooling is needed and how it is implemented.
>
> (Discuss...)
>
> Nigel
>
>
>
>
> On 14/02/2012 11:33, Rüdiger zu Dohna wrote:
>> Nigel,
>>
>> Thinking about it again, I assume that the transaction scope would not be appropriate. There are a number of values
>> (client id, delivery mode/delay, priority, time-to-live, etc.) that you can set on a messaging context. Any scope
>> other that dependent would mean, that these settings would be shared between several bean instances... not what users
>> would expect, would they? So I think we're bound to use DependentScope.
>>
>> It could well be that the transaction or some other scope would be helpful to implement the actual connection
>> pooling, though.
>>
>>
>> Rüdiger
>>
>> On 2012-02-14, at 11:57, Nigel Deakin wrote:
>>
>>> Rüdiger,
>>>
>>> I think that at the very least the default scope behaviour needs to be specified in the spec (if it wasn't then
>>> applications that used it might not always be portable).
>>>
>>> I suggested the default scope as being request scope (but with a separate instance for each injection point, even
>>> within the same scope) because I know this can be implemented using CDI. If CDI offers some new built-in scope,
>>> such as method scope or transaction scope, we could consider making that the default instead.
>>>
>>> I'm open to extending the spec to allow other built-in scopes to be used, though I'm not sure exactly what this
>>> would look like.
>>>
>>> And I'm open to allowing the application to define its own scopes, though again I'd welcome suggestions on what the
>>> spec would need to say to support this.
>>>
>>> Nigel
>>>
>>> On 13/02/2012 20:06, Rüdiger zu Dohna wrote:
>>>> 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>
>>>>>>>>> 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); }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>
>>