users@javaee-spec.java.net

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

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Tue, 17 Jul 2012 10:37:01 -0700

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.

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. Also, unlike with EJB, exceptions causing
rollback won't be wrappered.

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

* 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)
>