On Feb 22, 2011, at 4:37 PM, David Jencks wrote:

> cf 
> https://issues.apache.org/jira/browse/GERONIMO-4576 
> https://issues.apache.org/jira/browse/OPENEJB-1091 
> 
> For a long time we've known of this problem where an exception thrown by a 
> transaction synchronization that causes a transaction to be marked for 
> rollback only is lost.  When the user or openejb tries to commit the 
> transaction the transaction manager throws a RollbackException which 
> currently doesn't have any information about the original exception.
> 
> People have complained about this for a long time.... now we're trying to fix 
> it.
> 
> There are two parts AFAICT.  I think in openejb we just need to take the 
> TransactionRolledBackException we are currently throwing and call initCause 
> with the RollbackException from the tm.  In TransactionPolicy this would be 
> something like
> 
>        } catch (RollbackException e) {
> 
>            txLogger.info("The transaction has been rolled back rather than 
> commited: " + e.getMessage());
>            // TODO can't set initCause on a TransactionRolledbackException, 
> update the convertException and related code to handle something else 
>            Throwable txe = new 
> javax.transaction.TransactionRolledbackException("Transaction was rolled 
> back, presumably because setRollbackOnly was called during a synchronization: 
> "+e.getMessage());
> --            throw new ApplicationException(txe);
> ++            throw new ApplicationException(txe.initCause(e);
> 
> In the transaction implementation we need to keep track of the exception that 
> caused us to mark rollback only and then use it as the cause of the 
> RollbackException, e.g.
> 
> private Exception markRollbackCause;
> 
> ...
> RollbackException rollbackException = new RollbackException("Unable to 
> commit: transaction marked for rollback");
> if (markRollbackCause != null) { 
> rollbackException.initCause(markRollbackCause); 
> }
> throw rollbackException; 
> 
> ...
> 
>    private void markRollbackCause(Exception e) {
>        if (markRollbackCause == null) {
>            markRollbackCause = e;
>        }
>    }
> 
> (this tm code is committed in rev 1073479 in my sandbox tm)
> 
> At the moment if a sync throws an exception, we keep calling the other syncs, 
> and it would be possible for other ways of marking rollback only due to an 
> exception to occur more than once as well.  So there's a question as to 
> whether we should only record the first cause of rollback only or if we 
> should keep track of a list of causes.  The code above only tracks the first  
> cause.  I'm really not sure what to think about this and would appreciate 
> comments.
> 
> Thoughts?

Great to get more data captured. So, I'm all for it... 

Personally, I would think the *first* cause will almost always be the most 
important information a user would want... Any situations where subsequent 
exceptions are going to yield valuable information? Or will they mostly 
generate noise?

--kevan

Reply via email to