jsr345-experts@ejb-spec.java.net

[jsr345-experts] Re: Transaction timeout

From: Carlo de Wolf <cdewolf_at_redhat.com>
Date: Tue, 14 Feb 2012 11:55:09 +0100

On 02/10/2012 11:34 PM, Linda DeMichiel wrote:
>
>
> 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.

That's why we went from specifying the timeout in the
transaction-attribute to specifying it separately. (Which is also the
current case in JBoss AS.)

An EJB developer doesn't have access to TransactionManager, so this
annotation is a simple directive to call tm.setTransactionTimeout.
Nothing more, nothing less.
It does however have implications which EJB developers tend to forget.
It only applies to newly started transactions, it might not pass onto
remote invocations.

Alternatively I would have liked to see the TransactionManager exposed
to interceptors bound outside of the transaction boundary. (In other
words, make the transaction boundary interceptors part of the
interceptor binding order.) But that is something to be covered in the
new tx interceptors or just a bridge too far.

Last we can choose to do nothing, but I find that a chicken out approach.

Carlo

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