I'm running an application with the following components:
- Oracle 9i
- WAS 6.1.0.23 with WS and EJB3 features pack
- JPA with Hibernate 3.3.2.GA as provider (with Hibernate-EntityManager 3.4.0)
- Spring transaction manager for WAS : UowTransactionManager (spring 2.5.6)
- Spring webflow with flow-managed persistence (2.0.8), i.e. the entity manager is serialized into the http session, and restored on each request.
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:
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>
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>
Service
@Transactional(readOnly=true) @Service public class MyServiceImpl implements MyService { @Autowired MyDao dao; public void getSomething() { dao.findSomething(); } }
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:
- The UOW transaction manager is correctly invoked in the interception chain of the service, which suggests that a transaction is active
- Hibernate asks for a connection by invoking DataSource.getConnection() on the raw DataSource that is injected into the EMF; The strategy for getting a connection is from Hibernate's InjectedDataSourceConnectionProvider, and this class references the WAS DataSource (not a proxy that is aware of an active transaction, or such).
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.