Saturday, October 27, 2007

Integrating Spring, Hibernate and EJB 2.x

How to configure Hibernate Session Factory in a Spring application context used in an EJB 2.x stateless session bean?

Most of the examples found on the internet about Hibernate and Spring integration are targeted at web applications. How to configure Hibernate and Spring inside an EJB 2.x stateless session bean is rarely mentioned, and it is not as simple and straightforward as many assume.

The most important issue of the integration is around the management of JDBC connections:
In EJB 2.x, JDBC connections are managed by the data source registered with JNDI on the application server:

  • Applications are not expected to hold on JDBC connections after each use, that is, applications should aggressively release JDBC connections, preferrably after each statement.

  • Applications can acquire JDBC connections multiple times during the execution of one EJB invocation. The application server may return the same JDBC connection, or it may return different JDBC connections, but it assures that all JDBC connections returned are registered within the same Container Managed Transaction.


When database is accessed outside EJB 2.x, such as in a web application running in Tomcat, the application itself is responsible for transaction demarcation. When using a local database transaction, the application code must ensure that the same JDBC connection be used in all database access within the same transaction. Because database access occurs in multiple classes that collaborate to complete a transaction, it is very unwieldy for applications to pass around the JDBC connection in order to re-use the same JDBC connection.

Enter Spring and Hibernate.

Spring guarantees the same JDBC connection is reused, provided the same Spring-managed data source is re-used. The magic happens when a JDBC connection is retrieved for the first time from a Spring-managed data source, Spring binds the JDBC connection to the current execution thread. When another JDBC connection is requested within the same transaction from the Spring-managed data source, Spring returns the thread-bound JDBC connection. When the transaction ends, Spring invokes the commit() or rollback() method of the thread-bound JDBC connection and then unbinds it from the thread.

Hibernate 3.x employs similar technique. By default, a Hibernate session is bound to the thread and returned whenever SessionFactory.getCurrentSession() is invoked within the same transaction. The same JDBC connection is used for all JDBC operations initiated by the same Hibernate session. It is possible to specify other current session context class other than the default thread local context since Hibernate 3.1.

As can be seen from the above discussion, Spring and Hibernate by default re-use the same thread-bound JDBC connection. This setting does not go well with the aggressive connection release mode expected by EJB 2.x. Therefore, non-default settings must be configured for both Spring and Hibernate for Spring and Hibernate combination to be integrated within EJB 2.x.

Below is the recommended configuration. The reasons behind this configuration are explained following the configuration.

<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/datasource" resource-ref="true"/>

<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- default value is "false"
<property name="useTransactionAwareDataSource" value="false"/>
-->
<property name="exposeTransactionAwareSessionFactory" value="false"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SomeDialect</prop>
<!--
WARNING! 'hibernate.connection.release_mode' must not be set to
'after_statement'. Otherwise, it will be overriden with 'after_transaction'
by Hibernate because Spring's LocalConnectionProvider does not support
aggressive connection release.
-->
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
</props>
</property>
<property name="mappingResources">
<list>...</list>
</property>
</bean>


The reasons behind this configuration are explained below. It is recommended to have your IDE opened and source code of Spring and Hibernate 3.1 or above ready.

Spring uses LocalSessionFactoryBean, which is a subclass of AbstractSessionFactoryBean, to configure a Hibernate session factory.

There are lots of javadoc to read for each bean property that can be set for a LocalSessionFactoryBean. It's better off to read the buildSessionFactory() method to understand what each property value does in the build time.

Note that the above configuration has two parts for LocalSessionFactoryBean, the 'normal' Spring bean properties, such as 'dataSource', and the 'hibernateProperties' that takes a java.util.Properties value. The 'normal' properties are used to configure the default settings, which can be overriden by the 'hibernateProperties'.

