-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: MultipleHiLoPerTableGenerator and doWorkInNewTransaction
PostPosted: Mon Oct 10, 2005 11:07 am 
Beginner
Beginner

Joined: Thu Jun 30, 2005 4:20 am
Posts: 40
Location: Vienna
Hi,

I'm having troubles using MultipleHiLoPerTableGenerator with Websphere 5 and Hibernate 3.0.5:

I get the following warning:

Quote:
J2CA0075W: An active transaction should be present while processing method allocateMCWrapper.
J2CA0075W: An active transaction should be present while processing method initializeForUOW.


On IBM's page, this error is explained:
http://www-1.ibm.com/support/docview.wss?rs=180&context=SSEQTP&q=J2CA0075W&uid=swg21109248

I then looked into Hibernate's code and found that the MultipleHiLoPerTableGenerator calls
Code:
TransactionHelper.doWorkInNewTransaction()
which suspends the running transaction and starts a new one.
When closing the session, any exception is swallowed there:

Code:
try {
   session.getBatcher().closeConnection( conn );
}
catch ( Exception e ) {
   //swallow it to put JTA in a proper context
}


Does this mean that I can ignore the warning above? I'm a bit afraid that this will be a proplem with later J2EE versions. Does anybody have more insight into this than I do?

regards,
Stefan


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 1:33 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Can you try to reproduce by moving the close conn before the tx.commit() in the JTA case
Something like that.
Code:
         // commit transaction to ensure updated sequence is not rolled back
         if ( isJta ) {
            session.getBatcher().closeConnection( conn );
            tm.commit();
         }
         else {
            conn.commit();
         }
         return result;
      }
      catch ( SQLException sqle ) {
         catchedException = true;
         if ( isJta ) {
            try {
               tm.rollback();
            }
            catch( Throwable t ) {
               //clean as much as we can
            }
         }
         throw JDBCExceptionHelper.convert(
               session.getFactory().getSQLExceptionConverter(),
               sqle,
               "could not get or update next value",
               sql
            );
      }
      catch ( Exception e ) {
         catchedException = true;
         if ( isJta ) {
            try {
               tm.rollback();
               throw new HibernateException( e );
            }
            catch ( SystemException e1 ) {
               throw new HibernateException( e1 );
            }
         }
         else {
            throw new HibernateException( e );
         }
      }
      finally {
         if ( isJta ) {
            //conn already closed
            // switch back to surrounding transaction context
            if ( isJta && surroundingTransaction != null ) {
               try {
                  tm.resume( surroundingTransaction );
                  if ( log.isDebugEnabled() ) {
                     log.debug( "surrounding tx resumed" );
                  }
               }
               catch ( Exception e ) {
                  //do not hide a previous exception
                  if ( ! catchedException ) throw new HibernateException( e );
               }
            }
         }
         else {
            session.getBatcher().closeConnection( conn );
         }
      }

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 6:08 am 
Beginner
Beginner

Joined: Thu Jun 30, 2005 4:20 am
Posts: 40
Location: Vienna
Hi Emmanuel,
thanks a lot!
Your proposal was right, it works now, the warning does not occur anymore.

best regards,
Stefan


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 10:02 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
OK cool.
I've integrated a slightly different version of this fix in CVS.

Can you do me a favor and test this new version?

Code:
//$Id: TransactionHelper.java,v 1.7 2005/10/11 13:53:19 epbernard Exp $
package org.hibernate.engine;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.exception.JDBCExceptionHelper;

/**
* Allows work to be done outside the current transaction, by suspending it,
* and performing work in a new transaction
*
* @author Emmanuel Bernard
*/
public abstract class TransactionHelper {
   private static final Log log = LogFactory.getLog( TransactionHelper.class );
   
   /**
    * The work to be done
    */
   protected abstract Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException;

   /**
    * Suspend the current transaction and perform work in a new transaction
    */
   public Serializable doWorkInNewTransaction(SessionImplementor session)
   throws HibernateException {
   
      // This has to be done using a different connection to the
      // containing transaction because the new hi value must
      // remain valid even if the containing transaction rolls
      // back
      TransactionManager tm = session.getFactory().getTransactionManager();
      Transaction surroundingTransaction = null;  // for resuming in finally block
      Connection conn = null; // for ressource cleanup
      String sql = null; // for exception
      boolean isJta = tm != null;
      boolean catchedException = false;
      try {
         if ( isJta ) {
            //JTA environment
            // prepare a new transaction context for the generator
            surroundingTransaction = tm.suspend();
            if ( log.isDebugEnabled() ) {
               log.debug( "surrounding tx suspended" );
            }
            tm.begin();
            // get connection from managed environment
            conn = session.getBatcher().openConnection();
         }
         else {
            // get connection from the hibernate defined pool
            conn = session.getBatcher().openConnection();
            if ( conn.getAutoCommit() ) conn.setAutoCommit( false );
         }

         Serializable result = doWorkInCurrentTransaction( conn, sql );

         // commit transaction to ensure updated sequence is not rolled back
         if ( isJta ) {
            session.getBatcher().closeConnection( conn );
            tm.commit();
         }
         else {
            conn.commit();
         }
         return result;
      }
      catch ( SQLException sqle ) {
         catchedException = true;
         if ( isJta ) {
            try {
               try {
                  if ( ! conn.isClosed() ) {
                     session.getBatcher().closeConnection( conn );
                  }
               }
               catch (Throwable t) {
                  //clean as much as we can the JTA context
               }
               tm.rollback();
            }
            catch( Throwable t ) {
               //clean as much as we can the JTA context
            }
         }
         throw JDBCExceptionHelper.convert(
               session.getFactory().getSQLExceptionConverter(),
               sqle,
               "could not get or update next value",
               sql
            );
      }
      catch ( Exception e ) {
         catchedException = true;
         if ( isJta ) {
            try {
               try {
                  if ( ! conn.isClosed() ) {
                     session.getBatcher().closeConnection( conn );
                  }
               }
               catch (Throwable t) {
                  //clean as much as we can the JTA context
               }
               tm.rollback();
               throw new HibernateException( e );
            }
            catch ( SystemException e1 ) {
               //TODO raise the original exception?
               throw new HibernateException( e1 );
            }
         }
         else {
            throw new HibernateException( e );
         }
      }
      finally {
         if ( isJta ) {
            // switch back to surrounding transaction context
            if ( isJta && surroundingTransaction != null ) {
               try {
                  tm.resume( surroundingTransaction );
                  if ( log.isDebugEnabled() ) {
                     log.debug( "surrounding tx resumed" );
                  }
               }
               catch ( Exception e ) {
                  //do not hide a previous exception
                  if ( ! catchedException ) throw new HibernateException( e );
               }
            }
         }
         else {
            session.getBatcher().closeConnection( conn );
         }
      }
   }
}


Thanks.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 3:50 am 
Beginner
Beginner

Joined: Thu Jun 30, 2005 4:20 am
Posts: 40
Location: Vienna
Hi,

I tested it and it works well. I also tested the case where an SQL exception is caught, this also works well.

Thanks again for the quick help!

regards
Stefan


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 14, 2005 5:54 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Cool, thanks man :-)

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.