jsr342-experts@javaee-spec.java.net

[jsr342-experts] Re: Transactional interceptors and exceptions

From: Werner Keil <werner.keil_at_gmail.com>
Date: Mon, 23 Jan 2012 22:30:00 +0100

On Mon, Jan 23, 2012 at 10:07 PM, David Blevins <david.blevins_at_gmail.com>wrote:

>
> On Jan 20, 2012, at 4:51 PM, David Blevins wrote:
>
> > I don't have a good vision for how separating them would be done, but I
> wonder if it's just as simple as having a "Transaction" interceptor and a
> "RollbackOnException" interceptor. Or some variation on the idea.
>
> This idea came to me as a self-documenting and very flexible possible
> approach:
>
> @Transactional
> @Rollback({RuntimeException.class, MyCustomException.class})
> public void doSomething() {
> //...
> }
>
>
That looks interesting, and though using a slightly different notation, it
feels similar to Java 7 multi catch:

} catch (FirstException | SecondException ex) {
     logger.error(ex);
    throw ex;}



> If the exception is assignable to anything in the list, the transaction is
> rolled back. At this point there isn't the need for @ApplicationException
> or anything similar. Just about anyone could look at that and know what's
> going on and how to alter the behavior.
>
> That's probably good enough right there.
>
> In the future if we get some generally applicable pattern for annotation
> reuse in place (e.g. meta-annotations, more generic version of stereotype,
> whatever want to call it), these common combinations can be easily reused:
>
> @Transactional
> @Rollback({RuntimeException.class, MyCustomException.class})
> @RolesAllowed({"Manager", "Admin"})
> @Metatype
> @Target(ElementType.TYPE)
> @Retention(RetentionPolicy.RUNTIME)
> public @interface AcmeTransactionalOperation {
> }
>
> Then..
>
> @AcmeTransactionalOperation
> public void doSomething() {
> //...
> }
>
> Effectively, the problem of what we need to squish together for
> convenience isn't our problem anymore. We just focus on clear and separate
> concerns. With some ability to compose things together, the question of
> "will users also want x with y" where the answer is clearly "sometimes"
> becomes an easy one for users to solve for themselves.
>
> At that point we as spec designers need to only ask "will users want x and
> possibly not y". And of course, there'd be some flexibility to get that
> answer wrong. If we learn annotation X encompasses too much functionality
> (the "i got more than I wanted" problem), we could of course split those
> concerns into annotations D and E then redefine X as a meta-annotation
> comprised of D and E.
>
>
> -David
>
>
Werner


