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

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?

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>

I think you will need to go through the logs in details. It could be that the rollbacks you are seeing are working, except that something else has executed a commit first. I also cannot see anything in your code which indicates automated rollback. And that it should occur at the end of each test. If you are depending on a timeout based rollback it could be that the second test is running before the timeout occurs, therefore it sees the data before it is rolled back.
Many options here there is :-)

Related

spring bean optional property

I am using a data source defined in tomcat in my spring configuration as shown in the below xml.
It can happen sometimes that this data source may not be defined in the context.xml of tomcat.
In such cases , the context initialization fails since myDS is not found.
Is it possible to configure the datasource as optional so that application initialisation is not impacted ?
There can be a run time error when this data source is accessed , which is acceptable
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDS"/>
</bean>
<bean id="myEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="com..XX.XX" />
<property name="persistenceUnitName" value="myPU" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="#{systemProperties['showSql'] == null ? 'true' : systemProperties['showSql'] }" />
</bean>
</property>
<property name="persistenceUnitPostProcessors">
<list>
<ref bean="wrkflw-punitpostprocessor" />
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{systemProperties['dbDialect']}</prop>
</props>
</property>
</bean>
Thanks
Muhad
You may check the DelegatingDataSource, you could encapsulate the logic to load the datasource from JNDI within its instantiation. For your application there will be always a DataSource there, but in some cases (whenever its not able to load the DataSource from JNDI) there is no delegation.

JPA hibernate insertion not locking

We are using SpringFramework 3.2.12.RELEASE, Hibernate 4.1.6.FINAL against Oracle 11g.
We have a service managed by JPATransactionManager. The service accepts an id as primary key and creates a new entity with the id, saves it, makes an external call, then updates the entity. Under multi-thread testing with the same id, I am expecting all other threads are blocking after the first thread has done the insertion and making external call, however it is not the case. The service is annotated with #Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=false), and the two save calls are made via JpaRepository. Below is my spring configuration.
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"></property>
<property name="generateDdl" value="false"></property>
<property name="database" value="ORACLE"></property>
</bean>
<bean id="abstractEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
abstract="true">
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>
<bean id="myEntityManagerFactory" parent="abstractEntityManagerFactory">
<property name="persistenceUnitName" value="my" />
<property name="dataSource" ref="myDataSource" />
<property name="PackagesToScan" value="test.schema" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<jpa:repositories base-package="test.dao"
entity-manager-factory-ref="myEntityManagerFactory"></jpa:repositories>
Appreciate comments and help!

Spring: JMSTemplate/CachingConnectionFactory deployables unable to start automatically in weblogic

I recently changed some of my application to use the the following:
org.springframework.jndi.JndiTemplate
org.springframework.jms.connection.CachingConnectionFactory
org.springframework.jms.core.JmsTemplate
Everything is working fine and I'm able to deploy my war files and send JMS messages to the queue.
However something peculiar happens when my managed server restarts. The deployables will all go into a fail state which requires me to then manually start them up.
This started happening after the change to use caching connection factory, jndi template and jms template.
My SpringConfig file:
<!-- Service Controller begin -->
<bean id="appUtils" class="com.foo.util.AppUtil" lazy-init="true" />
<bean id="jms_jndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">#{jmsJndiFactory}</prop>
<prop key="java.naming.provider.url">#{jmsIp}</prop>
</props>
</property>
</bean>
<bean id="jmsUtils" class="com.foo.JmsUtil" >
<property name="template">
<bean class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
<property name="connectionFactory">
<bean class="org.springframework.jms.connection.CachingConnectionFactory" lazy-init="true">
<property name="sessionCacheSize" value="10" />
<property name="targetConnectionFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jms_jndiTemplate" />
<property name="jndiName" ref="jmsFactory" />
</bean>
</property>
</bean>
</property>
</bean>
</property>
<property name="destination">
<bean class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate" ref="jms_jndiTemplate" />
<property name="jndiName" ref="jmsQueue" />
</bean>
</property>
</bean>
ApplicationContext file:
<bean id="jmsQueue" class="java.lang.String" ><constructor-arg value="${jmsQueue.local}" /></bean>
<bean id="jmsFactory" class="java.lang.String" ><constructor-arg value="${jmsFactory.local}" /></bean>
<bean id="jmsJndiFactory" class="java.lang.String" ><constructor-arg value="${jmsJndiFactory.local}" /></bean>
<bean id="jmsIp" class="java.lang.String" ><constructor-arg value="${jmsIp.local}" /></bean>
applicationProperties file:
jmsQueue.local=jms/Queue
jmsFactory.local=jms/ConnectionFactory
jmsJndiFactory.local=weblogic.jndi.WLInitialContextFactory
jmsIp.local=t3://localhost:7031
Anyone has any idea as to why this might be happening? I'm using Weblogic. Any help would be greatly appreciated.
Thanks!
Edit: Forgot to mention that the error causing the failed state is
javax.naming.NameNotFoundException: Unable to resolve 'jms.Queue'. Resolved 'jms'; remaining name 'Queue'.
This is a JNDI error. The message means "I tried to find jms/Queue in the JNDI context but I only got as far as jms; there is no Queue child below".
Check the resources which you configured for the application in WebSphere.

