Spring JUnit JPA Transaction not rolling back - spring

I am trying to test my DAO that uses JPA EntityManager to fetch and update entities. I have marked my unit test as Transactional and set the defaultRollback property to false. However, I don't see my transactions rolling back at the end of the test when throwing a rune time exception. The data is getting persisted in the DB. Here is my unit test code along with spring configuration. I am clearly missing something but havent been able to identify what.
Btw, the transaction is RESOURCE_LOCAL in the persistence.xml
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:spring/test-jpa.xml"})
#TestExecutionListeners(
{ DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
#TransactionConfiguration(defaultRollback=false)
#Transactional
public class JpaTests {
#PersistenceContext
EntityManage em;
#Test
public void testTransactionQueueManager() {
Object entity = em.find(1);
//code to update entity omitted.
entity = em.merge(entity);
em.flush();
throw new RuntimeException
}
}
Spring Configuration
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jpa.driverclassname}" />
<property name="url" value="${jpa.url}" />
<property name="username" value="${jpa.username}" />
<property name="password" value="${jpa.password}" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="${jpa.persistenceunitname}"/>
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
<property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.DBDictionary"/>
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

Your configuration seems fine.
There could be different reasons for the unexpected commit, maybe a datasource with autocommit mode or a non transaction compliant database (mysql with MyISAM ?)
Did you check this thread Why are transactions not rolling back when using SpringJUnit4ClassRunner/MySQL/Spring/Hibernate ?

#TransactionConfiguration(defaultRollback=false)
might be the culprit. Try defaultRollback=true, that should rollback the transaction.

Adding rollbackFor may help, it's a common pitfall.
#Transactional(rollbackFor=Exception.class)

Related

Data is not getting inserted in JPA Spring weblogic

I have following configuration in application context
<jee:jndi-lookup id="dataSource" jndi-name="MY_DS" />
<context:load-time-weaver/>
<bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="persistenceUnitName" value="pu_TEST" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="true" />
</bean>
Now my DAO Class
#Repository
public class EmployeeDAO{
#PersistenceContext
private EntityManager em;
#Transactional
public void create(Employee entity) {
LOG.error("Enitity Manager:create" + em);
em.persist(entity);
// em.flush(); if i use flush it saves
}
}
Now when I save the entity it does not say give any error but no data is updated into db.
I do not wish to use flush as entitymanager is injected by spring and should perform flush at the end automatically which is not happening. correct my understanding.
Adding facade class may be issue is there, Does Propagation.REQUIRES_NEW has anything to do here?
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void process(){
Employee e = factory.getEmployee();
employeeDao.create(e);
}
On Debug after create method call it shows employee got primary key populated that mean db call has made but at the end it is not persisted.
Please try either of the 3 :
1.Solution 1
Please call below code
em.joinTransaction();
just before
em.persistEntity(entity);
2.Solution 2
make attribute readOnly=false in #Transactional
3.Solution 3
Try manually adding bean EmployeeDAO in spring xml file
or else you can try below:
#Transactional(propagation=Propagation.REQUIRED)

Could not open JPA EntityManager for transaction using MongoDB

Trying to use Spring, Hibernate-OGM with MongoDB. However getting an issue with transactions. I know they are not supported by MongoDB however I want to use annotation #transactional so I dont have to do begin, commit.
Exception
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:430)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:420)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:257)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
DB context.xml
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="mongo-hibernate"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
persistence.xml
<persistence-unit name="mongo-hibernate" transaction-type="JTA">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<properties>
<property name="hibernate.current_session_context_class" value="thread"/>
<property name="hibernate.ogm.datastore.provider" value="mongodb"/>
<property name="hibernate.ogm.datastore.grid_dialect" value="org.hibernate.ogm.datastore.mongodb.MongoDBDialect"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
<property name="hibernate.ogm.datastore.database" value="mongodbtest"/>
<property name="hibernate.ogm.mongodb.database" value="mongodbtest"/>
<property name="hibernate.ogm.mongodb.host" value="localhost"/>
<property name="hibernate.ogm.mongodb.associations.store" value="IN_ENTITY"/>
</properties>
</persistence-unit>
</persistence>
DAO
#PersistenceContext
protected EntityManager entityManager;
#Transactional(readOnly = false)
public <E> void updateObject(E entity) {
entityManager.persist(entity);
}
any help is appreciated. Thank you
So far I moved a little further, I changed some files to:
DB context.xml
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="mongo-hibernate"/>
</bean>
<bean class="com.arjuna.ats.jta.TransactionManager" factory-method="transactionManager" id="arjunaTransactionManager"/>
<bean class="com.arjuna.ats.jta.UserTransaction" factory-method="userTransaction" id="arjunaUserTransaction"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="arjunaTransactionManager"/>
<property name="userTransaction" ref="arjunaUserTransaction"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
DAO:
#PersistenceContext
protected EntityManager entityManager;
#Transactional(readOnly = false)
public <E> void updateObject(E entity) {
Session session = entityManager.unwrap(Session.class);
org.hibernate.Transaction tx = session.getTransaction();
tx.begin();
session.persist(entity);
tx.commit();
}
This way eveything is working fine, however I would really like it to work more simplier like:
#Transactional(readOnly = false)
public <E> void updateObject(E entity) {
entityManager.persist(entity);
}
Any suggestions?
Yup, I have a suggestion: Read the docs. ;)
"MongoDB does not support transaction."

EntityManager.flush() not flushing (JPA2 (OpenJPA), EJB3, Spring3, Websphere 7)

