OK, here is some code/configuration:
The Transaction-Manager and DataSource:
Code:
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven/>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- JDBC data source from JNDI for WebSphere/Tomcat -->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyAppDataSource"/>
The Transaction-Annotations (ReadWrite and Readonly):
Code:
@Target({ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public @interface ReadonlyTransaction {
// empty block for annotation
}
@Target({ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {
OperationFailedException.class, java.rmi.RemoteException.class })
public @interface ReadWriteTransaction {
// empty block for annotation
}
If I use Propagation.REQUIRED with readOnly=true in WebSphere, I get only the LOG-statements printed in my previous post. No stacktrace.
If I use Propagation.SUPPORTS with readOnly=true I get the following exception, when running a JMS query:
Code:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1041)
at com.myapp.integration.dao.hibernate.BaseDAOImpl.get(BaseDAOImpl.java:72)
at com.myapp.integration.dao.hibernate.UserDAOImpl.getUser(UserDAOImpl.java:80)
at com.myapp.business.user.UserManagerImpl.getEnabledUser(UserManagerImpl.java:246)
at com.myapp.business.user.UserManagerImpl.getUser(UserManagerImpl.java:338)
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:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy17.getUser(Unknown Source)
at com.myapp.presentation.report.ReportQueueListener.processReportRequest(ReportQueueListener.java:90)
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:597)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.jms.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:463)
at org.springframework.jms.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:355)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:537)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:497)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:264)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:662)
And here is some code from my BaseDaoImpl. The get() method is generic and called from mulitple places. If I call the method from a Struts action, everything is OK, there is an open session. But if I call the method from JMS or Quartz, there is no open session.
Code:
protected <T extends PersistentEntity> T get(Class<T> clazz, Serializable identifier, boolean lock) {
Session session = getSessionFactory().getCurrentSession();
T result = (T) session.get(clazz, identifier,
lock ? LockOptions.UPGRADE : LockOptions.NONE);
if (LOG.isDebugEnabled() && result == null) {
LOG.debug("Entity not found!");
}
return result;
}
Any idea? Thanks for your help.