[jboss-jira] [JBoss JIRA] Commented: (JBAS-4972) jboss 4.2.1 with spring 2.0.6 causes NoTransactionException

Adrian Brock (JIRA) jira-events at lists.jboss.org
Wed Nov 14 09:17:18 EST 2007


    [ http://jira.jboss.com/jira/browse/JBAS-4972?page=comments#action_12387500 ] 
            
Adrian Brock commented on JBAS-4972:
------------------------------------

This issue is really a duplicate of JBAS-4803 which contained no useful information,
not even how to reproduce it.

Now that I can reproduce it, it is easy to see that Spring is trying to register an transaction
synchronization after it has marked the transaction for rollback.

The relevant logging is this part.

2007-11-14 14:46:38,949 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Setting JTA transaction rollback-only
2007-11-14 14:46:38,949 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Registering after-completion synchronization with existing JTA transaction

org.springframework.transaction.NoTransactionException: No active JTA transaction
        at org.springframework.transaction.jta.JtaTransactionManager.registerAfterCompletionWithExistingTransaction(JtaTransactionManager.java:834)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:871)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:774)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:722)

Looking at the source I have for Spring (version 2.0.2) this is a bug in
org.springframework.transaction.support.AbstractPlatformTransactionManager::processRollback(...)

        /**
         * Process an actual rollback.
         * The completed flag has already been checked.
         * @param status object representing the transaction
         * @throws TransactionException in case of rollback failure
         */
        private void processRollback(DefaultTransactionStatus status) {
                try {
                        try {
                                triggerBeforeCompletion(status);
                                if (status.hasSavepoint()) {
                                        if (status.isDebug()) {
                                                logger.debug("Rolling back transaction to savepoint");
                                        }
                                        status.rollbackToHeldSavepoint();
                                }
                                else if (status.isNewTransaction()) {
                                        if (status.isDebug()) {
                                                logger.debug("Initiating transaction rollback");
                                        }
                                        doRollback(status);
                                }
                                else if (status.hasTransaction()) {
                                        if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                                                if (status.isDebug()) {
                                                        logger.debug(
                                                                        "Participating transaction failed - marking existing transaction as rollback-only");
                                                }

// ===========> HERE IT MARKS THE TRANSACTION FOR ROLLBACK

                                                doSetRollbackOnly(status);
                                        }
                                        else {
                                                if (status.isDebug()) {
                                                        logger.debug(
                                                                        "Participating transaction failed - letting transaction originator decide on rollback");
                                                }
                                        }
                                }
                                else {
                                        logger.debug("Should roll back transaction but cannot - no transaction available");
                                }
                        }
                        catch (RuntimeException ex) {
                                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                                throw ex;
                        }
                        catch (Error err) {
                                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                                throw err;
                        }

// ================> HERE IS WHERE IT TRIES TO REGISTER THE AFTER COMPLETION

                        triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                }

Probably something is wrong with this method in the same class where instead of running the
after completion inline it is trying to register it with the now defunct transaction.
i.e. the if statement is going is taking the wrong branch
BUT THAT IS ONLY A GUESS, I DON'T KNOW THE SPRING CODEBASE


        /**
         * Trigger <code>afterCompletion</code> callbacks.
         * @param status object representing the transaction
         * @param completionStatus completion status according to TransactionSynchronization constants
         */
        private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
                if (status.isNewSynchronization()) {
                        List synchronizations = TransactionSynchronizationManager.getSynchronizations();
                        if (!status.hasTransaction() || status.isNewTransaction()) {
                                if (status.isDebug()) {
                                        logger.debug("Triggering afterCompletion synchronization");
                                }
                                // No transaction or new transaction for the current scope ->
                                // invoke the afterCompletion callbacks immediately
                                invokeAfterCompletion(synchronizations, completionStatus);
                        }
                        else {
                                // Existing transaction that we participate in, controlled outside
                                // of the scope of this Spring transaction manager -> try to register
                                // an afterCompletion callback with the existing (JTA) transaction.
                                registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
                        }
                }
        }



> jboss 4.2.1 with spring 2.0.6 causes NoTransactionException
> -----------------------------------------------------------
>
>                 Key: JBAS-4972
>                 URL: http://jira.jboss.com/jira/browse/JBAS-4972
>             Project: JBoss Application Server
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: Transaction Manager
>    Affects Versions: JBossAS-4.2.1.GA, JBossAS-4.2.2.GA
>            Reporter: Adrian Brock
>         Assigned To: Adrian Brock
>         Attachments: earmodule-1.0.ear, server.log.zip, springejb.zip
>
>
> This issue was raised in the forums and the attachments sent to me private e-mail.
> "
> Hi Adrian,
> In the topic http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4084161
> you were asking for more information or some code that reproduces the problem.
> I created a small ear that contains an EJB, a spring bean and a JSP.
> The JSP calls the EJB which calls the Spring bean.
> I tested the ear with both jboss 4.2.1 and 4.2.2 and got the same error.
> In order to simulate the error, please do the following:
> - Install jboss 4.2.1 or 4.2.2
> - Copy the earmodule-1.0.ear to
> <jboss_home>\server\default\deploy\
> - Copy spring.jar, from <springframework 2.0.6 distribution>\dist\ to <jboss_home>\server\default\lib\
> (I could not attach the jar to this email because your email server complains that the zip is too big)
> - Additionally add to <jboss_home>\server\default\conf\jboss-log4j.xml the
> following in order to see how spring is using the transaction started by EJB
> to enlist the spring bean (UserBo):
>    <category name="org.springframework.transaction">
>       <appender-ref ref="CONSOLE"/>
>       <appender-ref ref="FILE"/>
>       <priority value="DEBUG"/>
>    </category>
> and if you want to see more details at console about spring transaction manager,
> change the Threshold of CONSOLE appender to DEBUG.
> - Start jboss
> - To trigger the error, open in a browser the URL:
> http://localhost:8080/test/
> I attached the source and the ear to this email + the server log from jboss 4.2.2.
> Like I said in the topic, this was not happening on jboss 4.0.4.
> Could you please take a look and do a debug perhaps.
> Thank you.
> I look forward to hearing from you.
> Best Regards,
> Bucegi Omu
> "

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the jboss-jira mailing list