Search code examples
springjpatestingjtaatomikos

Spring/JTA/JPA DAO integration test doesn't rollback?


My DAO integration tests are failing because entities created during the tests are still in the database at the start of the next test. The exact same behavior is seen from both MySQL 5 and H2.

The test classes are annotated with:

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( { "/testPersist-applicationContext.xml" })

The transaction bean configuration in the test application context is as follows:

<tx:annotation-driven />

<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
</bean>

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

The entity manager is configured as follows:

<bean id="myappTestLocalEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="myapp" />
    <property name="persistenceUnitPostProcessors">
        <bean                class="com.myapp.core.persist.util.JtaPersistenceUnitPostProcessor">
        <property name="jtaDataSource" ref="myappPersistTestJdbcDataSource" />
        </bean>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="false" />
            <property name="database" value="$DS{hibernate.database}" />
            <property name="databasePlatform" value="$DS{hibernate.dialect}" />
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
            </prop>
            <prop key="hibernate.format_sql">true"</prop>
            <prop key="hibernate.use_sql_comments">true</prop>
            </props>
    </property>
</bean>

<context:annotation-config />

Everything in the log files seem to be fine...I can see messages from Spring about rollback and from Atomikos about rollback as well. But frankly, the logs are so huge and so complex, I could easily be missing something...

Yet the inserted test data remains! Any clues?


Solution

  • It turned out that my C3P0 JDBC data source was not XA aware and was therefore not participating in the transaction. Why I did not get an error, nor a warning in the log file, I do not know. Nonetheless, the reason you cannot use an XA aware data source is explained very nicely here. Note that the data source does not need to be XA capable...just XA aware.

    Replacing the C3P0 data source with the following one solved the problem.

    <bean id="myappJTANonXADataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean">
            <property name="uniqueResourceName" value="myappDatabase" />
            <property name="driverClassName" value="$DS{hibernate.connection.driver_class}" />
            <property name="url" value="$DS{hibernate.connection.url}" />
            <property name="user" value="$DS{hibernate.connection.username}" />
            <property name="password" value="$DS{hibernate.connection.password}" />
            <property name="maxPoolSize" value="20" />
            <property name="reapTimeout" value="300" />
    </bean>