users@glassfish.java.net

CMT, JPA, Spring

From: <glassfish_at_javadesktop.org>
Date: Thu, 15 Jul 2010 11:12:55 PDT

I'm running in GlassFish 3.0.1 with the bundled Eclipse Persistence Services - 2.0.1.v20100213-r6600 for JPA and I'm using Spring. I've chosen to use a Dao pattern for all data access through the EntityManager. My Dao classes are managed by Spring and I wrap the EntityManager with Spring's JpaTemplate to get Exception translation. My application consists of an EJB that is defied as a WebService.

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Interceptors(SpringBeanAutowiringInterceptor.class)
@WebService(...)
@Service
public class MyWebService {...}

I'm using the SpringBeanAutowiringInterceptor to allow for the assignment of my Service classes to the EJB. My Service classes contain references to my Dao classes.

My Dao classes look as follows:
@Repository
@Transactional(propagation = Propagation.REQUIRED)
public class SomeDaoImpl {
        @PersistenceContext(name = "my-pu")
        private EntityManager entityManager;
}

My Service class looks as follows:
@Service("SomeService")
@Transactional(propagation = Propagation.REQUIRED)
public class SomeServiceImpl implements SomeService {
        
    @Autowired
    private SomeDao someDao;
    ....
}

Seeing as my Dao classes need the EntityManager and Spring will inject it, I configured my web.xml with a reference to the EntityManager.
    <persistence-unit-ref>
        <persistence-unit-ref-name>persistence/my-pu</persistence-unit-ref-name>
        <persistence-unit-name>my-pu</persistence-unit-name>
    </persistence-unit-ref>

And Spring is configured as follows:

    <context:annotation-config />
    <tx:annotation-driven />
    <tx:jta-transaction-manager/>
    <jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/my-pu"/>


My persistence.xml is configured as follows:
  <persistence-unit name="my-pu" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/myDataSource</jta-data-source>
    <shared-cache-mode>ALL</shared-cache-mode>
      <property name="eclipselink.target-server" value="SunAS9"/>

The issue that I am experiencing has to do with the transaction. I can see the container starting the transaction before the invocation of the WebService. This is apparent in the log file. (txId=4) As the execution continues and my services are invoked with the WebService class, I can see Spring transaction management locating an existing transaction and participating in it. (txId=4)

FINE: JTA TransactionSynchronizationRegistry found at default JNDI location [java:comp/TransactionSynchronizationRegistry

But it appears that two, Spring and GlassFish, are doing two different things with the TransactionManager.

While spinning through a loop, and I perform a search for a given entity for a specific Id, I get two different objects for the same Id. This should not happen as I have caching enabled in EclipseLink and so long as the transaction is active I should always be returned the same object.

The other issue is when the WebService method returns and GlassFish performs a commit on the transaction, EclipseLink begins to persist all entities. If an exception occurs during this persistence the entire transaction should be rolled back. However, that is not happening. I can see that GlassFish is performing a rollback on the transaction but when all is said an done, the newly inserted data is in the database. Only the data that caused the exception is not.

I can't seem to get any help on the Spring forum pertaining to this type of issue. It's been asked by others as well but does not seem to have any answers associated to the questions. So can Spring's transaction management, which is using the TransactionSynchronizationRegistry, participate with a container managed transaction of an EJB?


Thanks so much for taking the time to help...
[Message sent by forum member 'fericit_bostan']

http://forums.java.net/jive/thread.jspa?messageID=477754