Announcement Announcement Module
Collapse
No announcement yet.
Websphere 6.1 + JPA with Hibernate : Transaction problem Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Websphere 6.1 + JPA with Hibernate : Transaction problem

    Hello all,
    I'm facing the following problem when using WAS 6.1 + JTA + JPA with Hibernate and Spring defining the transaction boundaries : for each query that Hibernate performs in a single transaction, a new connection is retrieved from the DataSource, which leads to the application hanging when the connections pool behind the DataSource reaches the maximum size.

    Here are parts of my configuration:

    I use spring webflow with flow persistence context. A webflow controller invokes a @Transactional @Service annotated facade service. That service delegates to an autowired @Repository annotated DAO that declares the EntityManager, itself annotated with @PersistenceContext. In particular, there's no EJB.

    Code:
    @Transactional @Service
    public class MyServiceImpl implements MyService {
      @Autowired MyDao dao;
      public void someMethod() {
         dao.someOtherMethod();
      }
    }
    
    @Repository
    public class MyDaoJpa implements MyDao {
      @PersistenceContext EntityManager em;
      public void someOtherMethod() {
        em.find(...);
      }
    }
    The Spring configuration declares:
    1. a DataSource: jndi lookup on a WAS datasource; that DataSource is a resource-ref in my web.xml
    2. the entityManagerFactory: LocalContainerEntityManagerFactoryBean with injected DataSource form above, and HibernateJpaVendorAdapter
    3. <tx:annotation-driven/>
    4. WAS UOW transaction manager from Spring

    persistence.xml contains the following persistence unit:
    Code:
        <persistence-unit name="persistence" transaction-type="JTA">
            <properties>
                <property name="hibernate.archive.autodetection" value="class"/>
                <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
                <property name="hibernate.current_session_context_class" value="jta"/>
                <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
                <property name="hibernate.format_sql" value="true"/>
                <property name="hibernate.show_sql" value="true"/>
                <property name="hibernate.default_batch_fetch_size" value="20"/>
                <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/>   
            </properties>
        </persistence-unit>
    The DataSource is declared with a max pool size=10.

    When I invoke the service method from the web, the SQL queries are displayed on the console, so that I can notice the following:
    • If the nb of queries is smaller than 10, all is OK
    • If the nb of sql queries is larger than 10, the application hangs until a transaction timeout occurs
    • If I change the pool to some other size, this changes the limit accordingly in the above decisions

    This suggests me that WAS, (or Hibernate) does not correctly interpret the transaction context created by Spring.

    Doing some debug, I noticed the following:
    • The UOW transaction manager is invoked in the interception chain of the service
    • Hibernate asks for a connection by invoking DataSource.getConnection() on the EMF provided Datasource

    So can anybody help me in finding what I did wrong ?

  • #2
    Here are my further thoughts, as nobody seems to have a solution:

    In my configuration, there is something missing: since the entity manager is set up outside of the scope of the JTA transaction (ie. in spring webflow), each time we enter into a transactional method, we must invoke EntityManager.joinTransaction(), in order to tell the JTA transaction manager that this entity manager's requests are to be synch by JTA. Actually, all methods are read-only (as recommended for flow-managed persistence), but I feel that if I don't join the JTA transaction, queries would be invoked without transaction context, which might cause this kink of strange behaviour.

    Thus, I added an aspect that invokes joinTransaction() on the entity manager, after the transaction has started.
    -> unfortunately, this doesn't solve my problem. Actually, I don't know whether I should do this or not. I should try the webflow forum for that point.

    I think that Hibernate's connection provider is not of the correct type: there should be some kind of transaction-aware connection provider, that is aware of the Spring transaction.

    In "pure" Hibernate (ie. with a SessionFactory configured in Spring, instead of EMF), Spring provides another implementation of the ConnectionProvider, that is set into the SessionFactory : LocalJtaDataSourceConnectionProvider. This class is activated if there is a Hibernate property called "hibernate.transaction.manager_lookup_class". In my JPA config, that property is present, but there is no such mechanism in place, that replaces the ConnectionProvider. IMO, such behavior shoud be adapted into JpaVendorAdpater implementation for Hibernate (there is such a method for that purpose : getJpaPropertyMap()).

    It is not possible to inject Spring's LocalJtaDataSourceConnectionProvider into Hibernate when a JPA EMF is setup (in opposite to a SessionFactory setup), as this class only works when a SessionFactory is created with spring factorybean (it uses a ThreadLocal variable that gets initialized during SessionFactory setup). Maybe I should adapt (rewrite) this class so that it can be used for JPA config.

    Any help would be appreciated.

    Comment

    Working...
    X