users@ejb-spec.java.net

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

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Fri, 10 Feb 2012 14:34:27 -0800

On 2/10/2012 2:24 PM, Marina Vatkina wrote:
> Linda DeMichiel 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?
>
> Interestingly the JTA API use setTransactionTimeout() to modify future transactions started on the current thread. There
> is no begin(timeout) API.

Yes, I noticed that. Further information on its actual use would be helpful.

>
>>
>> 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?
>
> I don't think it's possible to change the timeout value of an active transaction.
>

I wouldn't expect it to be supported. This should be queued as an item for
JTA clarification.

> -marina
>>
>>
>> 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:
>>>>>>>
>>>>>>> <ejb-jar version="3.2">
>>>>>>> <assembly-descriptor>
>>>>>>> <container-transaction>
>>>>>>> <method>
>>>>>>> <ejb-name>A</ejb-name>
>>>>>>> <method-name>*</method-name>
>>>>>>> </method>
>>>>>>> <trans-attribute>RequiresNew</trans-attribute>
>>>>>>> <trans-timeout>
>>>>>>> <timeout>10</timeout>
>>>>>>> <unit>Seconds</unit>
>>>>>>> </trans-timeout>
>>>>>>> </container-transaction>
>>>>>>> </assembly-descriptor>
>>>>>>> </ejb-jar>
>>>>>>>
>>>>>>> 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.
>>>>