
Originally Posted by
DannielWillian
Anyway, I can't wire the entity manager factory to the transaction manager, because I'm using the JTA TM, not the JPA TM.
Note true. I'm wiring up the atomikos TM to my entity manager factory:
Here's my config for JTA (I have a separate persistence.xml that I use to allow me to use the same persistence unit in a non XA environment).
persistence.xml
Code:
<persistence-unit name="my-common-persistence" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="${hibernate.dialect}"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
Persistence base spring config (used by all applications):
Code:
<context:annotation-config/>
<tx:annotation-driven/>
<context:component-scan base-package="my.common.persistence"/>
<!-- Process @PersistenceContext to inject entity manager factory -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Translate vanilla JPA persistence exceptions into something meaningful -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<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" >
</bean>
</property>
<property name="jpaProperties" ref="jpaProperties"/>
</bean>
<!-- Dummy jpa properties that can be overridden -->
<util:properties id="jpaProperties"/>
My transaction manager config:
Code:
<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.J2eeUserTransaction">
<property name="transactionTimeout" value="300"/>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="atomikosTransactionManager,atomikosUserTransaction">
<property name="transactionManager" ref="atomikosTransactionManager"/>
<property name="userTransaction" ref="atomikosUserTransaction"/>
<!-- This is required for Spring Batch set set a custom isolation level when it runs -->
<property name="allowCustomIsolationLevels" value="true"/>
</bean>
My application specific override configuration:
Code:
<!-- Override jpa properties-->
<util:properties id="jpaProperties">
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</util:properties>
<bean id="dataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"
destroy-method="close">
<property name="uniqueResourceName" value="MyPrimary Datasource"/>
<property name="driverClassName" value="${my.database.driver}"/>
<property name="url" value="${my.database.url}"/>
<property name="user" value="${my.database.user}"/>
<property name="password" value="${my.database.password}"/>
<property name="testQuery" value="select 1"/>
<property name="maxPoolSize" value="50"/>
<property name="minPoolSize" value="20"/>
<property name="reapTimeout" value="0"></property>
</bean>
My Base DAO looks like this:
Code:
public abstract class BaseAbstractDAO<K, E> implements AbstractDAO<K, E>
{
protected Class<E> entityClass;
@PersistenceContext
protected EntityManager entityManager;
@SuppressWarnings({ "unchecked" })
public BaseAbstractDAO()
{
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[1];
}
public void setEntityManager(EntityManager manager)
{
this.entityManager = manager;
}
@Override
public void persist(E entity)
{
entityManager.persist(entity);
}
@Override
public void remove(E entity)
{
entityManager.remove(entity);
}
@Override
public E findById(K id)
{
return entityManager.find(entityClass, id);
}
@Override
public void flush()
{
entityManager.flush();
}
....
}
And one of my dao's:
Code:
@Repository("clientDao")
public class ClientDAOImpl extends BaseAbstractDAO<Long, Client> implements ClientDAO
{
....
}
The component scan and persistence annotation post processor automatically construct all my beans and inject them with the spring managed entitymanager.
My functional test base class (that all my functional tests extend from ) look like this:
Code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
@Transactional
public abstract class FunctionalTestBase
{
@Autowired
protected ClientDAO clientDao;
....
}
My actual functional tests just extend from this class and exercise the dao's:
Code:
public class ClientDaoImplFunctionalTest extends FunctionalTestBase
{
@Test
public void testCreateClient()
{
Client client = new Client();
client.setPassword("password");
client.setUsername("username");
this.clientDao.persist(client);
this.clientDao.flush();
Client retrieved = this.clientDao.findById(client.getId());
Assert.assertNotNull(retrieved);
Assert.assertEquals(client.getUsername(), retrieved.getUsername());
Assert.assertEquals(client.getPassword(), retrieved.getPassword());
}
If you had all of the above spring config in your application context file and started this test, your dao's would be constructed and injected into this class and then you could use them in functional tests.