Could not open JPA EntityManager for transaction in Spring Test - spring

I have a java project using Spring 3.0 , JPA 2.0 with MyEclipse IDE
Trying to convert some basic dao integration tests to spring and have run into a few issues. Here's my setup:
LevelDAO
public class LevelDAO extends JpaDaoSupport implements ILevelDAO
{
public void save(Level entity) {
logger.info("saving Level instance");
try {
getJpaTemplate().persist(entity);
logger.info("save successful");
} catch (RuntimeException re) {
logger.error("save failed", re);
throw re;
}
}
}
Unit Test
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "classpath:applicationContext.xml"})
#TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
public class LevelDaoImplTests {
LevelDAO levelDao;
#Test
public void shouldSaveNewLevels() {
levelDao= new LevelDAO();
Level l = new Level();
l.setName = "test";
levelDao.save(l);
}
}
Persistence.Xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="t1" transaction-type="RESOURCE_LOCAL">
<provider>
org.eclipse.persistence.jpa.PersistenceProvider
</provider>
<class>com.nlg.model.Level</class>
<properties>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://myserver.rds.amazonaws.com:3306/" />
<property name="javax.persistence.jdbc.user" value="myuser" />
<property name="javax.persistence.jdbc.password" value="mypass" />
</properties>
</persistence-unit>
applicationContext.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="t1" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean
id="LevelDAO" class="com.nlg.model.LevelDAO">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
</bean>
At first I recieved this
Value '2.0' of attribute 'version' of element 'persistence' is not valid
So reading another post which suggested changing this to "1.0"
and now recieve
java.lang.IllegalStateException: Failed to load ApplicationContext
That issue was resolved with the < provider > tag however hasn't fixed my issue:
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is Exception [EclipseLink-4021] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null].
My concern is that by downgrading the version no. to "1.0" that I'm also overlooking the issue of compatibility within this stack. I have non-spring versions of these tests working, so any ideas on where I've gone wrong appreciated.
Thanks

Unable to acquire a connection from driver [null], user [null] and URL [null]
These are JPA 2.0 properties:
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://myserver.rds.amazonaws.com:3306/" />
<property name="javax.persistence.jdbc.user" value="myuser" />
<property name="javax.persistence.jdbc.password" value="mypass" />
So if you switched back to 1.0, you'd probably want:
<property name="eclipelink.jdbc.url" value="jdbc:mysql://myserver.rds.amazonaws.com:3306/"/>
<property name="eclipelink.jdbc.user" value="myuser"/>
<property name="eclipelink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="eclipelink.jdbc.password" value="mypass"/>
But then I would recommend to solve "that other problem" and stay with 2.0
Here is an example of JPA 2.0 over EclipseLink that works ( notice persistence version="2.0" ):
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="eclipselinktest" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- list all classes -->
<class>com.codesmuggler.model.User</class>
<properties>
<!-- some properties needed by persistence provider:
- driver
- db url
- db user name
- db user password -->
<property name="javax.persistence.target-database" value="PostgreSQL"/>
<property name="javax.persistence.logging.level" value="INFO"/>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/testdb"/>
<property name="javax.persistence.jdbc.user" value="testuser"/>
<property name="javax.persistence.jdbc.password" value="testpassword"/>
<!-- for testing purpose every time application is launched drop and create tables
in production mode - this line should be removed or commented out
-->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
</properties>
</persistence-unit>
</persistence>
Take a look at the example in full

Related

Spring data + JTA transactions + JBoss7

