users@ejb-spec.java.net

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

From: Marina Vatkina <marina.vatkina_at_oracle.com>
Date: Fri, 10 Feb 2012 14:24:35 -0800

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.

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

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