users@javaee-spec.java.net

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

From: Markus Eisele <myfear_at_web.de>
Date: Fri, 13 Jul 2012 07:15:37 +0200

Hi Linda/all,

that's a good step! +1

- Markus

On 13 July 2012 03:00, Linda DeMichiel <linda.demichiel_at_oracle.com> 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?