jsr345-experts@ejb-spec.java.net

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

From: Pete Muir <pmuir_at_bleepbleep.org.uk>
Date: Mon, 20 Feb 2012 15:19:44 +0000

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.
>>>