As a side note, we don't set the 'jtaTransactionManager' property. Note that the class for this property is javax.transaction.TransactionManager, not the JtaTransactionManager that implements Spring's PlatformTransactionManager. In order to set this property, we need to know the JNDI name that the target application server binds its JTA transaction manager. The benefit of setting this property would be that we don't need to configure Hibernate's 'hibernate.transaction.manager_lookup_class' and 'hibernate.transaction.factory_class' properties. We concluded that this benefit could not justify explicitly specifying the application server specific JNDI name for transaction manager. We would rather set those two properties in Hibernate configuration.

If 'jtaTransactionManager' property is not set, Spring automatically set the 'hibernate.connection.release_mode' property to 'on_close'. Because we are running Hibernate inside an EJB 2.x, we must set this property to other value in the overriding 'hibernateProperties'.

The 'exposeTransactionAwareSessionFactory' property has a default value of true. If set to true, Spring will set the 'hibernate.current_session_context_class' property to Spring's own thread-bound implementation, which must be overriden by a value of 'jta' in the 'hibernateProperties'.

The 'useTransactionAwareDataSource' property must be left to the default 'false' value. Otherwise, Spring will wrap the data source with a TransactionAwareDataSourceProxy, which will effectively re-use the same JDBC transaction within the same transaction, even if Hibernate aggressively releases connections.

It must be pointed out that when 'useTransactionAwareDataSource' is set to false, Spring will supply LocalDataSourceConnectionProvider as the implementation of Hibernate's ConnectionProvider. LocalDataSourceConnectionProvider informs Hibernate that it does not support aggressive release of connection. However, in Hibernate's SettingsFactory, if the ConnectionProvider does not support aggressive release of connections and connection release mode is set to 'after_statement', the connection release mode will be automatically rectified to 'after_transaction', which effectively re-uses the same JDBC transaction for the whole transaction. A warning message "Overriding release mode as connection provider does not support 'after_statement'" is logged. Therefore, the connection release mode in the 'hibernateProperties' must be set to 'auto' instead of 'after_statement'. When the transaction factory is set to 'CMTTransactionFactory', the default connection release mode is 'after_statement', which is precisely what we want.

The other property settings are self-explanatory:

  • 'hibernate.current_session_context_class' should be set to 'jta'.

  • 'hibernate.transaction.manager_lookup_class' should be set the a class mapped to the target application server.

  • 'hibernate.transaction.factory_class' should be set to 'org.hibernate.transaction.CMTTransactionFactory'.


I hope this post will help anyone who has encountered mysterious connection problems when integrating Spring, Hibernate and EJB 2.x

7 comments:

EDH said...

Hello,

I tried out your suggestions.

Here some of my findings. I would appreciate your feedback because it still doesn't seem to work like I excepted.

