Results 1 to 9 of 9

Thread: Problem with rollback on exception

  1. #1
    Join Date
    Nov 2007
    Posts
    11

    Default Problem with rollback on exception

    Hi,

    I have spring application, accessing Postgres (8.x) database through Hibernate 3. In recent time i have noticed that DB changes in my service method are not rolled back when exception happens. My application is running on jboss 4.2.3, and using jndi XA datasource to connect to postgres.

    During debugging I have noticed that org.springframework.orm.hibernate3.SpringSessionSy nchronization.beforeCommit(boolean readOnly) is called. This method is flushing the session which is resulting in DataAccessException. At this point when I browse my database I see that entities created in service method (except one that is causing the problem) are already stored in database. Subsequently rollback method is called but it didn't change anything.

    My application is generated with andromda using hibernate3 cartridge. I have tried to update spring version to 2.5.6 and hibernate to 3.2.7.ga but didn't help.

    Does somebody has an idea why these changes are not rolled back? Thanx.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    I would say wrongly configured transactions.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Nov 2007
    Posts
    11

    Default

    I had:

    Code:
    <beans>
        <!-- ========================= DATASOURCE DEFINITION ========================= -->
    
        <!-- JNDI DataSource for J2EE environments -->
        <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName"><value>java:/jdbc/MyAppDatasource</value></property>
        </bean>
    
        <!-- ====================== End of DATASOURCE DEFINITION ====================== -->
    
        <!-- ===================== TRANSACTION MANAGER DEFINITION ========================= -->
    
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <property name="dataSource"><ref bean="dataSource"/></property>
        </bean>
    
        <!-- ===================== TRANSACTION MANAGER DEFINITION ========================= -->
    
    </beans>
    and when i replaced transaction manager with HibernateTransactionManager it started working as expected:

    Code:
        <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName"><value>java:/jdbc/myAppDatasource</value></property>
        </bean>
    
        <!-- ====================== End of DATASOURCE DEFINITION ====================== -->
    
        <!-- ===================== TRANSACTION MANAGER DEFINITION ========================= -->
    
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                <property name="dataSource"><ref bean="dataSource"/></property>
                <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
    The rest of relevant configuration:
    Code:
        <!-- Hibernate SessionFactory -->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="dataSource"><ref bean="dataSource"/></property>
            <property name="mappingLocations"><ref bean="hibernateMappingLocations"/></property>
            <property name="hibernateProperties"><ref bean="hibernateProperties"/></property>
            <!-- applicationContext sessionFactory merge-point -->
        </bean>
    
        <!-- The Hibernate interceptor -->
        <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
            <!-- applicationContext hibernateInterceptor merge-point -->
        </bean>
    
        <bean id="serviceTransactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
            <property name="transactionManager"><ref bean="transactionManager"/></property>
            <property name="transactionAttributeSource">
                <value>
                    com.myapp.deployment.service.DeploymentService.parse=PROPAGATION_REQUIRED
                </value>
            </property>
        <!-- applicationContext serviceTransactionInterceptor merge-point -->
        </bean>
    But the question stays.... why it doesn't work with DataSourceTransactionManager?

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    Because you MUST use the transaction manager for the chosen technology. Hibernate manages it transactions on the session not on the datasource. The session is the transactional resource here not the datasource (well in the end it is but not for your application).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5

    Default

    I can see that in your configuration of transactionAttributeSource of transactionInterceptor you have posted, is not specified what type of exception must be rolled back or commited.

    Code:
        <bean id="serviceTransactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
            <property name="transactionManager"><ref bean="transactionManager"/></property>
            <property name="transactionAttributeSource">
                <value>
                    com.myapp.deployment.service.DeploymentService.parse=PROPAGATION_REQUIRED
                </value>
            </property>
        <!-- applicationContext serviceTransactionInterceptor merge-point -->
        </bean>
    So, looking at DataSourceTransactionManager implementation, you can find that, by default, rollback is called when the exception that is thrown must extend java.lang.RuntimeException or java.lang.Error.

    The Exception that is thrown by the Service, extends java.lang.RuntimeException or java.lang.Error ?

  6. #6
    Join Date
    Nov 2007
    Posts
    11

    Default

    The exception is not thrown by service, but after service call when interceptor calls flush... But anyway my problem is solved by using HibernateTransactionManager.

  7. #7

    Default

    Yes, I have read it, but in your configuration you have:

    Code:
    <value>com.myapp.deployment.service.DeploymentService.parse=PROPAGATION_REQUIRED
    </value>
    and the method parse in DeploymentService what kind of exception throw ? (that method must throw an exception to handle transaction with DataSourceTransactionManager)

    The best solution is using HibernateTransactionManager, but you ask:

    ... But the question stays.... why it doesn't work with DataSourceTransactionManager?
    and my answer is on that question (if you like, try it).

  8. #8
    Join Date
    Nov 2007
    Posts
    11

    Default

    The 'parse' method was throwing java.lang.Exception, and changing this to RuntimeException didn't help. But the exception which should trigger rolback was org.springframework.dao.InvalidDataAccessResourceU sageException and this is RuntimeException, and it is caught in AbstractPlatformTransactionManager.processCommit(D efaultTransactionStatus status) method. Than org.springframework.transaction.support.AbstractPl atformTransactionManager.doRollbackOnCommitExcepti on(DefaultTransactionStatus, Throwable) method is called but without expected result and without exception which could give me a hint.

  9. #9
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    That was all due to the use of the wrong transaction manager. If there is no transaction basically each query leads to a commit (i.e. multiple transactions due to the use of auto commit on the connection), so then at the point of the exception all/most data is already committed in the database.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Posting Permissions

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