EJB 3.0 -> Spring -> JPA (JTA as transaction manager)

I am currently working on a project that includes EJB 3.0 (stateless SB), JPA (Hibernate as the provider), JTA as transaction manager. The app server is JBoss AS 7. Spring is used for integrating EJB and JPA.
All seems to be working fine, except if there is any exception that occurs in the EJB, then the persistence unit is closed by Spring. On the subsequent request, the persistence unit is again created, which becomes time consuming and also should not happen in the ideal situation.
Below are the configuration details
persistence.xml
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<class>com.test.User</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
spring-application-context.xml
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<jee:jndi-lookup id="dataSource" jndi-name="java:/datasources/test" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"></entry>
<entry key="hibernate.current_session_context_class" value="jta" />
<entry key="hibernate.connection.release_mode" value="auto" />
</map>
</property>
<property name="persistenceUnitPostProcessors">
<list>
<bean class="com.transaction.processor.JtaPersistenceUnitPostProcessor">
<property name="jtaMode" value="true"/>
<property name="jtaDataSource" ref="dataSource"/>
</bean>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager"></property>
<property name="autodetectUserTransaction" value="false"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
The class JtaPersistenceUnitPostProcessor is responsible for setting the transaction-type as JTA and the datasource to jta-datasource.
Could anyone please provide any help on this.
Thanks in advance.
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:jboss/TransactionManager" />
<property name="userTransactionName" value="java:comp/UserTransaction" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
you didn't specify any error message . you can add these lines in your configuration file .
I see you use JTA transaction manager and use that only if you use distributed Transaction and use JNDI. JTA tran. manager listens TX happening through connection acquired from JNDI datasource. If you have datasource created in your code and is not a part of Web container but is limited inside app. container in your web server, JTA wont work.
If you want to implement Tx manager with in a single app. context go for JPA transaction manager which is very reliable.

Hibernate (JPA,JSF 2.0, Spring) switch from HyperSQL to Oracle - Configuration is being ignored

i'm currently in the process of working on a midsized Webproject, using JSF 2.0 with Spring.As IDE i use Eclipse with JBoss Tools. The Webapp is deployed to a Tomcat v7.0 Server.
I use Hibernate/JPA/C3P0/ to connect to the Database (previously HyperSQL) I now tried to switch to an Oracle DB, which i did a number of times before and it never was a problem, however now it seems, that the changed configuartion is just being ignored. When i fire up the Server, it still uses the HyperSQl Driver and the old DB, although i cleaned the workdirectory of Tomcat, removed and redeployed the Webapp (which i built from scratch of course).
The project is split in two, one webapp and one service part. The project are dependent in Eclipse. However, although all of the businesslogic is implemented in the service layer, i can just remove it and the webapp doesn't throw an error and i can start it as if nothing has changed. This tells me that it must be cached somewhere and it is not refreshed on the server...I also deleted the server, added a freshly downloaded instance - still the same thing...Does anyone have an Idea what this could be about?
Here is my service.spring.xml:
<!-- Enable processing of #PersistenceContext and #PersistenceUnit -->
<context:annotation-config/>
<!-- Enable transaction configuration with #Transactional -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Configure a c3p0 pooled data source -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="user"/>
<property name="password" value="password"/>
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
<property name="jdbcUrl" value="jdbc:oracle:thin:#dburl"/>
<property name="initialPoolSize" value="1"/>
<property name="minPoolSize" value="1"/>
<property name="maxPoolSize" value="10"/>
</bean>
<!-- Configure the JPA entity manager factory with Hibernate -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false"/>
<property name="database" value="ORACLE"/>
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="persistenceUnitName" value="mygourmet"/>
</bean>
<!-- Configure transaction manager for JPA -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
And my persistence.xml:
<persistence-unit name="mygourmet" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.use_sql_comments" value="false" />
<property name="hibernate.connection.autocommit" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
I used the exact same configuration on another project and it works like a charm...Any hints are highly appreciated, thank you guys in advance!
Problem solved - i did a mvn clean install, generated new eclipse projects and imported them back into eclipse. It seems the changes in my service module were not recognized by eclipse.

Resources