users@javaee-spec.java.net

[javaee-spec users] Re: [jsr342-experts] Re: Re: transactional interceptors and exceptions

From: Paul Robinson <paul.robinson_at_redhat.com>
Date: Thu, 19 Jul 2012 15:00:23 +0100

Hi Linda,

Thanks for the feedback. My comments inline…

On 17 Jul 2012, at 18:37, Linda DeMichiel wrote:

> Hi Paul, Reza, all,
>
> I think you raise good points. Bill and I did contemplate whether to
> propose that we provide for S2c functionality as well. S2c alone (in
> the absence of S3c) didn't seem flexible enough to us. Also, the
> clear majority of the people who weighed in preferred an S3c approach.

I actually prefer S3c also, but my primary concerns are around co-existence with EJB and migration from EJB. I'd love to go down the S3c route, providing we can find a way to achieve co-existence and migration in a way that is clear and not error prone.

>
> Before we go further on this, however, I think there are a number of
> issues that we need to consider:
>
> * The new transactional interceptors are providing a somewhat
> different functionality than EJB CMT. While the functionality is
> similar, users will need to understand the differences. For example,
> while EJB interposes on every business method invocation,
> transactional interceptor interpositioning will only occur where the
> user has specifically indicated that it should.
> Further, we're not
> proposing that we treat EJB exceptions specially. (Actually, we think
> it would be an unnecessary complication to do so). Thus, EJB
> exceptions (like the RemoteException) that would cause transactions to
> be marked for rollback under EJB will not cause this behavior when
> they reach a transactional interceptor unless the rollbackOn element
> indicates that they should.

Agreed. As far as the Transactional interceptor is concerned, an EJB exception is just another exception and in fact I don't think the Transactional interceptor would have any awareness of EJB whatsoever.

> Also, unlike with EJB, exceptions causing
> rollback won't be wrappered.

Agreed, I also find this unnecessarily complicated.

>
> * While we're open to considering an annotation that could be applied
> to an exception class to indicate that transactions should not be
> marked for rollback for exceptions of that type, we don't think
> that we should embed knowledge of the EJB @ApplicationException
> annotation into the implementation of the new transactional
> interceptors. Any new annotation would then still need to be added to
> those EJB exceptions to achieve the behavior of @ApplicationException
> with the new transactional interceptors. We think that defining a
> different annotation is the right thing to do if we are planning for
> migration *from* EJB.

That's a good point. Even if we did go down the S2c route, it would seem a little strange to have @Transactional et al in the javax.transaction package, whilst making use of javax.ejb.ApplicationException for annotating Exceptions. So as you suggest we would need to have an @ApplicationException (or similar) in javax.transaction which brings with it the scope for error that i feared in my message below.

To summarise i think both approaches (S2c and S3c) could prove equally error prone when migrating away from EJB, so I no longer want to use that as an argument for selecting one or the other. Hopefully we can prevent these bugs through education. A simple rule of thumb; if you're not using EJB any more, you shouldn't be using any javax.ejb classes?

I do still worry about applications where EJBs and @Transactional annotated managed beans co-exist. Here an Exception annotated to mark rollbackOnly would do so when thrown from an EJB method, but not (necessarily) an @Transactional method. I think these bugs would be avoided providing the developer understood that javax.ejb.ApplicationException was an EJB "thing" and thus would only be observed by EJB. Hopefully, given the fact that @Transactional is sufficiently different in many ways, developers will be suitably primed by the time they manage to develop an application that uses both EJB and @Transactional.

