users@jms-spec.java.net

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

From: Rüdiger zu Dohna <ruediger.dohna_at_1und1.de>
Date: Fri, 17 Feb 2012 16:25:34 +0100

The lifetime of the MessagingContext actually injected (be it a proxy or directly a "real" MessagingContext) has to be the same as the lifetime of the bean it is injected into. So also in the case of a stateful bean, all calls go to that one MessagingContext. Multiple transactions may be involved, but from the perspective of the application it's only one Connection/Session.

If some JMS provider has very expensive connections (probably only remote connections are that expensive), it may be decided that some pooling is required. I think the pooling of the Socket in the Connection behind the MessagingContext would generally be sufficient (and clients that themselves create MessagingContexts from the Connection would benefit, too). Only if more optimization is possible and required, the proxy approach may be an option.

It's sufficient for the spec to describe the behavior of this first paragraph; the second paragraph is entirely up to the implementation.


On 2012-02-17, at 14:06, Nigel Deakin wrote:

> I think the question we need to ask is: does the application need to know exactly when the messaging context is created and closed or is this an internal detail of the container?
>
> Imagine a simple stateful session bean with a single business method that simply sends a string as a message.
>
> @Stateful
> @LocalBean
> public class JavaEESenderNewCDI {
>
> @Inject private MessagingContext context;
> @Resource(lookup="jms/requestQueue") Queue requestQueue;
>
> public void sendMessage(String payload) {
> messagingContext.send(inboundQueue, payload);
> }
> }
>
> Now imagine an application that makes two calls on the same stateful bean, with both calls in the same transaction.
>
> b.sendMessage("Hello")
> b.sendMessage("Goodbye");
>
> Does it make any difference when the "real" MessagingContext is created and closed? I think the answer is yes.
>
> If the underlying messaging context were request-scoped (as I proposed), and each call to sendMessage() counted as a separate request in CDI terms, then each time sendMessage() was called, a new underlying messaging context would be created, used to send the message, and then closed.
>
> However if underlying messaging context was somehow transaction scoped, then the two calls to sendMessage() would use the same underlying messaging context.
>
> These two scenarios are not functionally identical! In the first case, the two messages would be sent using different sessions, whereas in the second case the two messages would be sent using the same session.
>
> Since JMS does not define message order for messages sent using different session, in the first case the messages could be delivered in any order, whilst in the second case the messages must always be delivered in the order "Hello" followed by "Goodbye".
>
> Note that whether the two messages are sent in the same transaction is not the important thing here. It is whether the two messages are sent using the same session, since it is session that defines message order. And we need to understand the "scope" of the underlying messaging context to know whether the same or different sessions are used.
>
> I think this is sufficient to convince me that we can't simply leave the lifetime of the "real" messaging context objects as a detail of the container (I'll not using the word "scope" to avoid confusion) . We need to define it in the spec.
>
> I suspect it's less important exactly what the lifetime is, than that the spec defines at least a minimum lifetime over which the application can be confident that an injected messaging context will use the same session object.
>
> (The application may also need to know whether they are using the same or different sessions in a given transaction since this will affect whether the transaction manager needs to use two-phase commit, though strictly speaking this might be thought of as being just a performance issue).
>
> What do you think?
>
> (The above discussion leaves open the issue of exactly what the lifetime/scope is, and whether we define it in relation to a CDI scope or in more general terms.)
>
> Nigel
>
>
> On 15/02/2012 07:41, Rüdiger zu Dohna wrote:
>>
>> 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); }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>