The part of my architecture under consideration is as follows:
MDB (extending from Spring's AbstractMessageDrivenBean, onMessage with CMT "Required" attribute in ejb-jar.xml)=> service (injected as a LocalStatelessSessionProxyFactoryBean) => actual POJO Service => POJO DAO => Oracle 10g database.
All glued together via Spring dependency injection.

I'm using EJB CMT only. That is, I'm not using spring's declarative txn-management.

I'm on SJAS 8.1 Enterprise Edition.

In my original setup I had the exact settings as you with the exception of the exposeTransActionAwareSessionFactory and useTransactionAwareDataSource properties which I didn't specify at all. I did specify:
'hibernate.current_session_context_class' should be set to 'jta'.
'hibernate.transaction.manager_lookup_class' should be set the a class mapped to the target application server.
'hibernate.transaction.factory_class' should be set to 'org.hibernate.transaction.CMTTransactionFactory'.

My lookup class was the SunONETransactionManagerLookup class.

Now, using the above configuration I always got at seemingly random times an exception when getting a connection: "This Managed Connection is not valid as the phyiscal connection is not usable".

After specifying the additional useTransaction... and exposeTransaction... properties it seems the above problem got resolved.

However I'm still not getting the expected results, more specifically in the scenario where one method (CMT "Required") invokes another method (CMT "RequiresNew").

The server.log shows that the current txn is suspended and that a new one is being created. However it seems that the thread-id remains the same. I would have expected the new txn to run in a new thread.

The problem is that the first txn can't get a hold of the updates made by the second txn:
In my first txn I'm retrieving an object from the database.
In the new txn I'm retrieving this object again and I'm updating it (HibernateTemplate.update(object)).
After successfull completion of this new txn, control returns to the first method/txn. In there I'm again retrieving that same object from the database. However, the object returned doesn't contain the updates made in the second (new) txn. E.g. a collection it is referencing does not contain the entries I added (in the second/new txn).
I don't think this is normal behaviour, would you agree ?

Can you give me some more insight ?
Any suggestions would be appreciated.

Kind regards,
EDH

Alex said...

Hi EDH,
Thanks for your feedback. It's good to know that this configuration suggestion helped you get rid of the "This Managed Connection is not valid as the phyiscal connection is not usable" issue, which was exactly what I encountered before I applied this configuration.
As for your other issues, following are my thoughts.
In my experience with Sun Application Server 8.1 EE, when a transaction-'Required' method of one EJB invokes another transaction-'Required' method of another EJB that uses Hibernate, the Hibernate session is not flushed when exiting the second EJB and an exception is thrown when the session is flushed on exit of the first EJB. My solution is to eagerly flush Hibernate session inside EJBs. It would be better to flush the session using a AOP aspect. I wonder if this would also help resolve your issue...
As for whether a new thread is started when a 'RequiresNew' method is invoked, my feeling is that this depends on the implementation of the target application server.
As for the reason why the first transaction cannot see the changes made by the second transaction, it's probably because the database isolation level is set to 'unrepeatable read', which guarantees that all rows retrieved by a SELECT statement cannot be changed within a transaction, except for newly added rows (phantom reads). Please refer to Isolation (database systems) for more information. Note that 'repeatable read' setting is usually desirable. Therefore, the solution may be change the transaction attribute of the second method from 'RequresNew' to 'Required' so that it is executed in the same transaction and the change should be visible to the first method.

Alex said...

Note that 'repeatable read' setting is usually desirable. Therefore, the solution may be change the transaction attribute of the second method from 'RequresNew' to 'Required' so that it is executed in the same transaction and the change should be visible to the first method.

Alternatively, you may set the database level to 'Read Committed', which may have wider complication.

EDH said...

Regarding my initial reply.

It seems that the original problem I had was solved.

However in two specific scenarios I get a problem with connections. That is, my application works fine (reads, updates, deletes) except in two scenarios. In those scenarios I get the below stack trace.

I'm really stuck. I don't have a clue.
Any help would be appreciated.

Kind regards,
EDH


[#|2008-01-22T12:34:21.778+0100|SEVERE|sun-appserver-ee8.1_02|javax.enterprise.resource.resourceadapter|_ThreadID=21;|RAR5031:System Exception
com.sun.enterprise.resource.PoolingException: java.lang.NullPointerException
at com.sun.enterprise.resource.ConnectorXAResource.getResourceHandle(ConnectorXAResource.java:186)
at com.sun.enterprise.resource.ConnectorXAResource.start(ConnectorXAResource.java:88)
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:129)
at com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:113)
at com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:71)
at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:176)
at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:258)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:193)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:122)
at com.sun.gjc.spi.DataSource.getConnection(DataSource.java:70)
at sun.reflect.GeneratedMethodAccessor227.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:299)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
at $Proxy108.getConnection(Unknown Source)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:94)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2224)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2660)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:59)
at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:272)
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:336)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:2754)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:2557)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:841)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:137)
at $Proxy84.processZending(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.ejb.access.LocalSlsbInvokerInterceptor.invoke(LocalSlsbInvokerInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy99.processZending(Unknown Source)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchServiceImpl.process(ZendingBatchServiceImpl.java:225)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchServiceImpl.processZendingBatch(ZendingBatchServiceImpl.java:124)
at be.vlaanderen.ov.edison.serviceaccess.zendingen.zendingbatch.ZendingBatchServiceFacadeBean.processZendingBatch(ZendingBatchServiceFacadeBean.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:147)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:128)
at $Proxy70.processZendingBatch(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.ejb.access.LocalSlsbInvokerInterceptor.invoke(LocalSlsbInvokerInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy98.processZendingBatch(Unknown Source)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchBatchProcessingController.process(ZendingBatchBatchProcessingController.java:71)
at be.vlaanderen.ov.edison.serviceaccess.zendingen.zendingbatch.ZendingBatchConsumerBean.onMessage(ZendingBatchConsumerBean.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.sun.enterprise.security.SecurityUtil$2.run(SecurityUtil.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.enterprise.security.application.EJBSecurityManager.doAsPrivileged(EJBSecurityManager.java:955)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:158)
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:956)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:42)
at com.sun.enterprise.connectors.inflow.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:130)
at $Proxy109.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:187)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:45)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:409)
java.lang.NullPointerException
at com.sun.enterprise.resource.ConnectorXAResource.getResourceHandle(ConnectorXAResource.java:177)
at com.sun.enterprise.resource.ConnectorXAResource.start(ConnectorXAResource.java:88)
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:129)
at com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:113)
at com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:71)
at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:176)
at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:258)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:193)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:122)
at com.sun.gjc.spi.DataSource.getConnection(DataSource.java:70)
at sun.reflect.GeneratedMethodAccessor227.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:299)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
at $Proxy108.getConnection(Unknown Source)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:94)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2224)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2660)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:59)
at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:272)
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:336)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:2754)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:2557)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:841)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:137)
at $Proxy84.processZending(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.ejb.access.LocalSlsbInvokerInterceptor.invoke(LocalSlsbInvokerInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy99.processZending(Unknown Source)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchServiceImpl.process(ZendingBatchServiceImpl.java:225)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchServiceImpl.processZendingBatch(ZendingBatchServiceImpl.java:124)
at be.vlaanderen.ov.edison.serviceaccess.zendingen.zendingbatch.ZendingBatchServiceFacadeBean.processZendingBatch(ZendingBatchServiceFacadeBean.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:147)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:128)
at $Proxy70.processZendingBatch(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.ejb.access.LocalSlsbInvokerInterceptor.invoke(LocalSlsbInvokerInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy98.processZendingBatch(Unknown Source)
at be.vlaanderen.ov.edison.service.zendingen.zendingbatch.ZendingBatchBatchProcessingController.process(ZendingBatchBatchProcessingController.java:71)
at be.vlaanderen.ov.edison.serviceaccess.zendingen.zendingbatch.ZendingBatchConsumerBean.onMessage(ZendingBatchConsumerBean.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.sun.enterprise.security.SecurityUtil$2.run(SecurityUtil.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.enterprise.security.application.EJBSecurityManager.doAsPrivileged(EJBSecurityManager.java:955)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:158)
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:956)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:42)
at com.sun.enterprise.connectors.inflow.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:130)
at $Proxy109.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:187)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:45)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:409)

Jakub said...

I am wondering if the same configuration can be used when working on was with WebSphereUowTransactionManager ??

Another thing, it seems like these hibernate settings are suitable for CMT environment (i am nearly sure this is configuration for CMT environment, but if it is, i am wondering why you defined transactionManager bean). Can you explain how these hibernate settings should be if you used in BMT ??

mazout said...

Are you using HibernateTemplate or factory.openSession() or factory.getCurrentSession() to get a Session? I think that depending on the way you use Hibernate some of the settings you suggest may not be put in effect.

I want to try MDB with CMT, relying on Spring to synchronize my session with the underlying JTA transaction (but without Spring driving the transaction, that is no spring transaction manager). In this case I think I only need manager_lookup_class and factory_class. I will use only HibernateTemplate to get the session. If I also want to use factory.getCurrentSession() I need to leave exposeTransactionAwareSessionFactory=true(default)
and not override the current_session_context_class property.

Patrick said...

Anyone having a complete sample out there? My transaction won't be commited. Anyone using kind of GenericDAOImpl pattern?