2

I am using jersey with mysql and hibernate 4 and c3p0. I have created a initialization servlet that configures hibernate and sets the current session context class to thread. I have created hibernateUtils class that contains static methods for getting and committing sessions and I am using a filter to start a session on inbound request and commit it upon response.

The problem is that at some random intervals I am getting org.hibernate.TransactionException: nested transactions not supported exception, but I am not trying to create a new session except on the filter.

Correct me if I am wrong but when setting the current session class to thread I don't need to create a threadlocal in the hibernateutil, hibernate does this. So my question is, is this a safe way to handle that and what could cause the error happening on random intervals?

====================== EDIT ===========================

Sorry for not posting the code earlier. So the filter implements the ContainerRequestFilter,ContainerResponseFilter

in the request filter I am doing

Session session = sessionfactory.getCurrentSession();
session.getTransaction().begin();
session.setDefaultReadOnly(readOnly);

and in the response

Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try {
    if (transaction != null && !transaction.wasCommitted()
       && !transaction.wasRolledBack() && transaction.isActive()) {
        transaction.commit();
    }
} catch (HibernateException e) {
    Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
    try {
        if (transaction != null && transaction.isActive()) {
            transaction.rollback();
        }
    } catch (HibernateException e) {

    } finally {
         Session session = sessionfactory.getCurrentSession();
         try {
              if (session != null && session.isOpen()) {
                  session.close();
              }
         } catch (HibernateException e) {
            log.error("Closing session after rollback error: ", e);
            throw e;
     }

}

BenMorel
  • 34,448
  • 50
  • 182
  • 322
maxsap
  • 2,971
  • 9
  • 44
  • 70

1 Answers1

1

It seems that you are using programmatic transaction demarcation in your filter (as far as I understood). So please double check that you terminate properly each transaction, nevermind what append during the request (i.e. rollback if you get an exception and commit otherwise) :

try {
    session.getTransaction().begin();
    // call the filter chain
    session.getTransaction().commit()
}
catch (RuntimeException e) {
    session.getTransaction().rollback();
}

Without the code it's difficult to be sure, but I guess that for some request you didn't terminate the transaction properly (i.e. by a commit or by a rollback). So the transaction remains associated to the thread and the thread go back to the thread pool (in a very strange state since there is still a transaction associated with it), then another request reuse the same thread, a new transaction is created in the filter... and you got the exception.

EDIT

After looking carrefully at your code, it (may) confirms my assumptions.

Look at the flow when transaction.wasRolledBack()==true : it won't be commited nor rolled back.

And if you the javadoc for Transaction.wasRolledBack() :

Was this transaction rolled back or set to rollback only?

If the transaction is marked as "RollBack only" : it will return true, but it don't means that the transaction is ended. It means that the only possible ending state for the transaction is "RollBack".

But, on the other hand the same javadoc also say this:

Returns: boolean True if the transaction was rolled back via this local transaction; false otherwise.

I found that ambiguous.

So I suggest you to do this:

if (transaction != null && !transaction.wasCommitted()
   && !transaction.wasRolledBack() && transaction.isActive()) {
    transaction.commit();
}else if(transaction.wasRolledBack()){
    transaction.rollback();
}
ben75
  • 29,217
  • 10
  • 88
  • 134
  • sorry for not posting sample code prior, I have updated my question I know that it seems that way but I cannot think of where the leaked session can be since I am closing it on finally! – maxsap Sep 12 '13 at 22:09
  • thank you for this tip, I will try and see if the error persists. – maxsap Sep 12 '13 at 22:54