Results 1 to 10 of 10

Thread: Transaction not rolling back

  1. #1
    Join Date
    Jun 2005
    Location
    Reston, Virginia
    Posts
    8

    Default Transaction not rolling back

    Hello,

    I've been wrestling with this problem all afternoon; I've seen the various postings on this issue but nothing seems to be working. So here is one more instance of this classic problem.

    First, my environment. I am running MySQL backend, using InnoDB database tables. I am using Spring 1.2. I am deploying a web application on Tomcat 5.0.23

    Here is a snippet of my application context file:

    Code:
    <beans>
        
        <!-- some bean declarations -->
    
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
            <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
            <property name="url"><value>jdbc&#58;mysql&#58;//localhost/mydb</value></property>
            <property name="username"><value>root</value></property>
            <property name="password"><value>********</value></property>
        </bean>
        
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="dataSource"><ref bean="dataSource"/></property>
            <property name="mappingResources">
                <list>
                    <value>com/something/SomeObject.hbm.xml</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.max_fetch_depth">3</prop>
                    <prop key="hibernate.connection.autocommit">false</prop>
                </props>
            </property>
        </bean>
        
        <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
    
        <bean id="springHibernateDao" class="com.something.SpringHibernateDao">
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
    
        <!-- some more bean declarations -->
    
        <bean id="serviceTarget" class="com.something.DefaultService">
            <property name="maxAgeInDays"><value>365</value></property>
            <property name="idGenerator"><ref bean="idGenerator"/></property>
        </bean>
        
        <bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager"><ref bean="hibernateTransactionManager"/></property>
            <property name="target"><ref bean="serviceTarget"/></property>
            <property name="transactionAttributes">
                <props>
                    <prop key="saveRequest">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                </props>
            </property>
        </bean>
    </beans>
    I intentionally throw a RuntimeException in my method "saveRequest(...)" after saving an object to see a rollback, however it fails to rollback. This is what gets printed to the log file:

    Code:
    2005-06-21 17&#58;50&#58;44,284 DEBUG &#91;com.something.DefaultService&#93; - <Throwing random exception>
    2005-06-21 17&#58;50&#58;44,284 DEBUG &#91;org.springframework.transaction.interceptor.RuleBasedTransactionAttribute&#93; - <Applying rules to determine whether transaction should rollback on com.something.ServiceException&#58; java.lang.RuntimeException&#58; Viva la Bam!>
    2005-06-21 17&#58;50&#58;44,284 DEBUG &#91;org.springframework.transaction.interceptor.RuleBasedTransactionAttribute&#93; - <Winning rollback rule is&#58; null>
    2005-06-21 17&#58;50&#58;44,284 DEBUG &#91;org.springframework.transaction.interceptor.RuleBasedTransactionAttribute&#93; - <No relevant rollback rule found&#58; applying superclass default>
    2005-06-21 17&#58;50&#58;44,284 DEBUG &#91;org.springframework.transaction.interceptor.TransactionInterceptor&#93; - <com.something.DefaultService.saveRequest threw throwable &#91;com.something.ServiceException&#58; java.lang.RuntimeException&#58; Viva la Bam!&#93; but this does not force transaction rollback>
    2005-06-21 17&#58;50&#58;44,334 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Clearing transaction synchronization>
    2005-06-21 17&#58;50&#58;44,334 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Removed value &#91;org.springframework.orm.hibernate3.SessionHolder@3d0426&#93; for key &#91;org.hibernate.impl.SessionFactoryImpl@167f4bf&#93; from thread &#91;http-8080-Processor24&#93;>
    2005-06-21 17&#58;50&#58;44,334 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Removed value &#91;org.springframework.jdbc.datasource.ConnectionHolder@5084c6&#93; for key &#91;org.springframework.jdbc.datasource.DriverManagerDataSource@381d92&#93; from thread &#91;http-8080-Processor24&#93;>
    The lines that get to me are the ones that says Winning rollback rule is: null and No relevant rollback rule found: applying superclass default. I don't understand what this output means. Why isn't it finding a winner?

    Any help you can provide is greatly appreciated.

    Sincerely,
    Daniel

  2. #2

    Default

    Every single example of spring transaction I have seen, all of them have a '*' in the end. I don't think that will solve the problem but it doesn't hurt to try.

    Code:
        <bean id="txProxyTemplate" abstract="true"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager"><ref bean="transactionManager"/></property>
            <property name="transactionAttributes">
                <props>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="remove*">PROPAGATION_REQUIRED</prop>
                    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                </props>
            </property>
        </bean>
    Code:
        <bean id="manager" parent="txProxyTemplate">
            <property name="target">
                <bean class="com.neeraj.service.impl.BaseManager">
                    <property name="DAO"><ref bean="dao"/></property>
                </bean>
            </property>
        </bean>
    Neeraj Kumar

  3. #3
    Join Date
    Aug 2004
    Posts
    107

    Default

    2005-06-21 17:50:44,284 DEBUG [org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute] - <Applying rules to determine whether transaction should rollback on com.something.ServiceException: java.lang.RuntimeException: Viva la Bam!>
    It "appears" that you are throwing a com.something.ServiceException (which contains a runtime exception). Is ServiceException a run-time exception?

    If it is not, then the transaction will commit (Add -com.something.ServiceException to the transaction attributes if you want the transaction to rollback).

    Dino

  4. #4
    Join Date
    Jun 2005
    Location
    Reston, Virginia
    Posts
    8

    Default

    hucmuc, I am about to try what you suggested, I'll post the results.

    So, the TransactionManager does not rollback on uncaught exceptions? Am I understanding this correctly? I thought that if I specified -com.something.ServiceException then it would ignore this Exception and not rollback when it's thrown, I suppose my understanding of this is incorrect?

  5. #5
    Join Date
    Jun 2005
    Location
    Reston, Virginia
    Posts
    8

    Default

    It worked!

    Would someone please post suggestions where I can read more about how Spring Transactions work short of reading the source and the Spring documentation, e.g., commercial books?

    Thanks!

    Daniel

  6. #6
    Join Date
    Aug 2004
    Posts
    107

    Default

    Quote Originally Posted by sildani
    hucmuc, I am about to try what you suggested, I'll post the results.

    So, the TransactionManager does not rollback on uncaught exceptions? Am I understanding this correctly? I thought that if I specified -com.something.ServiceException then it would ignore this Exception and not rollback when it's thrown, I suppose my understanding of this is incorrect?
    The default mechanism follows the ejb approach: App exceptions (e.g. classes extending Exception) will commit the transaction. Run-time exceptions will rollback.

    If you want to rollback on an App exception within an ejb you have to grab the context and explicitly call rollback. With spring, you define this in the xml file (in my previous email). This demonstrates the power of Spring.

    Note: you need to check the callee of the saveRequest method. It is probably catching run-time exceptions and then wrapping it automatically into an application exception (com.something.ServiceException).

    Dino

  7. #7
    Join Date
    Jun 2005
    Location
    Reston, Virginia
    Posts
    8

    Default

    Thank you for your help. I want to continue the discussion a little more, for I am running into another problem that is related.

    An exception is being thrown in another thread when I call save(). As a result, the exception isn't really going through the transaction-wrapped method.

    Let me post some more log entries:

    Code:
    2005-06-21 20&#58;32&#58;50,786 DEBUG &#91;com.something.SpringHibernatePersister&#93; - <Saving object&#58; com.something.Request@782dc6&#91;id=<null>&#93;>
    2005-06-21 20&#58;32&#58;50,786 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Retrieved value &#91;org.springframework.orm.hibernate3.SessionHolder@1d2aa14&#93; for key &#91;org.hibernate.impl.SessionFactoryImpl@19c123d&#93; bound to thread &#91;http-8080-Processor25&#93;>
    2005-06-21 20&#58;32&#58;50,786 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Retrieved value &#91;org.springframework.orm.hibernate3.SessionHolder@1d2aa14&#93; for key &#91;org.hibernate.impl.SessionFactoryImpl@19c123d&#93; bound to thread &#91;http-8080-Processor25&#93;>
    2005-06-21 20&#58;32&#58;50,796 DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - <Retrieved value &#91;org.springframework.orm.hibernate3.SessionHolder@1d2aa14&#93; for key &#91;org.hibernate.impl.SessionFactoryImpl@19c123d&#93; bound to thread &#91;http-8080-Processor25&#93;>
    2005-06-21 20&#58;32&#58;50,796 DEBUG &#91;org.springframework.transaction.interceptor.TransactionInterceptor&#93; - <Invoking commit for transaction on com.something.DefaultService.saveRequest>
    2005-06-21 20&#58;32&#58;50,906 WARN &#91;org.hibernate.util.JDBCExceptionReporter&#93; - <SQL Error&#58; 1062, SQLState&#58; 23000>
    2005-06-21 20&#58;32&#58;50,916 ERROR &#91;org.hibernate.util.JDBCExceptionReporter&#93; - <Duplicate entry '0517200002' for key 2>
    2005-06-21 20&#58;32&#58;50,916 ERROR &#91;org.hibernate.event.def.AbstractFlushingEventListener&#93; - <Could not synchronize database state with session>
    org.hibernate.exception.ConstraintViolationException&#58; Could not execute JDBC batch update
    	at org.hibernate.exception.ErrorCodeConverter.convert&#40;ErrorCodeConverter.java&#58;74&#41;
    	at org.hibernate.exception.JDBCExceptionHelper.convert&#40;JDBCExceptionHelper.java&#58;43&#41;
    	at org.hibernate.jdbc.AbstractBatcher.executeBatch&#40;AbstractBatcher.java&#58;179&#41;
    	at org.hibernate.jdbc.AbstractBatcher.prepareStatement&#40;AbstractBatcher.java&#58;72&#41;
    	at org.hibernate.jdbc.AbstractBatcher.prepareStatement&#40;AbstractBatcher.java&#58;67&#41;
    	at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement&#40;AbstractBatcher.java&#58;148&#41;
    	at org.hibernate.persister.entity.BasicEntityPersister.insert&#40;BasicEntityPersister.java&#58;1829&#41;
    	at org.hibernate.persister.entity.BasicEntityPersister.insert&#40;BasicEntityPersister.java&#58;2190&#41;
    	at org.hibernate.action.EntityInsertAction.execute&#40;EntityInsertAction.java&#58;46&#41;
    	at org.hibernate.engine.ActionQueue.execute&#40;ActionQueue.java&#58;239&#41;
    	at org.hibernate.engine.ActionQueue.executeActions&#40;ActionQueue.java&#58;223&#41;
    	at org.hibernate.engine.ActionQueue.executeActions&#40;ActionQueue.java&#58;136&#41;
    	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions&#40;AbstractFlushingEventListener.java&#58;274&#41;
    	at org.hibernate.event.def.DefaultFlushEventListener.onFlush&#40;DefaultFlushEventListener.java&#58;27&#41;
    	at org.hibernate.impl.SessionImpl.flush&#40;SessionImpl.java&#58;726&#41;
    	at org.hibernate.impl.SessionImpl.managedFlush&#40;SessionImpl.java&#58;320&#41;
    	at org.hibernate.transaction.JDBCTransaction.commit&#40;JDBCTransaction.java&#58;86&#41;
    	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit&#40;HibernateTransactionManager.java&#58;488&#41;
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit&#40;AbstractPlatformTransactionManager.java&#58;401&#41;
    	at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning&#40;TransactionAspectSupport.java&#58;260&#41;
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke&#40;TransactionInterceptor.java&#58;67&#41;
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed&#40;ReflectiveMethodInvocation.java&#58;144&#41;
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke&#40;JdkDynamicAopProxy.java&#58;174&#41;
    	at $Proxy3.saveRequest&#40;Unknown Source&#41;
    	at com.something.web.MyFormController.onSubmit&#40;MyFormController.java&#58;108&#41;
    	at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission&#40;SimpleFormController.java&#58;248&#41;
    	at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal&#40;AbstractFormController.java&#58;243&#41;
    	at org.springframework.web.servlet.mvc.AbstractController.handleRequest&#40;AbstractController.java&#58;128&#41;
    	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle&#40;SimpleControllerHandlerAdapter.java&#58;44&#41;
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch&#40;DispatcherServlet.java&#58;684&#41;
    	at org.springframework.web.servlet.DispatcherServlet.doService&#40;DispatcherServlet.java&#58;625&#41;
    	at org.springframework.web.servlet.FrameworkServlet.serviceWrapper&#40;FrameworkServlet.java&#58;386&#41;
    	at org.springframework.web.servlet.FrameworkServlet.doPost&#40;FrameworkServlet.java&#58;355&#41;
    	at javax.servlet.http.HttpServlet.service&#40;HttpServlet.java&#58;709&#41;
    	at javax.servlet.http.HttpServlet.service&#40;HttpServlet.java&#58;802&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter&#40;ApplicationFilterChain.java&#58;237&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter&#40;ApplicationFilterChain.java&#58;157&#41;
    	at org.apache.catalina.core.StandardWrapperValve.invoke&#40;StandardWrapperValve.java&#58;214&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardContextValve.invokeInternal&#40;StandardContextValve.java&#58;198&#41;
    	at org.apache.catalina.core.StandardContextValve.invoke&#40;StandardContextValve.java&#58;152&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardHostValve.invoke&#40;StandardHostValve.java&#58;137&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.valves.ErrorReportValve.invoke&#40;ErrorReportValve.java&#58;118&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;102&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardEngineValve.invoke&#40;StandardEngineValve.java&#58;109&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.ContainerBase.invoke&#40;ContainerBase.java&#58;929&#41;
    	at org.apache.coyote.tomcat5.CoyoteAdapter.service&#40;CoyoteAdapter.java&#58;160&#41;
    	at org.apache.coyote.http11.Http11Processor.process&#40;Http11Processor.java&#58;799&#41;
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection&#40;Http11Protocol.java&#58;705&#41;
    	at org.apache.tomcat.util.net.TcpWorkerThread.runIt&#40;PoolTcpEndpoint.java&#58;577&#41;
    	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run&#40;ThreadPool.java&#58;683&#41;
    	at java.lang.Thread.run&#40;Thread.java&#58;534&#41;
    Caused by&#58; java.sql.BatchUpdateException&#58; Duplicate entry '0517200002' for key 2
    	at com.mysql.jdbc.ServerPreparedStatement.executeBatch&#40;ServerPreparedStatement.java&#58;827&#41;
    	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch&#40;BatchingBatcher.java&#58;57&#41;
    	at org.hibernate.jdbc.AbstractBatcher.executeBatch&#40;AbstractBatcher.java&#58;172&#41;
    	... 56 more
    My understanding of the code above is that the exception is getting thrown in some web chain, as evidenced by the stack trace and seeing these lines...

    Code:
    ...
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke&#40;JdkDynamicAopProxy.java&#58;174&#41;
    	at $Proxy3.saveRequest&#40;Unknown Source&#41;
    	at com.something.web.MyFormController.onSubmit&#40;MyFormController.java&#58;108&#41;
    	at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission&#40;SimpleFormController.java&#58;248&#41;
    ...
    To have my transaction rollback upon this exception, what do I have to do? Or better asked, what is the best way to approach this problem? Should I put a proxy in front of the web controller? This would be one step higher than putting it around the actual service method, and makes some sense to me, but I am not sure if that's the best way. Is there a better way?

    Thanks,
    Daniel

  8. #8
    Join Date
    Aug 2004
    Posts
    107

    Default

    I've never used spring's MVC so pardon my ignorance in this area.

    Anyhow, from looking at the stack trace something went wrong in the update (duh!) and the hibernate template will convert the AppException into a spring run-time exception. Theoretically your application should rollback automatically in this instance. You shouldn't need to do anything. Just make sure that you don't convert the runtime exception into an application exception.

    What is the complete signature of saveRequest? Does it have a throw clause?


    Dino

  9. #9
    Join Date
    Jun 2005
    Location
    Reston, Virginia
    Posts
    8

    Default

    You are right, the transaction is actually being rolled back... it wasn't being rolled back before, but it was because I was catching and re-throwing the exception (which happened to be of the 'caught' variety); since correcting THAT problem, it now rolls back on other uncaught exceptions as well.

    I am new to Spring, and this whole notion in general to just let the execption surface to the top and let the framework take care of it. It's a great notion, because now I can define error handlers to take care of my exceptions for me, which is very nice design IMHO. Don't get me wrong, I am not letting EVERY exception surface; but rather I can focus on catching the non-fatal exceptions and lettting the fatal eexceptions bubble up.

    I am just a newbie trying to break free from the old school mold. So far, I have been very pleased with Spring.

    Thank you so much for your help, your time is very appreciated!

  10. #10
    Join Date
    Aug 2004
    Posts
    107

    Default

    Your welcome. Glad to help.

    dino

Similar Threads

  1. Replies: 7
    Last Post: Sep 13th, 2005, 01:45 AM
  2. Transaction rolling back - What's wrong ??
    By vaibhavkhattri in forum Data
    Replies: 5
    Last Post: Aug 16th, 2005, 04:42 AM
  3. Replies: 3
    Last Post: Jul 14th, 2005, 10:30 AM
  4. Replies: 3
    Last Post: Nov 19th, 2004, 07:16 PM
  5. Transaction pb Hibernate/MySQL
    By syluser in forum Data
    Replies: 2
    Last Post: Aug 28th, 2004, 02:40 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •