Hi there,
I am having some issues with CMT rollbacks not working correctly.
I am using the Steve Ebersole variation on the ThreadLocal pattern, and stateless session beans calling DAOs for data access. On Weblogic 8.1, sql server 7. I find that when I use a new Session per operation all CMT rollbacks seem to work fine. The below code shows a dao save method, which is called from a SLSB method (also shown below) - the session is opened and closed around the save call. The rollback works correctly in this case.
public void save(Object entity) throws DataAccessException {
try {
Session session = HibernateSession.currentSession();
session.save(entity);
session.flush();
}
catch (HibernateException he) {
throw new DataAccessException("error ocurred executing save call ", he);
}
finally {
HibernateSession.closeSession();
}
}
/**
* @ejb.business-method
* @ejb.interface-method
* @ejb.transaction type="Required"
*/
public void insertExample() {
try{
CreditCardPaymentHDO hdo = new CreditCardPaymentHDO();
HibernateDaoSupport dao = new HibernateDaoSupport();
dao.save( hdo);
throw new NullPointerException("will have to rollback now");
}catch(Throwable t){
getSessionContext().setRollbackOnly();
}
}
However I would like open the session at the start of a SLSB method, do a number of loads, saves etc and close the session at the end of the SLSB method to take advantage of lazy loads, session caching etc (all in the same CMT transaction). However I find that the following EJB code results in weblogic throwing an exception when the closeSession() method is called from the finally clause.
/**
* @ejb.business-method
* @ejb.interface-method
* @ejb.transaction type="Required"
*/
public void insertExample() {
try{
HibernateSession.currentSession();
CreditCardPaymentHDO hdo = new CreditCardPaymentHDO();
HibernateDaoSupport dao = new HibernateDaoSupport();
dao.save( hdo);
throw new NullPointerException("will have to rollback now");
}catch(Throwable t){
getSessionContext().setRollbackOnly();
}finally{
HibernateSession.closeSession();
}
}
javax.ejb.EJBException: EJB Exception: : au.com.wanews.olps.framework.exception.DataAccessException: Error closing hibernate session
at au.com.wanews.olps.framework.database.hibernate.HibernateSession.closeSession(HibernateSession.java:78)
at au.com.wanews.olps.beans.advertisementlodgement.AdvertisementLodgementEJB.retrieveReferenceTables(AdvertisementLodgementEJB.java:543)
at au.com.wanews.olps.beans.advertisementlodgement.AdvertisementLodgementEJB_mkl5ls_ELOImpl.retrieveReferenceTables(AdvertisementLodgementEJB_mkl5ls_ELOImpl.java:325)
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:324)
at org.springframework.ejb.access.LocalSlsbInvokerInterceptor.invoke(LocalSlsbInvokerInterceptor.java:41)
at org.springframework.aop.framework.MethodInvocationImpl.proceed(MethodInvocationImpl.java:216)
at org.springframework.aop.framework.AopProxy.invoke(AopProxy.java:137)
at $Proxy20.retrieveReferenceTables(Unknown Source)
at au.com.wanews.olps.website.tests.EjbTestServlet.test0(EjbTestServlet.java:249)
at au.com.wanews.olps.website.tests.EjbTestServlet.doGet(EjbTestServlet.java:233)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1053)
at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:387)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:28)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:27)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6316)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:317)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:118)
at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3622)
at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2569)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:197)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:170)
Caused by: net.sf.hibernate.JDBCException: Cannot close connection
at net.sf.hibernate.impl.BatcherImpl.closeConnection(BatcherImpl.java:273)
at net.sf.hibernate.impl.SessionImpl.disconnect(SessionImpl.java:3203)
at net.sf.hibernate.impl.SessionImpl.close(SessionImpl.java:549)
at au.com.wanews.olps.framework.database.hibernate.HibernateSession.closeSession(HibernateSession.java:75)
... 25 more
Caused by: java.sql.SQLException: The transaction is no longer active - status: 'Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException]'. No further JDBC access is allowed within this transaction.
at weblogic.jdbc.wrapper.JTSConnection.checkIfRolledBack(JTSConnection.java:118)
at weblogic.jdbc.wrapper.JTSConnection.checkConnection(JTSConnection.java:127)
at weblogic.jdbc.wrapper.Connection.preInvocationHandler(Connection.java:67)
at weblogic.jdbc.wrapper.JTSConnection_weblogic_jdbc_sqlserver_SQLServerConnection.getWarnings(Unknown Source)
at net.sf.hibernate.impl.BatcherImpl.closeConnection(BatcherImpl.java:267)
... 28 more
; nested exception is: au.com.wanews.olps.framework.exception.DataAccessException: Error closing hibernate session
It looks like weblogic expects that the connection should be closed prior to calling getSessionContext().setRollbackOnly(). I guess that the session per operation works correctly because the session is closed prior to calling setRollbackOnly(). Can anyone suggest why this might be so ? I would really like to execute the whole ejb method using the one Session. Interestingly, if I don't catch the Throwable but let the container rollback the transaction all is fine (no exceptions thrown and changes rolled back).
Any help on this greatly appreciated.
Tom.
[/b]
|