Hibernate version:
Mapping documents:
Code between sessionFactory.openSession() and session.close():
Full stack trace of any exception that occurs:
Name and version of the database you are using:
Debug level Hibernate log excerpt:
When ever a runtime exception occurs after session.save(POJO), hibernate tries to insert the data into the database eventhough it is "already marked for rollback" by Jboss. We are using hibernate as persistence layer for our enterprise application which is the client of stateless session beans. The error in the jboss server.log is:
18:16:46,921 DEBUG [Printer] com.krcl.rap.object.AlmkAirline{airDesc=amma, airCd=amma} 18:16:46,937 DEBUG [SessionImpl] executing flush 18:16:46,937 DEBUG [EntityPersister] Inserting entity: [com.krcl.rap.object.AlmkAirline#amma] 18:16:46,937 DEBUG [BatcherImpl] about to open: 0 open PreparedStatements, 0 open ResultSets 18:16:46,953 INFO [TxConnectionManager] Could not enlist XAResource! javax.transaction.RollbackException: Already marked for rollback at org.jboss.tm.TransactionImpl.enlistResource(TransactionImpl.java:588) at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:455) at org.jboss.resource.connectionmanager.TxConnectionManager.managedConnectionReconnected(TxConnectionManager.java:343) at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:483) at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:814) at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:102) at net.sf.hibernate.connection.DatasourceConnectionProvider.getConnection(DatasourceConnectionProvider.java:59) at net.sf.hibernate.impl.BatcherImpl.openConnection(BatcherImpl.java:278) at net.sf.hibernate.impl.SessionImpl.connect(SessionImpl.java:3302) at net.sf.hibernate.impl.SessionImpl.connection(SessionImpl.java:3282) at net.sf.hibernate.impl.BatcherImpl.prepareStatement(BatcherImpl.java:61) at net.sf.hibernate.impl.BatcherImpl.prepareStatement(BatcherImpl.java:56) at net.sf.hibernate.impl.BatcherImpl.prepareBatchStatement(BatcherImpl.java:109) at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:460) at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:442) at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:29) at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2414) at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2367) at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236) at com.krcl.rap.masters.HibernateUtil$SessionSynchronization.beforeCompletion(HibernateUtil.java:174) at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1308) at org.jboss.tm.TransactionImpl.rollback(TransactionImpl.java:456) at org.jboss.ejb.plugins.TxInterceptorCMT.endTransaction(TxInterceptorCMT.java:390) at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:277) at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:128) at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:118) at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191) at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122) at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331) at org.jboss.ejb.Container.invoke(Container.java:700) 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.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284) at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546) at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:367) 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 sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261) at sun.rmi.transport.Transport$1.run(Transport.java:148) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:144) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) at java.lang.Thread.run(Thread.java:534) 18:16:47,000 INFO [TxConnectionManager] Could not enlist in transaction on entering meta-aware object!
The code in EJB which is responsible for the above exception is :
public void createTrainingCenter_h (TrainingMasterVO trainingVO) throws RemoteException, NamingException, HibRuntimeException, HibernateException { try { SessionFactory sessionFactory = HibernateUtil.lookupSessionFactory(); Session session = HibernateUtil.getSession(sessionFactory); AlmkAirline tCenter = new AlmkAirline(); tCenter.setAirCd(trainingVO.getCentreCode()); tCenter.setAirDesc(trainingVO.getCentreDescription()); session.save(tCenter); if (true) { ctx.setRollbackOnly(); throw new RemoteException(); } } catch (NamingException ne) { ne.printStackTrace(); throw ne; } catch (HibRuntimeException he) { he.printStackTrace(); throw he; } catch (HibernateException e) { e.printStackTrace(); throw e; } }
The HibernateUtil class is defined below:
import java.util.HashMap; import java.util.Map;
import javax.naming.InitialContext; import javax.naming.NamingException; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager;
import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.engine.SessionFactoryImplementor;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
/** * Class allowing for reuse of Hibernate Session instances within a transaction * transaction. */ public class HibernateUtil {
private static Log logger = LogFactory.getLog(HibernateUtil.class);
private static ThreadLocal sessionSynchronizations = new ThreadLocal();
public static SessionFactory lookupSessionFactory() throws NamingException { InitialContext initCtx = new InitialContext(); return (SessionFactory) initCtx.lookup("java:/hibernate/HibernateFactory"); }
/** * Gets a session from the given session factory. If a session has already * been asked for this session factory in the current JTA transaction, the * same session is returned. Else, a new session is created. * The returned session will automatically be flushed and closed at the end * of the current JTA transaction. * @param sessionFactory the factory from which to get the session * @return a session associated with the current JTA transaction. */ public static Session getSession(SessionFactory sessionFactory) throws HibRuntimeException { try { Map map = getSessionSynchronizationMap(); Key key = new Key(sessionFactory, getCurrentTransaction(sessionFactory)); SessionSynchronization sync = (SessionSynchronization) map.get(key); if (sync == null) { Session session = sessionFactory.openSession(); sync = new SessionSynchronization(key, session); map.put(key, sync); getCurrentTransaction(sessionFactory).registerSynchronization(sync); } return sync.getSession(); } catch(SystemException e) { throw new HibRuntimeException(e); } catch(HibernateException e) { throw new HibRuntimeException(e); } catch(RollbackException e) { throw new HibRuntimeException(e); } } /** * Gets the thread local map storing the session synchronizations. * The returned map contains Key instances as keys and SessionSynchronization * instances as values */ private static Map getSessionSynchronizationMap() { Map map = (Map) sessionSynchronizations.get(); if (map == null) { map = new HashMap(); sessionSynchronizations.set(map); } return map; } /** * Gets the current JTA transaction. * @param sessionFactory the session factory allowing to get the current * transaction * @return the current JTA transaction * @throws SystemException */ private static Transaction getCurrentTransaction(SessionFactory sessionFactory) throws SystemException { SessionFactoryImplementor sessionFactoryImpl = (SessionFactoryImplementor) sessionFactory; TransactionManager txManager = sessionFactoryImpl.getTransactionManager(); return txManager.getTransaction(); } /** * Closes the given session and removes the session synchronization identified * by the given key from its map. */ private static void closeSession(Key key, Session session) throws HibernateException { getSessionSynchronizationMap().remove(key); session.close(); }
/** * A class combining a session factory and a JTA transaction. It's used as * key in the map of session synchronizations. */ private static class Key { private SessionFactory sessionFactory; private Transaction transaction; public Key(SessionFactory sessionFactory, Transaction transaction) { this.sessionFactory = sessionFactory; this.transaction = transaction; } public SessionFactory getSessionFactory() { return sessionFactory; } public Transaction getTransaction() { return transaction; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof Key) { Key k = (Key) o; return ((k.transaction == this.transaction) && (k.sessionFactory == this.sessionFactory)); } return false; } public int hashCode() { return (37 * transaction.hashCode()) + sessionFactory.hashCode(); } } /** * Class allowing to close a session at the end of a JTA transaction. */ private static class SessionSynchronization implements Synchronization { private Key key; private Session session; public SessionSynchronization(Key key, Session session) { this.key = key; this.session = session; }
/** * @see javax.transaction.Synchronization#beforeCompletion() */ public void beforeCompletion() { logger.debug("beforeCompletion called"); try { session.flush(); closeSession(key, session); this.session = null; } catch (HibernateException e) { logger.error("impossible to flush or close the session", e); //throw new HibRuntimeException(e); } }
/** * @see javax.transaction.Synchronization#afterCompletion(int) */ public void afterCompletion(int status) { logger.debug("afterCompletion called"); if (this.session != null) { try { closeSession(key, session); this.session = null; } catch (HibernateException e) { logger.warn("impossible to close the session", e); } } } public Session getSession() { return session; } } }
What goes wrong in my code? Can anybody suggest how transaction rollback is handled when Hibernate is used with stateless session beans.
Thanks in Advance Best regards Amrit
_________________ amritkumar
|