Announcement Announcement Module
Collapse
No announcement yet.
Transactional test not rolling back as I expected Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transactional test not rolling back as I expected

    I want to add an integration test to my persistence layer using the AbstractTransactionalSpringContextTests. But I cant figure out why my dao
    doesn't participate in the transaction. Here is an excerpt of my log:

    Code:
    ...
    
    INFO --- JdbcTransactionObjectSupport.<clinit>&#40;60&#41; | JDBC 3.0 Savepoint class is available
    INFO --- AbstractTransactionalSpringContextTests.onSetUp&#40;97&#41; | Began transaction&#58; transaction
     manager &#91;[email protected]65216&#93;; 
     defaultCommit false
    INFO --- AbstractTestLife.testLife&#40;40&#41; | TEST Cleaning up ...
    INFO --- AbstractTestLife.testLife&#40;41&#41; |      ====
    Hibernate&#58; select owner0_.id as id, owner0_.parentId as parentId5_, owner0_.ownerName as ...
    INFO --- AbstractTestLife.testLife&#40;44&#41; | TEST LIFE CYCLE
    INFO --- AbstractTestLife.testLife&#40;46&#41; | ====== TEST Create 1st
    Hibernate&#58; insert into core_owner &#40;parentId, ownerName, ownerDesc, added&#41; values &#40;?, ?, ?, ?&#41;
    INFO --- AbstractTransactionalSpringContextTests.endTransaction&#40;162&#41; | Rolled back transaction 
     after test execution
    The test passes, but the object gets written to the database. The registry:

    Code:
    <beans>
            <bean id="propertyConfigurer" ...
            <bean id="dataSource" 
            	class="org.apache.commons.dbcp.BasicDataSource" 
            	destroy-method="close">
            ...
            <bean id="sessionFactory" 
            	class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            	<property name="dataSource" ref="dataSource"/>
            ...
            <bean id="jdbcExceptionTranslator" 
                    class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator">
            ...
            <bean id="hibernateTemplate" 
    		class="org.springframework.orm.hibernate3.HibernateTemplate">
                    <property name="sessionFactory" ref="sessionFactory"/>
                    <property name="jdbcExceptionTranslator" ref="jdbcExceptionTranslator"/>
            </bean>
            <bean id="genericDao" 
    	        class="org.helianto.core.hibernate.GenericDaoImpl">
    	        <property name="hibernateTemplate" ref="hibernateTemplate"/>
            </bean>
            <bean id="transactionManager" 
                    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                    <property name="sessionFactory" ref="sessionFactory"/>
            </bean>
    	
    </beans>
    I don't have any TransactionProxyFactoryBean here since this is a job for the service layer. Here is the superclass for my tests:

    Code:
    ...
    
    public abstract class AbstractTestBase 
        extends AbstractTransactionalSpringContextTests &#123;
    
        /**
         * Logger for this class
         */
        protected static final Log logger = LogFactory.getLog&#40;AbstractTestBase.class&#41;;
        
        private GenericDao genericDao;
        
        ...
    
        /**
         * @return Returns the genericDao.
         */
        public GenericDao getGenericDao&#40;&#41; &#123;
            return genericDao;
        &#125;
        /**
         * @param genericDao The genericDao to set.
         */
        public void setGenericDao&#40;GenericDao genericDao&#41; &#123;
            this.genericDao = genericDao;
        &#125;
        ...
    &#125;
    The autowire seems to work, as the genericDao is correctly invoked.

    Thanks for any help on this.

    Maurício

  • #2
    Configuration looks OK. Are you sure that autocommit is disabled on the data source? You can set a property on BasicDataSource.

    Comment


    • #3
      Transactional test not rolling back as I expected

      Thanks for the reply, Rod.

      To make sure auto commit is off, I changed my data source as follows:

      Code:
      	<bean id="dataSource" 
      		class="org.apache.commons.dbcp.BasicDataSource" 
      		destroy-method="close">
      		<property name="driverClassName" 
      			value="$&#123;hibernate.connection.driver_class&#125;"/>
      		<property name="url"
      			value="$&#123;hibernate.connection.url&#125;"/>
      		<property name="defaultAutoCommit"
      			value="false"/>
      		<property name="username"
                  value="root"/>
      	</bean>
      The log is showing:

      Code:
      ...
      
      INFO --- LocalSessionFactoryBean.afterPropertiesSet&#40;691&#41; | Building new Hibernate SessionFactory
      INFO --- Configuration.secondPassCompile&#40;875&#41; | processing extends queue
      INFO --- Configuration.secondPassCompile&#40;879&#41; | processing collection mappings
      INFO --- Configuration.secondPassCompile&#40;888&#41; | processing association property references
      INFO --- Configuration.secondPassCompile&#40;917&#41; | processing foreign key constraints
      INFO --- ConnectionProviderFactory.newConnectionProvider&#40;53&#41; | Initializing connection provider&#58; org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider
      INFO --- SettingsFactory.buildSettings&#40;77&#41; | RDBMS&#58; MySQL, version&#58; 3.23.58
      INFO --- SettingsFactory.buildSettings&#40;78&#41; | JDBC driver&#58; MySQL-AB JDBC Driver, version&#58; mysql-connector-java-3.0.16-ga &#40; $Date&#58; 2004/09/30 07&#58;35&#58;03 $, $Revision&#58; 1.27.2.44 $ &#41;
      INFO --- Dialect.<init>&#40;92&#41; | Using dialect&#58; org.hibernate.dialect.MySQLDialect
      INFO --- TransactionFactoryFactory.buildTransactionFactory&#40;31&#41; | Using default transaction strategy &#40;direct JDBC transactions&#41;
      INFO --- TransactionManagerLookupFactory.getTransactionManagerLookup&#40;33&#41; | No TransactionManagerLookup configured &#40;in JTA environment, use of read-write or transactional second-level cache is not recommended&#41;
      
      **** NEXT TWO LINES SEEM TO SHOW THAT COMMIT IS DISABLED!
      
      INFO --- SettingsFactory.buildSettings&#40;125&#41; | Automatic flush during beforeCompletion&#40;&#41;&#58; disabled
      INFO --- SettingsFactory.buildSettings&#40;129&#41; | Automatic session close at end of transaction&#58; disabled
      INFO --- SettingsFactory.buildSettings&#40;136&#41; | JDBC batch size&#58; 15
      INFO --- SettingsFactory.buildSettings&#40;139&#41; | JDBC batch updates for versioned data&#58; disabled
      INFO --- SettingsFactory.buildSettings&#40;144&#41; | Scrollable result sets&#58; enabled
      INFO --- SettingsFactory.buildSettings&#40;152&#41; | JDBC3 getGeneratedKeys&#40;&#41;&#58; enabled
      INFO --- SettingsFactory.buildSettings&#40;160&#41; | Connection release mode&#58; null
      INFO --- SettingsFactory.buildSettings&#40;184&#41; | Maximum outer join fetch depth&#58; 2
      INFO --- SettingsFactory.buildSettings&#40;187&#41; | Default batch fetch size&#58; 1
      INFO --- SettingsFactory.buildSettings&#40;191&#41; | Generate SQL with comments&#58; disabled
      INFO --- SettingsFactory.buildSettings&#40;195&#41; | Order SQL updates by primary key&#58; disabled
      but... it did not work.

      I tried to make sure that my session is participating in the transaction. The log looks like this:

      Code:
      ...
      
      INFO --- AbstractTestLife.testLife&#40;124&#41; | 
      ======== TEST BEGIN Create 2nd instance with key changed from User
      INFO --- UserTests.first&#40;49&#41; | 
               Created User, &#91; org.helianto.core.User@2acc57&#91;id=<null>&#93; details &#91; id = null, username = TEST, userType = I, entity = org.helianto.core.Entity@b122a1&#91;id=1&#93;, credential = org.helianto.core.Credential@59a34&#91;id=1&#93;, enabled = true, credentialsNonExpired = true, accountNonExpired = true, accountNonLocked = true &#93;&#93;
      INFO --- AbstractTestLife.setInstance&#40;57&#41; | 
               Instance is now org.helianto.core.User@2acc57&#91;id=<null>&#93;
      DEBUG --- GenericDaoImpl.save&#40;14&#41; | 
              Saving org.helianto.core.Credential@1fbfd6&#91;id=<null>&#93;
      DEBUG --- HibernateTemplate.execute&#40;307&#41; | Found thread-bound Session for HibernateTemplate
      Hibernate&#58; insert into core_credential &#40;alias, email, firstName, lastName, notPersonal, password, created, lastModified, state&#41; values &#40;?, ?, ?, ?, ?, ?, ?, ?, ?&#41;
      DEBUG --- HibernateTemplate.execute&#40;331&#41; | Not closing pre-bound Hibernate Session after HibernateTemplate
      INFO --- UserTests.changeUniqueKey&#40;66&#41; | 
               Unique key changed, &#91; org.helianto.core.User@2acc57&#91;id=<null>&#93; details &#91; credential = org.helianto.core.Credential@1fbfd6&#91;id=2&#93;, entity = org.helianto.core.Entity@b122a1&#91;id=1&#93; &#93;&#93;
      INFO --- AbstractTestLife.testLife&#40;127&#41; | 
               Instance is now org.helianto.core.User@2acc57&#91;id=<null>&#93;
      DEBUG --- GenericDaoImpl.save&#40;14&#41; | 
              Saving org.helianto.core.User@2acc57&#91;id=<null>&#93;
      DEBUG --- HibernateTemplate.execute&#40;307&#41; | Found thread-bound Session for HibernateTemplate
      Hibernate&#58; insert into core_user &#40;entityId, credentialId, parent, username, enabled, credentialsNonExpired, accountNonExpired, accountNonLocked, userType&#41; values &#40;?, ?, ?, ?, ?, ?, ?, ?, ?&#41;
      DEBUG --- HibernateTemplate.execute&#40;331&#41; | Not closing pre-bound Hibernate Session after HibernateTemplate
      INFO --- AbstractTestLife.testLife&#40;129&#41; | 
               Instance is now org.helianto.core.User@2acc57&#91;id=2&#93;
      INFO --- AbstractTestLife.testLife&#40;131&#41; | 
               TEST END Create 2nd with key changed
      
      INFO --- AbstractTestLife.testLife&#40;133&#41; | 
      ======== TEST BEGIN Update second instance from User
      DEBUG --- GenericDaoImpl.save&#40;14&#41; | 
              Saving org.helianto.core.Credential@6b9c84&#91;id=<null>&#93;
      DEBUG --- HibernateTemplate.execute&#40;307&#41; | Found thread-bound Session for HibernateTemplate
      Hibernate&#58; insert into core_credential &#40;alias, email, firstName, lastName, notPersonal, password, created, lastModified, state&#41; values &#40;?, ?, ?, ?, ?, ?, ?, ?, ?&#41;
      DEBUG --- HibernateTemplate.execute&#40;331&#41; | Not closing pre-bound Hibernate Session after HibernateTemplate
      INFO --- UserTests.changeUniqueKey&#40;66&#41; | 
               Unique key changed, &#91; org.helianto.core.User@2acc57&#91;id=2&#93; details &#91; credential = org.helianto.core.Credential@6b9c84&#91;id=3&#93;, entity = org.helianto.core.Entity@b122a1&#91;id=1&#93; &#93;&#93;
      INFO --- AbstractTestLife.testLife&#40;135&#41; | 
               Instance is now org.helianto.core.User@2acc57&#91;id=2&#93;
      DEBUG --- GenericDaoImpl.update&#40;35&#41; | 
              Updating org.helianto.core.User@2acc57&#91;id=2&#93;
      DEBUG --- HibernateTemplate.execute&#40;307&#41; | Found thread-bound Session for HibernateTemplate
      DEBUG --- HibernateTemplate.execute&#40;331&#41; | Not closing pre-bound Hibernate Session after HibernateTemplate
      INFO --- AbstractTestLife.testLife&#40;138&#41; | 
               TEST END Update second instance
      
      DEBUG --- AbstractPlatformTransactionManager.triggerBeforeCompletion&#40;668&#41; | Triggering beforeCompletion synchronization
      DEBUG --- AbstractPlatformTransactionManager.processRollback&#40;576&#41; | Initiating transaction rollback
      DEBUG --- HibernateTransactionManager.doRollback&#40;505&#41; | Rolling back Hibernate transaction on Session &#91;org.hibernate.impl.SessionImpl@11bed71&#93;
      DEBUG --- AbstractPlatformTransactionManager.triggerAfterCompletion&#40;692&#41; | Triggering afterCompletion synchronization
      DEBUG --- HibernateTransactionManager.doCleanupAfterCompletion&#40;560&#41; | Closing Hibernate Session &#91;org.hibernate.impl.SessionImpl@11bed71&#93; after transaction
      DEBUG --- SessionFactoryUtils.doClose&#40;773&#41; | Closing Hibernate Session
      INFO --- AbstractTransactionalSpringContextTests.endTransaction&#40;162&#41; | Rolled back transaction after test execution
      
      ...
      I don't know what I am doing wrong.

      Thanks again.

      Comment


      • #4
        I believe MySql default configuration does not allow transactions. Are you sure transactions work at all?

        Comment


        • #5
          You have to use INNODB type tables for transactions to work. The default is MYISAM and they are not transactional capable.

          Comment


          • #6
            Transactional test not rolling back as I expected

            That's it. Thank you all.

            Comment

            Working...
            X