>
> > I can see concrete use cases for people wanting the protection of
> MANDATORY and having the mindset of, "Look, it's your transaction, deal
> with the exceptions as you see fit. Don't make me tell you what's safe and
> isn't."
> >
> > Of course the concept of app/system exceptions could still be supported
> for when people opt-into the "RollbackOnException" contract, though I
> wonder if it would be all that used. Theoretically, if you had specific
> goals for your exception handling, you could simply assume that
> responsibility. Don't use the standard "RollbackOnException" interceptor
> and instead write your own interceptor to call setRollbackOnly() using
> whatever conditions you wanted. With things separated, you'd have this
> ability, with them "smushed" together you'd have to write all your own
> transaction handling code.
> >
> > A lot of things can simply be traced back to the fact that interceptors
> did not exist when these particular APIs were created.
> >
> > For as large as the CMT API is it's actually not that complete. For
> example, why not an interceptor that calls getRollbackOnly() and throws a
> "DontBotherInvokingMeException" if the answer is false? Was probably not
> worth the xml before and perhaps not worth annotation now, but it's an
> interesting omission.
> >
> >> I definitely agree with you about the SFSB destruction issue flagged
> >> in your blog. I would advocate that we try to fix that for the
> >> transactional interceptor case. We could try to fix it in general
> >> with the introduction of more metadata, if the EJB EG wants.
> >
> > Will definitely give that some thought.
> >
> >>
> >>>
> >>> Not a proposal, but some thoughts.
> >>>
> >>
> >> thanks again for posting
> >
> > Thanks for tackling this topic. It's a fun one. We could certainly
> green-light the CMT API as-as with no harm, but there's no denying we won't
> get this chance again for quite a long time :)
> >
> >
> > -David
> >
> >>>>
> >>>> Jan 18, 2012 07:53:44 PM, jsr342-experts_at_javaee-spec.java.net wrote:
> >>>> Supporting a superset of Spring and EJB would result in something
> >>>> very complex. In particular, the way Spring allows control over
> >>>> the rollback behavior using include lists and exclude lists and
> >>>> class names and Class objects is very complex. We were hoping to
> >>>> satisfy most developers with something much simpler than Spring
> >>>> or EJB.
> >>>>
> >>>> Which of the features from Spring's @Transactional annotation do you
> >>>> think are the most used?
> >>>>
> >>>> reza_rahman_at_lycos.com wrote on 01/17/12 09:47:
> >>>>> Sorry for the delay in responding. Things are hectic these days...
> >>>>>
> >>>>> I actually think EJB 3 application vs. system exception is a good
> idea (except
> >>>>> for that I don't think the special treatment of RemoteException is
> really needed
> >>>>> -- in Spring, system exception == runtime exception). It's easy to
> explain,
> >>>>> works in the real world and corresponds nicely with exception
> handling best
> >>>>> practices:
> http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html?page=1.
> >>>>> Now, I do think it would be very useful to provide a mechanism to
> override
> >>>>> default exception level behavior (no
> >>>>> annotation/checked/unchecked/_at_ApplicationException) per bean/method.
> Basically,
> >>>>> I would like to see the super-set of Spring
> >>>>> (
> http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/transaction/annotation/Transactional.html
> )
> >>>>> and EJB exception handling.
> >>>>>
> >>>>> As to wrapping exceptions, I do agree it's completely overkill and
> >>>>> counter-intuitive (Spring does not do it, for example).
> >>>>>
> >>>>> Hope it helps.
> >>>>>
> >>>>> Jan 10, 2012 03:14:50 PM, jsr342-experts_at_javaee-spec.java.net
> >>>>> <mailto:jsr342-experts_at_javaee-spec.java.net> wrote:
> >>>>>
> >>>>>
> >>>>> It looks like we're in general agreement on the transactional
> interceptor
> >>>>> approach I proposed earlier.
> >>>>>
> >>>>> Aside from the more obvious open issues around naming, there is an
> >>>>> issue related to the handling of exceptions that we need to resolve.
> >>>>>
> >>>>> The issue relates to what should happen with regard to the state of a
> >>>>> transaction when an exception is thrown that reaches a transactional
> >>>>> interceptor.
> >>>>>
> >>>>>
> >>>>> First, some background on how EJB handles container-managed
> transactions....
> >>>>>
> >>>>> The EJB spec distinguishes between "system exceptions", which
> >>>>> cause the container to mark the transaction for rollback, and
> >>>>> "application exceptions", which by default do not cause the
> >>>>> transaction to be marked for rollback.
> >>>>>
> >>>>> An application exception is either a checked exception (other than
> the
> >>>>> RemoteException) or a runtime exception annotated with
> @ApplicationException.
> >>>>>
> >>>>> @Target(TYPE) @Retention(RUNTIME)
> >>>>> public @interface ApplicationException {
> >>>>>
> >>>>> /**
> >>>>> * Indicates whether the container should cause the transaction to
> >>>>> * rollback when the exception is thrown.
> >>>>> */
> >>>>> boolean rollback() default false;
> >>>>>
> >>>>> /**
> >>>>> * Indicates whether the application exception designation should
> >>>>> * apply to subclasses of the annotated exception class.
> >>>>> */
> >>>>> boolean inherited() default true;
> >>>>> }
> >>>>>
> >>>>>
> >>>>> An EJB system exception is a subclass of RemoteException or a
> subclass
> >>>>> of RuntimeException that has not been designated as an application
> >>>>> exception.
> >>>>>
> >>>>> When the EJB container intercepts a system exception (at a business
> >>>>> method boundary), it causes the current transaction to be marked for
> >>>>> rollback. When the called method runs in the context of the caller's
> >>>>> transaction, the container throws the
> EJBTransactionRolledBackException
> >>>>> (or some variant thereof). If a new transaction was *started* for the
> >>>>> called method, the container throws the EJBException. In both these
> >>>>> cases, the original exception is wrappered. Application exceptions
> >>>>> are thrown back to the caller as is.
> >>>>>
> >>>>> If the caller receives an application exception, the caller
> presumably
> >>>>> knows based on the exception type whether the exception causes
> >>>>> rollback or not. Unless the caller is familiar with the transaction
> >>>>> attribute of the called method, however, the caller doesn't know
> >>>>> whether its own transaction was marked for rollback or whether only
> >>>>> the callee's transaction was rolled back. However, the caller can
> >>>>> invoke the getRollbackOnly method to determine the state of its own
> >>>>> transaction.
> >>>>>
> >>>>> In the case of a system exception, if the caller receives the
> >>>>> EJBException, the caller can assume that the callee's transaction was
> >>>>> rolled back, but that the caller's own transaction was not affected.
> >>>>> If the caller receives the EJBTransactionRolledBackException, the
> >>>>> caller knows that its own transaction was marked for rollback (and
> >>>>> that the callee was run within the context of that same transaction).
> >>>>>
> >>>>>
> >>>>> So much for background.... Now, what should the behavior be for
> >>>>> transactional interceptors?
> >>>>>
> >>>>> While we could adopt the EJB approach (modulo some renaming), Bill
> and
> >>>>> I are concerned that it is too complex. (See Chapter 14 ("Exception
> >>>>> Handling") of the EJB 3.1 spec for the gory details.)
> >>>>>
> >>>>> We propose a simpler approach along the following lines:
> >>>>>
> >>>>> By default, all exceptions should result in the current transaction
> >>>>> being marked for rollback. If the developer believes that the
> >>>>> exception should not cause rollback, he or she annotates the
> exception
> >>>>> class with @DontRollbackTransaction (real name for this exception
> *TBD*).
> >>>>>
> >>>>> The DontRollbackTransaction annotation is simply:
> >>>>>
> >>>>> @Target(TYPE)
> >>>>> @Retention(RUNTIME)
> >>>>> @Inherited
> >>>>> public @interface DontRollbackTransaction {}
> >>>>>
> >>>>> All exceptions are thrown back without any wrappering. While we can
> >>>>> understand the rationale for wrappering an exception that marks the
> >>>>> caller's transaction for rollback in a
> TransactionRolledbackException,
> >>>>> we're not convinced that this is needed. Likewise, we're not
> >>>>> convinced of the need to make a distinction by means of exception
> >>>>> wrappering as to whether the callee's transaction was rolled back.
> >>>>>
> >>>>>
> >>>>> We'd like your feedback on this and on your experience with regard
> >>>>> to how developers are actually making use of the current EJB
> facility,
> >>>>> particularly in view of the assumptions that we are making.
> >>>>>
> >>>>> Again, we are assuming the following:
> >>>>>
> >>>>> (1) It is not essential that the caller be able to identify from an
> >>>>> exception that it receives whether its own transaction was marked
> >>>>> for rollback, as the caller can use the getRollbackOnly method
> >>>>> to determine this.
> >>>>>
> >>>>> (2) It is not essential that the caller be able to identify by means
> >>>>> of the exception that it receives back whether a transaction
> >>>>> was started on behalf of a method that it invoked, as it can
> >>>>> use its knowledge of the exception received and getRollbackOnly
> >>>>> status to determine this if it does not already know this
> information.
> >>>>>
> >>>>> (3) Subclasses of dont-rollback exceptions will typically be
> dont-rollback
> >>>>> exceptions, and, if not, they can be defined to not extend
> dont-rollback
> >>>>> exceptions. (Note that if we receive compelling feedback from
> >>>>> developers to the contrary on this point, we could always add a
> >>>>> an element to the annotation to control this at a later time. If
> >>>>> we think this is at all likely, we should choose an annotation
> >>>>> name accordingly.)
> >>>>>
> >>>>>
> >>>>> Please post your feedback.
> >>>>>
> >>>>> Other specleads should feel free to forward this message to your
> expert
> >>>>> groups for
> >>>>> further input.
> >>>>>
> >>>>>
> >>>>> thanks,
> >>>>>
> >>>>> -Linda
> >>>>>
> >>>>
> >>>
> >
>
>


-- 
 Werner Keil | JCP Executive Committee Member (ME) | Eclipse UOMo Lead
 Twitter @wernerkeil | #Java_Social | #EclipseUOMo | #OpenDDR
Skype werner.keil | Google+ gplus.to/wernerkeil
* M-Day: February 1 2012, Frankfurt, Germany. Werner Keil, JCP EC Member,
OpenDDR Evangelist will discuss "Mobile Web Development"
* Social Media Week: February 13-17 2012, Hamburg, Germany. Werner Keil, JCP
EC Member, designated Social JSR Spec Lead will discuss "Java Social"
* Mobile Developer Conference: February 14 2012, Hamburg, Germany. Werner
Keil, JCP EC (ME) Member, OpenDDR Evangelist will present "OpenDDR"