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?