jsr345-experts@ejb-spec.java.net

[jsr345-experts] Re: [ejb-spec users] Re: Transaction timeout

From: Marina Vatkina <marina.vatkina_at_oracle.com>
Date: Mon, 20 Feb 2012 11:23:37 -0800

Thank you Pete.

-marina

Pete Muir wrote:
> I collected some feedback from colleagues on this topic, and it was pretty much universally agreed that this is a bad solution to a problem that very few of
> the colleagues I asked had ever seen in the wild (only Emmanuel Bernard said he thought it was useful).
>
> First, we noted that this can be set via UserTransaction, as well as TransactionManager, so is
> something that can be achieved today if needed. I think the consensus was that this is probably
> an edge case, so something we could leave on UT.
>
> -----------------
>
> I've never had a use for this.
>
> +1 for calling TransactionManager/UserTransaction for this. Also I don't like that it
> doesn't affect the current transaction, that's what I would expect it
> to do do as well.
>
> ------------------
>
> This means someone can annotate a method with the transactiontimeout, but that method might not start a
> transaction, so therefore the timeout is not applied to that method.
>
> That's a terrible solution! Not only does it have the issue you describe but developers are going to think their
> method will timeout which is simply not the case.
>
> Transaction timeouts should be a container setting, and developers should probably stay away from them.
>
> ----------------
>
> I agree with the previous posters, it seems misleading to specify it on a method where it would not necessarily
> affect that methods behaviour.
>
> I am certainly not recommending it, but in theory it would work on a method with @TransactionAttribute(RequiresNew)
> but that would be the only case it could be guaranteed to work. For instance, it would be unpredictable whether it would
> affect a @TransactionAttributed(Required).
>
> -----------------
>
> I agree, it doesn't sound like a great idea. Especially if the API we offer is misleading or error prone, which the current
> proposals seem to be.
>
> However, if we did end up doing this, having a separate annotation for the timeout would make most sense. We would
> then have to be careful to makes sure we take the right action when an invalid combination of annotations is used. Surely,
> there must be other technologies that give the user the opportunity to specify an ambiguous/invalid combination of annotations.
> We'd need to see how they handle it.
>
> My main concern is whether it is really needed. In my experience, from transactions consultancy, I see users setting the timeout
> as an extreme upper bound to make sure progress is made. This is set at a course grained level for all transactions. The proposed
> solution seems to be useful for situations where you want fine grained control over the timeout, for specific workloads. Also, you
> need the precision that can't be achieved with a global timeout value. OK, my evidence is anecdotal, from a relatively small sample
> size, so there may be many users needing to do this. However, i don't see it being a common use case, warranting an annotation.
> Especially if we can't come up with an API that is not error prone or misleading.
>
> The original email conversation doesn't seem to present the motivation for this feature. Do we have users crying out for this? Can
> references be provided? Maybe there are other solutions to meeting our users needs, without providing this annotation?
>
> ------------------
>
> I have personally been in situations where I wish I could have customized the time out for a given method / call stack. Some operation
> expected to be longer than usual and where the default was not appropriate. But definitely @Timeout or the @Transaction.timeout annotation
> should impact the current transaction or the tx about to be opened. If that impacts future non related transactions, that does not make sense.
>
> ------------------
>
> The timeout can be set on the UserTransaction. This then sets if for all transactions created on that thread for all subsequent transactions.
> Therefore any already running transaction is not going to have it's timeout changed.
>
> So this approach could work for CMT, but only if the transaction interceptor of the annotated method begins the transaction.
>
> For example:
>
> REQUIRES_NEW could first look for the Timeout annotation before begining a new transaction and modify the timeout accordingly. When
> the interceptor returns it would reset the timeout back to what it was originally. We must change this value back as we don't want it set for other
> method calls, and also that thread may later be used by some other bean.
>
> REQUIRED, would work if there is no other active transaction running when the method is invoked. Clearly this could only be known at runtime,
> making it hard to come up with some protection, to prevent this.
>
> MANDATORY: requires an existing transaction, so the timeout value would never be observed.
>
> NEVER, SUPPORTS and NOT_SUPPORTED: does not make sense to have the timeout set ever.
>
> Clearly this is very misleading and error prone. And in the case of REQUIRED, even an educated developer would not know if their timeout was
> going to be observed.
>
> We may have a strong requirement for this feature, but I think we need to come up with a better solution.
>
>
>
> On 10 Feb 2012, at 19:45, reza_rahman_at_lycos.com wrote:
>
>
>> I agree that there is no burning need for this.
>>
>> In my experience, it's only useful for cases where you have EJBs that inevitably need to handle long-running transactions (an edge case and should be done sparingly).
>>
>> Feb 10, 2012 02:18:45 PM, jsr345-experts_at_ejb-spec.java.net wrote:
>>
>> ===========================================
>>
>> I have to say that I'm a bit skeptical about specifying this at method level.
>>
>> Do we have any compelling user requests for this level of granularity -- as
>> opposed, say, to being able to set a transaction timeout more globally for
>> the application?
>>
>> Unlike AccessTimeout and StatefulTimeout, which apply to the access of
>> specific beans, in the absence of RequiresNew, it is not always
>> obvious where a tx is begun, or how different timeout settings across
>> multiple CMT methods would interrelate. Does only the tx timeout set
>> at the method where the tx originates apply, or what happens if there
>> are multiple values for the same transaction?
>>
>>
>> On 2/10/2012 10:45 AM, Marina Vatkina wrote:
>>
>>> Returning (temporary) back to this thread...
>>>
>>> While I don't think we should support settings that are not on the method that is being invoked, this new annotation can
>>> easily be part of the upcoming CMT support for CDI managed beans that is being discussed in the Platform EG.
>>>
>>> When the new CMT annotations are introduced, let's make sure the transaction timeout is one of them. EJBs should be able
>>> to reuse it even if we don't support the other new annotations.
>>>
>>> thanks,
>>> -marina
>>>
>>> David Blevins wrote:
>>>
>>>> On Dec 12, 2011, at 2:58 AM, Carlo de Wolf wrote:
>>>>
>>>>
>>>>> I've raised http://java.net/jira/browse/EJB_SPEC-46 using the annotation you provided.
>>>>>
>>>>> Let's dig into the edge case:
>>>>>
>>>>> @Stateless class FooBean {
>>>>> @EJB OtherBean other;
>>>>>
>>>>> @TransactionAttribute(NEVER)
>>>>> @TransactionTimeout(30)
>>>>> public void doSomething() {
>>>>> other.doSomethingElse();
>>>>> }
>>>>> }
>>>>>
>>>>> @Stateless class OtherBean {
>>>>> @TransactionAttribute(REQUIRED) // REQUIRES_NEW
>>>>> public void doSomethingElse() {
>>>>> assert currentTransactionTimeout() == 30;
>>>>> }
>>>>> }
>>>>>
>>>>> Does it blend?
>>>>>
>>>>> I would say yes. The transaction timeout is set on the current thread before FooBean.doSomething.
>>>>>
>>>> I was imaging something plain and declared and deterministic. If the timeout is not specified explicitly in annotation
>>>> or xml on the method that starts the transaction (or its class for class-level defaults) then the timeout defaults to
>>>> whatever behavior that vendor had prior to EJB 3.2. Consistent to how @StatefulTimeout and @AccessTimeout behave and
>>>> fit gently ontop of what vendors were doing already in a way that doesn't prevent them from continuing to do it.
>>>>
>>>>
>>>> Reading between the lines I think I see what you're getting at though; that the callers of beans (not the beans
>>>> themselves) should be able to make these kinds of decisions. There might be room for that in general if we can find
>>>> good semantics for it, but I wouldn't want to see us quietly change the semantics of @TransactionTimeout to be wildly
>>>> different than @StatefulTimeout or @AccessTimeout where the caller does not get to decide the timeouts for their usage
>>>> of the bean (the bean decides). I think quietly diverging here would actually damage our ability to cleanly do
>>>> caller-driven metadata in the future (as opposed to callee-driven as we have now).
>>>>
>>>> It's a good idea you're onto. There's some real vision there I've come to appreciate. Not sure what JSR-308 will offer
>>>> in this regard, but if we had the ability to annotate method calls (as opposed to the method itself) and some clean
>>>> way to get that data at runtime, we could do some really simple and powerful caller-driven declarative programming.
>>>>
>>>> Using your example, imagine how cool this would be:
>>>>
>>>> @Stateless class FooBean {
>>>> @EJB OtherBean other;
>>>> @TransactionAttribute(NEVER)
>>>> public void doSomething() {
>>>>
>>>> @TransactionTimeout(30)
>>>> @TransactionAttribute(REQUIRED)
>>>> other.doSomethingElse();
>>>> }
>>>> }
>>>> @Stateless class OtherBean {
>>>> public void doSomethingElse() {
>>>> assert currentTransactionTimeout() == 30;
>>>> }
>>>> }
>>>>
>>>> If that day comes, we'll be really glad we don't have a legacy mess to clean up.
>>>>
>>>> Not sure how you'd do that at the VM level. Maybe similar to a closure, fabricate a method call around the
>>>> other.doSomethingElse() call and move the annotations to that method. Then you just need some way expose that method
>>>> object at runtime to interested parties (in this situation, the container). Maybe you don't even need special
>>>> semantics, the container could just see this fabricated method as a plain method call made on the proxy and do what it
>>>> does anyway.
>>>>
>>>> Then there are effectively no "EJBs" anymore. There are effectively only services you use on plain objects when and
>>>> were you want as determined by the code that uses those objects, not the objects themselves. People write plain code,
>>>> others can use it in an "enterprisey" way if they like when they like. No more component fixation. Would change the
>>>> way we do pretty much everything. Imagine this:
>>>>
>>>> public void doSomething() {
>>>> if (thisMightBeLong) {
>>>> @TransactionTimeout(10, TimeUnit.MINUTES)
>>>> @TransactionAttribute(REQUIRED)
>>>> other.doSomethingElse();
>>>> } else {
>>>> @TransactionTimeout(30)
>>>> @TransactionAttribute(REQUIRED)
>>>> other.doSomethingElse();
>>>> }
>>>> }
>>>>
>>>> Got off on a tangent :) Anyway, I see the vision and like it. Not sure we have the tools to do it now, but boy will it
>>>> be cool when we do.
>>>>
>>>>
>>>> -David
>>>>
>>>>
>>>>
>>>>> On 12/09/2011 04:29 PM, David Blevins wrote:
>>>>>
>>>>>> It's a good concept.
>>>>>>
>>>>>> The fact that many @TransactionAttributes can effectively affect a single transaction seems to lead me to the
>>>>>> conclusion that the timeout should be a different annotation. Otherwise I suspect there will be several frustrated
>>>>>> people who can't figure out why the timeout doesn't work when they put it on SUPPORTS or worse REQUIRED in
>>>>>> situations where that particular method didn't start the transaction.
>>>>>>
>>>>>> Perhaps @TransactionTimeout to be consistent with @StatefulTimeout and @AccessTimeout. We could have put the
>>>>>> stateful timeout data on @Stateful. As well we could have put the access timeout info on @Lock. We didn't, so my
>>>>>> vote would be for consistency.
>>>>>>
>>>>>> @Target({METHOD, TYPE})
>>>>>> @Retention(RUNTIME)
>>>>>> public @interface TransactionTimeout {
>>>>>> long timeout() default -1L;
>>>>>> TimeUnit unit() default TimeUnit.SECONDS;
>>>>>> }
>>>>>>
>>>>>>
>>>>>> What I wonder is that it clearly only would work 100% of the time on REQUIRES_NEW and sometimes on REQUIRED. We'll
>>>>>> definitely have to document that, but I wonder if we might want to be a bit strict about it.
>>>>>>
>>>>>> Something like this is a little loose, but workable:
>>>>>>
>>>>>> @Stateless
>>>>>> @TransactionTimeout(30)
>>>>>> public class FooBean {
>>>>>>
>>>>>> @TransactionAttribute(REQUIRES_NEW)
>>>>>> public void doSomething() {}
>>>>>>
>>>>>> @TransactionAttribute(NEVER)
>>>>>> public void doSomething() {}
>>>>>> }
>>>>>>
>>>>>> This is flat out wrong:
>>>>>>
>>>>>> @Stateless
>>>>>> public class FooBean {
>>>>>>
>>>>>> @TransactionAttribute(REQUIRES_NEW)
>>>>>> @TransactionTimeout(30)
>>>>>> public void doSomething() {}
>>>>>>
>>>>>> @TransactionAttribute(NEVER)
>>>>>> @TransactionTimeout(30)
>>>>>> public void doSomething() {}
>>>>>> }
>>>>>>
>>>>>> Not sure what tact is the best to discourage that blatant misuse.
>>>>>>
>>>>>>
>>>>>> -David
>>>>>>
>>>>>>
>>>>>> On Dec 9, 2011, at 3:35 AM, Carlo de Wolf wrote:
>>>>>>
>>>>>>
>>>>>>> Given the functionality of a transaction manager to set the transaction timeout [1]. I would like to expose this
>>>>>>> feature in a spec defined manner.
>>>>>>>
>>>>>>> How about the following annotation:
>>>>>>>
>>>>>>> @Target({METHOD, TYPE})
>>>>>>> @Retention(RUNTIME)
>>>>>>> public @interface TransactionAttribute {
>>>>>>> TransactionAttributeType value() default TransactionAttributeType.REQUIRED;
>>>>>>> long timeout() default -1L;
>>>>>>> TimeUnit unit() default TimeUnit.SECONDS;
>>>>>>> }
>>>>>>>
>>>>>>> Where -1 means unspecified.
>>>>>>>
>>>>>>> And the following descriptor fragment:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> A
>>>>>>> *
>>>>>>>
>>>>>>> RequiresNew
>>>>>>>
>>>>>>> 10
>>>>>>> Seconds
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> What do you guys think?
>>>>>>>
>>>>>>> Carlo
>>>>>>>
>>>>>>> [1] http://docs.oracle.com/javaee/6/api/javax/transaction/TransactionManager.html#setTransactionTimeout%28int%29
>>>>>>>
>>>>>>> PS. Since people are going to dig, we discussed changing transaction attributes on Oct 17th 2007.
>>>>>>>
>
>