I'm facing a problem in my project: entityManager.flush() is not doing anything, and the flushing is only being done right before commit, when exiting the EJB.
My project runs on WebSphere 7.
I'm using JPA2 through OpenJPA.
I'm using Spring for Autowiring.
I'm using Container Managed Transactions.
Relevant code snippets below
persistence.xml
<persistence-unit name="persistenceUnit" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<properties>
<property name="openjpa.TransactionMode" value="managed" />
<property name="openjpa.ConnectionFactoryMode" value="managed" />
<property name="openjpa.DynamicEnhancementAgent" value="true" />
<property name="openjpa.jdbc.DBDictionary" value="StoreCharsAsNumbers=false" />
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
applicationContext.xml
<!-- Configure a JPA vendor adapter -->
<bean id="openJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
</bean>
<!-- Entity Manager -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myappDS"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="openJpaVendorAdapter" />
</bean>
EJB3 Bean
#Stateless(name="JPABaseEntityServiceBean")
#Configurable
public class JPABaseEntityServiceBean implements JPABaseEntityService {
Logger logger = LoggerFactory.getLogger(JPABaseEntityServiceBean.class);
#Autowired
JPABaseEntityDao jpaBaseEntityDao;
public JPABaseEntity persist(JPABaseEntity jpaBaseEntity) {
return jpaBaseEntityDao.persist(jpaBaseEntity);
}
DAO:
#Repository
public class JPABaseEntityDao implements BaseEntityDao {
#PersistenceContext
transient EntityManager entityManager;
public JPABaseEntity persist(JPABaseEntity jpaBaseEntity) {
Date now = new Date();
jpaBaseEntity.setCreatedBy(TO_DO_ME);
jpaBaseEntity.setUpdatedBy(TO_DO_ME);
jpaBaseEntity.setUpdatedOn(now);
jpaBaseEntity.setCreatedOn(now);
entityManager.persist(jpaBaseEntity);
entityManager.flush();
return jpaBaseEntity;
}
The "INSERT" is being done only when leaving the EJB, meaning the entityManager.flush() inside the DAO is not working
Ok, resolved in a way
Seems like the problem was that the Entity Manager was not getting the Transaction from WebSphere (probably because the Entity Manager was being injected by Spring, I haven't investigated that deeply)
So what I did is make Spring control the transaction in the EntityManager:
1. added <tx:annotation-driven/> and <tx:jta-transaction-manager/> to applicationContext.xml
2. annotated the DAO methods with #Transactional
The overall transaction is still handled by the EJB, meaning it's still using CMT and JTA from WebSphere
I had a ton of problems in the way because of dependency hell (the one that got me the most was hibernate-core including JBoss's javax.transaction implementation, grr), but other than that everything seems to be working smoothly

Spring + Hibernate + JPA + 2 databases. persist silently fails to commits with #Transactional annotation

My setup is Spring MVC 3.1, Hibernate 4.1 with two databases.
My service methods seem to work fine for reads (for both dbs). But the persist fails to insert the data in the db - and no exception in the logs at all. Looking at the sql output of hibernate it looks like it did retrieve the newly generated id but then never did the insert - if it did it doesn't show in the db nor was an insert logged in the log file. In the db I can see the sequence number is incremented but no data was inserted. I couldn't figure out what is wrong with my config. Hopefully someone has an idea.
Below are the relevant pieces from config file
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
</bean>
<bean id="mgrFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
<property name="packagesToScan" value="xxx.yyy" />
<property name="persistenceUnitName" value="puOne"/>
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
</property>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="txMgr"/>
<bean id="txMgr"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="mgrFactory">
</bean>
This works fine as it is. What I want to do now is add the ability to use another database. So I added another data source, entity manager factory and transaction manager
<bean id="dataSourceTwo" class="org.apache.commons.dbcp.BasicDataSource">
</bean>
<bean id="mgrFactoryTwo"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSourceTwo">
<property name="packagesToScan" value="xxx.zzz" />
<property name="persistenceUnitName" value="puTwo"/>
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
</property>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="txMgrTwo"/>
<bean id="txMgrTwo"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="mgrFactoryTwo">
</bean>
I also made sure that the two respective base DAOs annotate their entity manager's with the unit name like
#PersistenceContext(unitName = "puOne")
protected EntityManager entityManager;
The last thing I did was to add the transaction manager names inside my #Transactional annotations inside my services like
#Override
#Transactional(value="txMgrTwo" propagation = Propagation.REQUIRED)
public boolean create(User user) {
userDao.persist(user);
}

JPA Detected reentrant flush

I have little problem with openjpa implementation of jpa with spring 2.5. My dao method:
#Transactional
public User getUserByName(final String name) {
return (User) getEntityManager().createQuery("select u from User as u where u.name = :name").setParameter("name", name).getSingleResult();
}
returns org.springframework.dao.InvalidDataAccessApiUsageException:
org.apache.openjpa.persistence.InvalidStateException: Detected reentrant flush. Make sure your flush-time instance callback methods or event listeners do not invoke any operations that require the in-progress flush to complete.
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:1904)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1679)
at org.apache.openjpa.kernel.QueryImpl.isInMemory(QueryImpl.java:956)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:838)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:779)
at org.apache.openjpa.kernel.DelegatingQuery.execute(DelegatingQuery.java:525)
at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:254)
at org.apache.openjpa.persistence.QueryImpl.getSingleResult(QueryImpl.java:317)
at org.jpa.dao.UserDao.getUserByName(UserDao.java:71)
//EDIT
EntityManager settings:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
<property name="showSql" value="false"/>
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.OpenJpaDialect"/>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
How do you obtain an EntityManage? In dao class:
#PersistenceContext(type = PersistenceContextType.EXTENDED)
protected EntityManager entityManager;
What is wrong? Any idea?
I have the same problem, and modify my entity for the primary key:
#Id
//#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
maybe can help you.

Resources