I use JBoss7 and EclipseLink over MS SQL db. I'm trying to add Spring Data to my project, but everything fails when repository method implementation is generated.
It tries to join current transaction and fails with "ARJUNA016083: Can't register synchronization because the transaction is in aborted state".
My Spring config:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" destroy-method="destroy">
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="persistenceUnitName" value="${module.persistence-unit-name}" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="transactionManager" />
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" />
</bean>
<bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="transactionManager" />
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" />
</bean>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="myUnit" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:jboss/datasources/mixx</jta-data-source>
<class>package.MyEntity</class>
<shared-cache-mode>NONE</shared-cache-mode>
<validation-mode>NONE</validation-mode>
<properties>
<property name="eclipselink.target-server" value="JBoss" />
<property name="eclipselink.deploy-on-startup" value="true" />
<property name="eclipselink.weaving" value="static" />
<property name="eclipselink.exception-handler" value="package.persistence.EclipseLinkExceptionHandler" />
<property name="eclipselink.session.customizer" value="package.persistence.EclipseLinkSessionCustomizer" />
</properties>
</persistence-unit>
</persistence>
It fails exactly in JTATransactionWrapper.registerIfRequired(UnitOfWorkImpl uow) when it tries to call (line 136):
((Transaction)txn).registerSynchronization(new Synchronization() {
public void beforeCompletion() {}
public void afterCompletion(int status) {
//let the wrapper know the listener is no longer registered to an active transaction
isJoined = false;
}
});
Does Spring Data work fine with EclipseLink and JTA? Is there a chance to use it in my project?

Spring 4 Jpa Hibernate - Can't Inject EntityManager

I guess I have the same problem as many people, but unsolved on most of cases. I will try anyway, hope you guys can help me.
The problem is in my repository when I try to inject que Entity Manager using #persistenceContext annotation and always comes null.
The stack:
Spring 4.2.5
Spring Data 1.10.1
Hibernate 5
This is my xml for Sprint data:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="conquerPU"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="com.conquer.module" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/conquer" />
<property name="username" value="app" />
<property name="password" value="10203040" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<jpa:repositories base-package="com.conquer.module" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
This is my application context.xml
<context:annotation-config/>
<context:component-scan base-package="com">
<context:include-filter type="aspectj" expression="com.*" />
</context:component-scan>
<!-- a HTTP Session-scoped bean exposed as a proxy -->
<bean id="sessionData" class="com.conquer.common.SessionData" scope="session">
<aop:scoped-proxy/>
</bean>
<!--Hibernate persistence interceptor - Used for audit data-->
<bean id="hibernateInterceptor" class="com.conquer.module.security.interceptor.HibernateInterceptor"></bean>
<!--Application Context to be used anywhere-->
<bean id="applicationContextProvder" class="com.conquer.common.ApplicationContextProvider"/>
<!-- SpringMVC -->
<import resource="spring-mvc.xml"/>
<!-- SpringData -->
<import resource="spring-jpa.xml"/>
<!-- SpringSecurity -->
<import resource="spring-security.xml"/>
This is my repository
#Repository
#Transactional
public class BaseRepositoryImpl<T, ID extends Serializable> implements BaseRepository<T, ID> {
#PersistenceContext
public EntityManager em;
public RepositoryFactorySupport baseFactory;
public BaseRepository<T, ID> baseRepository;
public BaseRepositoryImpl() {
System.out.println("BASE REPOSITORY RUNNING...");
this.baseFactory = new JpaRepositoryFactory(em);
this.baseRepository = this.baseFactory.getRepository(BaseRepository.class);
}
// Implementations here ...
}
This is my persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="conquerPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect"/>
<property name = "hibernate.show_sql" value = "true" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.ejb.interceptor" value="com.conquer.module.security.interceptor.HibernateInterceptor"/>
</properties>
</persistence-unit>
</persistence>
Although this question is quite old, we faced with this problem as well and solved it by adding this bean to our application context:
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
The documentation for context:annotation-config clearly states that this should not be necessary, but in our case it was (albeit we use Spring 4.2 inside Eclipse Virgo 3.7 with Gemini Blueprint, so this setup is probably far from mainstream).

database not updated using JPA and spring when new entries are made

