-->
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.  [ 1 post ] 
Author Message
 Post subject: Transaction Boundary, StatelessSessions and Result Scrolling
PostPosted: Thu Mar 24, 2011 9:20 am 
Regular
Regular

Joined: Tue Oct 10, 2006 2:21 pm
Posts: 58
I had an embarrassing incident yesterday. Code which had passed my automated integration test suite failed in production. This proved to involve StatelessSessions, Scrollable Results and transaction commitment.

Code:
private ScrollableResults query(StatelessSession sess) {
    return sess.createQuery(hql)
            ...
            .scroll(ScrollMode.FORWARD_ONLY);       
}

private void process()  {
    ...
    StatelessSession sess = getBroker().getStatelessSession();
    getBroker().beginStatelessSessionTransaction();
    ScrollableResults results = query(sess);
    getBroker().commitStatelessSessionTransaction();
   
    while ( true ) {
        int transCount = 0;
        while ( results.next() ) {
            transCount++;
            OrderRec order = (OrderRec) results.get(0);
            // do non-database related stuff with order
        }
        if (transCount < MAX_ROWS_PER_DIP) {
            // we're done
            break;
        } else {
            // don't hog the processor.
            pause();
        }
    }
}


(note these "broker" calls are calls to a Thread-local-pattern based wrapper around Hibernate. This was originally based on an old suggestion from Hibernate and is not suspected here).

This code worked in my automated integration test suite. When it was tried in production, however, it failed:

2011-03-23 02:30:00,254 [sked-5] ERROR util.JDBCExceptionReporter - Operation
not allowed after ResultSet closed
2011-03-23 02:30:00,255 [sked-5] ERROR HibernateException
org.hibernate.exception.GenericJDBCException: could not advance using next()
at
org.hibernate.exception.SQLStateConverter.handledNonSpecificException
(SQLStateConverter.java:126)
at org.hibernate.exception.SQLStateConverter.convert
(SQLStateConverter.java:114)
at org.hibernate.exception.JDBCExceptionHelper.convert
(JDBCExceptionHelper.java:66)
at org.hibernate.exception.JDBCExceptionHelper.convert
(JDBCExceptionHelper.java:52)
at org.hibernate.impl.ScrollableResultsImpl.next
(ScrollableResultsImpl.java:127)

This exception was able to be overcome by the following code change (committing the transaction only after the scrollable results were walked).

Code:
private void process()  {
   ...
   StatelessSession sess = getBroker().getStatelessSession();
   getBroker().beginStatelessSessionTransaction();
   ScrollableResults results = query(sess);
   
   while ( true ) {
      int transCount = 0;
      while ( results.next() ) {
         transCount++;
         OrderRec order = (OrderRec) results.get(0);
         // do non-database related stuff with order
      }
      if (transCount < MAX_ROWS_PER_DIP) {
         // we're done
         break;
      } else {
         // don't hog the processor.
         pause();
      }
      
   }
   getBroker().commitStatelessSessionTransaction();
}


I had assumed that as long as the Session remained open, the results were readable. Is this not the case for stateless sessions?

Anyway, I still wanted to understand the difference between my integration test environment and my production environment. Eventually, I realized that my production environment was using C3P0 to provide connections whereas my test environment was not. Turning C3P0 on in the test environment caused the first code to fail in the test environment as it did in production.

I wonder if this is a bug. If my first code sample is correct then it should work under C3P0 or Hibernate's default connection provider. If it is incorrect, then it should fail either way. It doesn't seem right to me that the choice of connection pool should affect the way transactions work, but I could be wrong about this. Can someone explain the inconsistency?


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

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.