Failure when committing JTA transaction: status=STATUS_NO_TR
sprhodes Jan 3, 2006 9:24 PMHi all, having a little problem that I'm hoping someone can shed some light on.
I have a servlet in which I'm trying to use JTA transactions, but when I call the commit() method on the UserTransaction, I get back:
2006-01-03 21:08:25,718 INFO [STDOUT] org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=pathfinder/16, BranchQual=, localId=16] status=STATUS_NO_TRANSACTION
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:344)
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.TxManager.commit(TxManager.java:200)
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:126)
2006-01-03 21:08:25,718 INFO [STDOUT] at test.TransactServlet.doGet(TransactServlet.java:52)
I added some debugging statements to check though, and there is an active transaction right at the moment when commit() is called. This we can see from a slightly larger snippet of the trace file:
2006-01-03 21:08:25,687 INFO [test.TransactServlet] Before commit: 0 - STATUS_ACTIVE
2006-01-03 21:08:25,687 DEBUG [org.hibernate.transaction.CacheSynchronization] transaction before completion callback
2006-01-03 21:08:25,687 DEBUG [org.hibernate.transaction.CacheSynchronization] automatically flushing session
2006-01-03 21:08:25,687 DEBUG [org.hibernate.impl.SessionImpl] automatically flushing session
2006-01-03 21:08:25,687 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] flushing session
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushing entities and processing referenced collections
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Processing unreferenced collections
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Scheduling collection removes/(re)creates/updates
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
2006-01-03 21:08:25,703 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
2006-01-03 21:08:25,718 DEBUG [org.hibernate.pretty.Printer] listing entities:
2006-01-03 21:08:25,718 DEBUG [org.hibernate.pretty.Printer] test.UserObject{name=JBossHibernate, id=77}
2006-01-03 21:08:25,718 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] executing flush
2006-01-03 21:08:25,718 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] post flush
2006-01-03 21:08:25,718 DEBUG [org.hibernate.jdbc.JDBCContext] before transaction completion
2006-01-03 21:08:25,718 DEBUG [org.hibernate.impl.SessionImpl] before transaction completion
2006-01-03 21:08:25,718 DEBUG [org.hibernate.transaction.CacheSynchronization] transaction after completion callback, status: 4
2006-01-03 21:08:25,718 DEBUG [org.hibernate.jdbc.JDBCContext] after transaction completion
2006-01-03 21:08:25,718 DEBUG [org.hibernate.impl.SessionImpl] after transaction completion
2006-01-03 21:08:25,718 DEBUG [org.hibernate.jdbc.JDBCContext] no active transaction, could not register Synchronization
2006-01-03 21:08:25,718 DEBUG [org.hibernate.jdbc.JDBCContext] no active transaction, could not register Synchronization
2006-01-03 21:08:25,718 DEBUG [org.hibernate.transaction.CacheSynchronization] automatically closing session
2006-01-03 21:08:25,718 DEBUG [org.hibernate.impl.SessionImpl] automatically closing session
2006-01-03 21:08:25,718 DEBUG [org.hibernate.impl.SessionImpl] closing session
2006-01-03 21:08:25,718 DEBUG [org.hibernate.jdbc.ConnectionManager] connection already null in cleanup : no action
2006-01-03 21:08:25,718 INFO [STDOUT] org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=pathfinder/16, BranchQual=, localId=16] status=STATUS_NO_TRANSACTION
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:344)
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.TxManager.commit(TxManager.java:200)
2006-01-03 21:08:25,718 INFO [STDOUT] at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:126)
2006-01-03 21:08:25,718 INFO [STDOUT] at test.TransactServlet.doGet(TransactServlet.java:52)
Here is the code for the servlet in question:
@Override protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { try { /* get JNDI Context */ InitialContext jndiCtx = new InitialContext(); SessionFactory sf = new Configuration().configure().buildSessionFactory(); // get the UserTransactionObject UserTransaction ut = (UserTransaction)jndiCtx.lookup( "UserTransaction" ); ut.begin(); logger.info( "UT status right after begin: " + getStatusName( ut.getStatus() ) ); // and open the Hibernate session Session session = sf.getCurrentSession(); // do something transactional using Hibernate UserObject obj = new UserObject( "JBossHibernate" ); session.save( obj ); // do something else involving the transaction (send a JMS message, for example) // TODO: add a separate transactional step here logger.info( "Before commit: " + getStatusName( ut.getStatus() ) ); // commit the transaction /* this is where it blows up!! */ ut.commit(); logger.info( "After commit: " + getStatusName( ut.getStatus() ) ); PrintWriter out = response.getWriter(); out.append( "<html><head><title>Success</title></head><body><p />Success!</body>"); } catch( Exception e ) { e.printStackTrace(); PrintWriter out = response.getWriter(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); pw.append( "<html><head><title>Error</title></head><body><p />" ); e.printStackTrace(pw); pw.append( "</body>"); pw.flush(); sw.flush(); out.print( sw.toString() ); }
If it helps, here are the datasource definition and the hibernate.cfg.xml:
datasource
<?xml version="1.0" encoding="UTF-8"?> <!-- ===================================================================== --> <!-- --> <!-- JBoss Server Configuration --> <!-- Thanks to Horia Muntean <horia@bvb.ro> --> <!-- ===================================================================== --> <!-- $Id: db2-xa-ds.xml,v 1.4 2004/09/15 14:37:40 loubyansky Exp $ --> <datasources> <!-- XADatasource for DB2 V8.1 (app driver) copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib --> <xa-datasource> <jndi-name>db2DataSource</jndi-name> <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class> <xa-datasource-property name="DatabaseName">HIBTEST</xa-datasource-property> <xa-datasource-property name="User">prhodes</xa-datasource-property> <xa-datasource-property name="Password">redacted</xa-datasource-property> <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) --> <metadata> <type-mapping>DB2</type-mapping> </metadata> </xa-datasource> </datasources>
hibernate config
<hibernate-configuration> <session-factory> <property name="connection.autocommit">false</property> <property name="connection.datasource">java:/db2DataSource</property> <property name="dialect">org.hibernate.dialect.DB2Dialect</property> <property name="transaction.flush_before_completion">true</property> <property name="transaction.auto_close_session">true</property> <property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property> <property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property> <property name="current_session_context_class">jta</property> <mapping resource="test/UserObject.hbm.xml" /> </session-factory> </hibernate-configuration>
UserObject is just a stupid little class with an id and one attribute:
<hibernate-mapping> <class name="test.UserObject" table="USEROBJECT"> <id name="id" column="ID" type="long"> <generator class="native" /> </id> <property name="name" column="NAME" type="string" /> </class> </hibernate-mapping>
package test; public class UserObject { private Long id; private String name; public UserObject() { } public UserObject( String name ) { this.name = name; } public Long getId() { return id; } public void setId( Long id ) { if( this.id == null ) { this.id = id; } else { throw new RuntimeException( "attempt to modify immutable field \"id\" with value: " + this.id ); } } public void setName( String name ) { this.name = name; } public String getName() { return name; } }