I am configuring a simple JPA application using Spring framework.
My goal is to populate the db with data during JUnit Test runs. I understand this is not ideal. But I want it for different purposes.
Here is my persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="tothought-tutorial-test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" /> -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
test-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd">
<!-- Database -->
<!-- <jdbc:embedded-database id="datasource" type="H2"></jdbc:embedded-database> -->
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/to_thought_tutorial" />
<property name="username" value="demo" />
<property name="password" value="demo" />
</bean>
<!-- Entity Manager -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="persistenceUnitName" value="tothought-tutorial-test" />
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Jpa Repositories -->
<jpa:repositories base-package="com.cloudfoundry.tothought.repositories"></jpa:repositories>
</beans>
Here is junitTest class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="classpath:META-INF/test-context.xml")
#Transactional
public class PostPartRepositoryTest {
#Autowired
PostPartRepository repository;
#Test
public void test() {
PostPart postPart = new PostPart();
String body = "Hello";
postPart.setBody(body);
repository.save(postPart);
PostPart dbPostPart = repository.findOne(postPart.getPostPartId());
assertNotNull(dbPostPart);
assertEquals(body, dbPostPart.getBody());
}
#Test
public void insertTest(){
Post post = new Post();
post.setPostDate(new Date());
post.setTitle("First Post");
PostPart postPart = new PostPart();
String body = "Hello";
postPart.setBody(body);
postPart.setPost(post);
repository.save(postPart);
PostPart dbPostPart = repository.findOne(postPart.getPostPartId());
assertNotNull(dbPostPart);
assertNotNull(dbPostPart.getPost());
assertEquals(body, dbPostPart.getBody());
}
}
Both the test passes. But I do not see any entry in tables, although tables are created the first time.
You won't see any entries because you are running the test with #Transactional using the SpringJUnit4ClassRunner. The default for running tests with #Transactional is for any database changes to be automatically rolled back once the test is finished. For more information see this question here
The order in which these things happen is as follows:
Test starts, setup scripts are run, which creates your tables.
Tests start running in transactional context.
Tests finish running, and any database changes made during your test, are automatically rolled back, leaving the database in the state it was in before the tests ran.
You can change this default behaviour you can use #TransactionConfiguration(defaultRollback=false) at the top of the class. However this is bad practice because unit tests should not depend on each other and shouldn't be permanently modifying application state. Also, if you are depending on one test to set something in the environment and use it in the next test, there is no guarantee which order the tests are executed by test runner.

Exception after DAO-operation using WebSphere-8 / Spring 4 / Hibernate 4.3

My WebSphere 8 driven portlet uses Spring 4 and Hibernate 4.3 over JPA. I have a JTA data source. This is my setup:
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
>
<persistence-unit name="myUnit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/mydb</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform" />
<property name="hibernate.transaction.factory_class" value="org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
</properties>
</persistence-unit>
</persistence>
my-portlet.xml
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.DB2Dialect" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
When my DAO-method is called, an exceptions are thrown:
00000090 RegisteredSyn E WTRN0074E: Exception caught from before_completion synchronization operation: java.lang.IncompatibleClassChangeError
at com.ibm.ws.uow.ComponentContextSynchronizationWrapper.beforeCompletion(ComponentContextSynchronizationWrapper.java:65)
and
(... servlet and portlet specific exceptions ...)
Caused by: org.springframework.transaction.TransactionSystemException: UOWManager transaction processing failed; nested exception is com.ibm.wsspi.uow.UOWException: javax.transaction.RollbackException
(...)
Caused by: java.lang.IncompatibleClassChangeError
This is my DAO-class:
#Repository("myDao")
#SuppressWarnings("unchecked")
public class HibernateMyEntityDao implements MyEntityDao
{
#PersistenceContext(unitName = "myUnit")
private EntityManager entityManager;
public Session getSession()
{
return entityManager.unwrap(Session.class);
}
#Transactional
public List<MyEntity> findActive()
{
Calendar date = Calendar.getInstance();
Criteria crit = getSession().createCriteria(MyEntity.class);
crit.setFirstResult(0);
crit.setFetchSize(10);
crit.add(Restrictions.le("start", date));
crit.add(Restrictions.gt("end", date));
return crit.list();
}
}
What am I doing wrong here?
A IncompatibleClassChangeError normally indicates that the dependency versions are incorrect. You can read more about it here and here.
It is probable that the combination of websphere 8, spring 4 and hibernate 4.3 are not compatible with each other. My guess is on hibernate 4.3 and websphere 8 not being compatible. Did you try with slightly older versions of spring and hibernate?

