CDI transaction management

Atul picture Atul · Jul 6, 2015 · Viewed 9.5k times · Source

I am working on a migration project from JBoss Seam to CDI. Following is the technology stack :

1)WildFly 8.2.0 (CDI 1.2 with Weld as CDI provider)

2)JSF 2.2

3)JPA 2

We are using container managed JTA transactions :

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
   xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/persistence
        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
   <persistence-unit name="surveillenace" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>java:/surveillenaceDS</jta-data-source> 


    <!-- other configurations not shown here -->

</persistence>

and using @PersistenceContext annotation to inject EntityManager into DAO object.

We are using @Transaction annotation for container managed transactions.

My questions/Understanding are below .

Can anybody confirm this since this is relatively a new area for me.

1)As I understand , CDI provides support for CMT through @Transaction interceptor. Which is the class / dependency actually implements this interceptor ? Which artifacts we need to import for this in pom.xml ?

2)Since CMT is used , we don't need to demarcate any transaction and container will manage it. We only need to use EntityManager API to persist changes in Db. Is this understanding correct ?

 @Transactional
    public String finishOperation() {
        log.debug("in finishOperation() ") ;
        try {   
        //operations done on managed entities 
        //no transaction demarcation code is required here 
        dao.getEntityManager.commit();      

    }catch(Throwable xx){
    }
    }

3)Consider below trivial scenario executed using above configuration:

Component1.somemethod() - runs inside transaction and persists an entity (e.g: User) and commits transaction. After this , Component2 is invoked as below :
Component2.somemethod() - runs inside the transation but the entity User doesn't seem to in managed state that is em.contains(user) returns false. I have to merge this entity again to make it managed or reload from persistent store again

Since Seam uses conversation-scoped entity manager , all entity instances remain in managed state (inside persistent-context) even when any component commits a transaction and another component is invoked there after. But in CDI case , as I understand this is happening due to "transaction scoped entity manager". Once a transaction commits , all entity instances become detached. How can we achieve same effect as Seam using CDI ?

Answer

Antoine Sabot-Durand picture Antoine Sabot-Durand · Jul 8, 2015

To answer your question and clarify previous answer which was only target to Java EE 6 / CDI 1.0 while you are working with Java EE 7 / CDI 1.2

  1. CDI doesn't implement transaction but JTA spec does. Yes JTA defines the interceptor binding @Transactional and implementation have to provide matching interceptors. As you are under WildFly, the answer to your question is in JBoss JTA implementation: Narayana. You'll find the @Transactional(Required) interceptor here. Others are in the same package.
  2. Yes, your understanding is correct.
  3. Extended Persistence context are only injectable in EJB Stateful session bean. In Java EE 7 you can try to use the new JPA 2.1 Unsyncrhonized mode (not tested in CDI).