Gaetan
Gaetan

Reputation: 2826

WAS 6.1, JPA with JTA, Hibernate, Spring : data retrieval problem

I'm running an application with the following components:

In each request going from the web controller to the service layer (annotated with Spring's @Transactional), I have noticed that for each SQL query that Hibernate performs during the service invocation inside the transaction, a new DataSource connnection is requested from the jndi DataSource by Hibernate's ConnectionProvider, until the DataSource runs out of free connections and eventually hangs.

Here are parts of the configuration:

  1. Spring:

    <tx:annotation-driven />
    <context:component-scan base-package="org.home.myapp" />
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/DS" resource-ref="true"/>
    <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
    <bean id="EMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      </property>
    </bean>
    
  2. persistence.xml

    <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>
    
  3. Service

    @Transactional(readOnly=true) @Service
    public class MyServiceImpl implements MyService {
      @Autowired MyDao dao;
      public void getSomething() {
        dao.findSomething();
      }
    }
    
  4. DAO

    @Repository
    public class MyDaoJap implements MyDao {
      @PersistenceContext EntityManager em;
      public void findSomething() {
        em.find(...);
      }
    }
    

Note the transaction is read-only, which is normal for flow-persistence: only the last transition (with commit=true) invokes a non-readOnly transactional method. Turning on the readOnly flag automatically turns Hibernate flush mode to MANUAL.

While doing some debug, I noticed the following:

I guess the problem is in this second point, but I can't find an error in my configuration. Can anybody help ?

Thanks for your help.

Upvotes: 6

Views: 4583

Answers (2)

Michael Pralow
Michael Pralow

Reputation: 6630

some wild guesses from our config

  • hibernate prop - hibernate.connection.release_mode=after_statement
  • web.xml resource ref datasource config - <res-sharing-scope>Shareable</res-sharing-scope>
  • spring sessionFactory config - useTransactionAwareDataSource="true"

it even might be a configuration issue inside was

Upvotes: 2

Michael Wiles
Michael Wiles

Reputation: 21194

I think (and hope) that your problems stems from the fact that by using the dataSource property it defaults to a "nonJtaDataSource". The default (simple) configuration is really optimised for lower grade transactional systems (tomcat/SE) and not the more hardcore stack that you're using.

You're going to need to configure the entity manager factory to have a jta datasource. The way that I did this is to create my own JtaPersistenceUnitPostProcessor where I could set this up.

By doing it this way I was able to set the EMF to use a JtaDatasource, I'm not sure if there is a better way of doing this. You could simply, as a POC add the jta datasource reference to your persistence.xml.

Upvotes: 0

Related Questions