>
> * If we add such an annotation, we would need to define the
> interaction with the rollbackOn/dontRollbackOn elements. We are
> currently assuming that the rollbackOn/dontRollbackOn values would
> override the effect of such an annotation.
>
> * Finally, before adding more flexibility/functionality we'd like to
> be sure that our tradeoff would be the right one to make in view of
> the further complexity that it would introduce. Note also, that
> this is something that we could add down the road if we received such
> feedback from developers.
>
> What do all of you think?
>
> thanks again,
>
> -Linda
>
>
> On 7/14/2012 7:46 AM, Paul Robinson wrote:
>> Linda,
>>
>> So it looks like we are settling on adopting almost the same approach for exception handling as that currently provided
>> by EJB. I'll quote my previous email on this:
>>
>> My personal thoughts are that we really have to provide the same behaviour as that provided by EJB transactional
>> intercepters (D3 S2c A1). As this is a JEE related specification, users are going to find it very strange that the
>> semantics of these, seemingly identical, annotations are different. More dangerously, there are going to be many
>> users who don't know that the semantics around exception handling and rollback are different, potentially causing
>> the behaviour of there application to change in unexpected ways.
>>
>>
>> However, the proposal does differ in how non-default behaviour is expressed. By offering S3c rather than S2c, we are
>> going to cause potentially unexpected behaviour for those migrating away from EJB. I would expect that many developers
>> will leave the annotations on the Exception classes, expressing a change from the default, and expect those to be
>> adhered to. Unfortunately, with the S3c approach these old annotations will be ignored along with the developer's intend
>> behaviour. My feeling is that in many (most?) applications, this is the type of bug that is unlikely to be detected
>> during testing and is likely to surface at runtime.
>>
>> My understanding is that EJB and the TX interceptors will co-exist for some time, so we can't prevent this type of issue
>> by simply preventing the EJB related transaction annotations being placed on an Exception class.
>>
>> Do we really need to move away from the accepted and well understood behaviour of EJB?
>>
>> Paul.
>>
>>
>> On 13 Jul 2012, at 02:00, Linda DeMichiel wrote:
>>
>>>
>>> We'd like to close out the remaining open issue as to how to
>>> specify the behavior of transactional interceptors when an
>>> exception is thrown that reaches such an interceptor.
>>>
>>> After tallying and weighing the responses that we received from
>>> polling this group, from our other Java EE specleads, and from members
>>> of the community, we propose that we take the "D3 S3C A1" approach
>>> -- which is consistent with the majority of the opinions we received.
>>> (To refresh your memory, please see Bill's earlier message, appended below.)
>>>
>>>
>>> The proposal is the following:
>>>
>>> By default, "application exceptions" (i.e., checked exceptions /
>>> instances of Exception and its subclasses other than RuntimeException)
>>> do not result in the transactional interceptor marking the transaction
>>> for rollback, and instances of RuntimeException and its subclasses do.
>>>
>>> This default behavior can be overridden via the Transactional
>>> annotation. More specifically, we propose adding to the
>>> Transactional annotation an element to specify additional
>>> exceptions that result in the interceptor marking the
>>> transaction for rollback and an element to specify exceptions
>>> that do not cause the interceptor to mark the transaction for rollback.
>>>
>>> For example:
>>>
>>> @Inherited
>>> @InterceptorBinding
>>> @Target({TYPE, METHOD})
>>> @Retention(RUNTIME)
>>> public @interface Transactional {
>>> TxType value() default TxType.REQUIRED;
>>> Class[] rollbackOn() default {};
>>> Class[] dontRollbackOn() default {};
>>> }
>>>
>>> When a class is specified for either of these elements, the
>>> designated behavior applies to subclasses of that class as well.
>>> If both elements are specified, dontRollbackOn takes precedence.
>>>
>>>
>>> Examples:
>>>
>>> @Transactional(rollbackOn={Exception.class})
>>>
>>> will override behavior for application exceptions, causing the
>>> transaction to be marked for rollback for all application exceptions.
>>>
>>>
>>> @Transactional(dontRollbackOn={IllegalStateException})
>>>
>>> will prevent transactions from being marked for rollback by the
>>> interceptor when an IllegalStateException or any of its subclasses
>>> reaches the interceptor.
>>>
>>>
>>> @Transactional(
>>> rollbackOn={SQLException.class},
>>> dontRollbackOn={SQLWarning.class}
>>> )
>>>
>>> will cause the transaction to be marked for rollback for all
>>> runtime exceptions and all SQLException types except for SQLWarning.
>>>
>>>
>>> Note that we are assuming that there is no special, built-in knowledge
>>> about EJB application exceptions (i.e., runtime exceptions annotated
>>> with @ApplicationException). As far as the interceptor is concerned,
>>> these would be treated just as any other runtime exceptions unless
>>> otherwise specified.
>>>
>>> Please let us know if you have any additional feedback on this.
>>>
>>> thanks!
>>>
>>> -Linda
>>>
>>> --------------------------------
>>>
>>>
>>> On 1/30/2012 12:40 PM, Bill Shannon wrote:
>>>> One of the issues with the new transactional annotations we're
>>>> proposing is how to handle exceptions that are thrown out of a
>>>> transactional method.
>>>>
>>>> The first choice is, what should the default behavior be?
>>>> We have these options:
>>>>
>>>> D1. By default, exceptions don't effect the current transaction.
>>>> D2. By default, exceptions cause the current transaction to be
>>>> marked for rollback.
>>>> D3. By default, runtime exceptions cause the current transaction to be
>>>> marked for rollback; checked exceptions do not effect the current
>>>> transaction.
>>>>
>>>> After deciding on the default behavior, we have these choices for
>>>> overriding the default:
>>>>
>>>> S1. You can't override the default.
>>>> S2a. You can override the default by annotating exceptions that
>>>> should cause rollback. (E.g., with @ApplicationException)
>>>> S2b. You can override the default by annotating exceptions that
>>>> should not cause rollback.
>>>> S2c. You can override the default by annotating exceptions that
>>>> should cause rollback and by annotating exceptions that should
>>>> not cause rollback. (E.g., with a "rollback" element in
>>>> @ApplicationException)
>>>> S3a. You can override the default by annotating class or methods
>>>> with a list of exceptions that should cause rollback.
>>>> S3b. You can override the default by annotating class or methods
>>>> with a list of exceptions that should not cause rollback.
>>>> S3c. You can override the default by annotating class or methods
>>>> with a list of exceptions that should cause rollback, and a
>>>> list of exceptions that should not cause rollback.
>>>>
>>>> The S2c and S3c options have these additional options:
>>>>
>>>> A1. The rollback behavior is an element(s) of the base annotation.
>>>> A2. The rollback behavior is a separate annotation(s).
>>>>
>>>> (Note that S2 and S3 are not mutually exclusive.)
>>>>
>>>> In all cases, the behavior for a given exception is determined by
>>>> looking for an annotation or specification for that particular
>>>> exception and if none is found traversing the superclass chain.
>>>> That is, the exception behavior is always "inherited".
>>>>
>>>>
>>>> My understanding is that Spring supports D3 S3c A1.
>>>> (In addition, Spring allows specifying the exceptions as either
>>>> Class objects or String names, which seems like overkill.)
>>>>
>>>> EJB supports D3 S2c A1 for local beans.
>>>>
>>>> I believe Reza was suggesting D3 S2c S3c A1.
>>>>
>>>> I believe David was suggesting D1 S3a A2.
>>>>
>>>> Our goal with these new transactional annotations was to come up
>>>> with something that was simple, where "simple" means both "has
>>>> few concepts" and "is easily understood by developers". In addition
>>>> to being simple, it needs to satisfy a large percentage of the use cases.
>>>>
>>>> The simplest is D1 S1, but I don't think that matches what developers
>>>> will expect.
>>>>
>>>> Given the prevalence of D3 in existing systems, D3 S1 would be very
>>>> simple. Unfortunately, we're told that many developers are moving
>>>> towards using runtime exceptions for everything, so D3 S2b would be
>>>> a relatively simple approach.
>>>>
>>>> The major advantage I see for the S3 options is that they allow you
>>>> to more easily override the default behavior for "system" exceptions.
>>>> For example, if your method throws IllegalArgumentException in a case
>>>> where it knows that it hasn't modified the state of the transaction,
>>>> you might like that exception to *not* cause the transaction to be
>>>> marked for rollback. With S2, you would have to subclass the exception
>>>> and mark the subclass. But of course that does have the advantage
>>>> that other uses of that exception in methods you call have the default
>>>> behavior.
>>>>
>>>> Which options do you prefer?
>>
>> --
>> Paul Robinson
>> Web service transactions lead
>> paul.robinson_at_redhat.com <mailto:paul.robinson_at_redhat.com>
>>
>> JBoss, a Division of Red Hat
>> Registered in England and Wales under Company Registration No. 03798903
>> Directors: Michael Cunningham (USA), Brendan Lane (Ireland), Matt Parson
>> (USA), Charlie Peters (USA)
>>

-- 
Paul Robinson
Web Service Transactions Lead
paul.robinson_at_redhat.com
JBoss, a Division of Red Hat
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham (USA), Brendan Lane (Ireland), Matt Parson
(USA), Charlie Peters (USA)