JBoss AS7 + Oracle 11g + Spring 3.1 + JPA 2 - Multiple DSs, PUs, EMs, TMs

I'm building an application that needs CRUD operations on two separate databases. The transactions are applied to one database or the other (never both...so no need for JTA is my understanding). My setup is pretty close to what is found here: Multiple database with Spring+Hibernate+JPA
The problem: My server (JBoss AS7) starts up fine. The application reads from both datasources, say DS1 and DS2, BUT it can only manipulate data from DS1. I can see sequences (Oracle 11g) being updated but no table updates. There are no errors/exceptions thrown. I suspect one of my transaction managers isn't committing.
Below is a list of technologies used and configuration settings...
Tech Stack
JBoss AS7
Oracle 11g
Spring 3.1
JPA 2
Hibernate 4.1
persistence-ds1.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="pu1">
<class>com.somepackage.EntityA</class>
<class>com.somepackage.EntityB</class>
<class>com.somepackage.EntityC</class>
<validation-mode>CALLBACK</validation-mode>
<properties>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
</properties>
</persistence-unit>
</persistence>
persistence-ds2.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="pu2">
<class>com.somepackage.EntityD</class>
<class>com.somepackage.EntityE</class>
<class>com.somepackage.EntityF</class>
<validation-mode>CALLBACK</validation-mode>
<properties>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
</properties>
</persistence-unit>
</persistence>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="ds1" jndi-name="java:jboss/datasources/DS1"
expected-type="javax.sql.DataSource" />
<jee:jndi-lookup id="ds2" jndi-name="java:jboss/datasources/DS2"
expected-type="javax.sql.DataSource" />
<bean id="em1" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="emf1" />
<property name="persistenceUnitName" value="pu1" />
</bean>
<bean id="em2" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="emf2" />
<property name="persistenceUnitName" value="pu2" />
</bean>
<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-ds1.xml"/>
<property name="dataSource" ref="ds1" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-ds2.xml"/>
<property name="dataSource" ref="ds2" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<tx:annotation-driven transaction-manager="txm1" />
<tx:annotation-driven transaction-manager="txm2" />
<bean id="txm1" class="org.springframework.orm.jpa.JpaTransactionManager">
<qualifier value="txMgr1"/>
<property name="entityManagerFactory" ref="emf1" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="txm2" class="org.springframework.orm.jpa.JpaTransactionManager">
<qualifier value="txMgr2"/>
<property name="entityManagerFactory" ref="emf2" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
</beans>
In my DAOs, I reference the transaction managers at the class-level as follows.
#Transactional("txm1")
public class DAO1 { ... }
#Transactional("txm2")
public class DAO2 { ... }
I resolved my issue!
In my applicationContext.xml, I removed the following.
<tx:annotation-driven transaction-manager="txm1" />
<tx:annotation-driven transaction-manager="txm2" />
And used the following instead.
<tx:annotation-driven />
But here's what I believe was the kicker (main problem). In my DAOs, I was assigning the two transaction managers at the class-level. But then I was overriding them with the way I was declaring my methods.
#Transactional(readOnly = false, value = "txm1")
public abstract class AbstractJpaDAO1<T extends Serializable> {
...
#Transactional(readOnly = true)
public T findById(final Long id) {...}
#Transactional
public boolean insert(final T entity) {...}
As you can see, the #Transaction annotations on the methods were overriding the the one at the class-level. And because there was no transaction manager specified on the methods, Spring defaulted to "transactionManager", which I didn't (and still don't) have declared in my applicaitonContext.xml. So, it was trying to commit using a transaction manager that didn't exist.
For the resolution, I just removed the #Transitional annotations on the methods, and kept the one at the class-level.
#Transactional(readOnly = false, value = "txm1")
public abstract class AbstractJpaDAO1<T extends Serializable> {
...
public T findById(final Long id) {...}
public boolean insert(final T entity) {...}
Now everything works! I can read/write to two separate databases.

Resources