Tuesday, June 10, 2008

Hibernating in the Spring

So I've been working on a project which uses the Spring bindings (2.0) for Hibernate (3.2) to handle persisting business objects to the database, and up until yesterday everything seemed to be working fine. Persisting and retrieving specific objects worked well and the web front end, based on Grails, had no trouble seeing and sorting the data as needed. Then yesterday I needed to do something a little different. I needed to pull all instances of a certain class from the DB and pass their IDs via JMS to an Message Driven Bean hosted on a remote JBoss server which in turn pulled the actual objects, extracted data from them and related tables, and built a warehouse using the correlated data. With all the extra pieces going in I expected something would go wrong right out of the gate as I've come to trust in Mr. Murphy's wisdom, and I wasn't disappointed. After a run completed I found I was missing about 2/3 of the expected data!

Well, I started the run again with added logging and found the following:
  1. The sending component was pulling fewer entries from the DB than there were rows.
  2. All of the pulled data was being sent.
  3. All of the sent data was ending up in the JBoss JMS queue that the MDB subscribed to.
  4. All of the data in the queue was being pulled by the MDB.
  5. About half of the data pulled didn't have a corresponding entry in the DB, and therefore didn't result in a valid warehouse entry being created.

Well, the "infection" point for the bug was clearly the client, but that didn't make any sense. The code that loaded the objects from the DB basically boiled down to:

HibernateTemplate ht = (HibernateTemplate)appContext.getBean("hibernateTemplate");
List = ht.loadAll(Foo.class);

Here ht is an instance of org.springframework.orm.hibernate3.HibernateTemplate, and loadAll(Foo.class) should have returned a list of all the instances of Foo in the DB. For some reason however it returned 2/3 as many instances as there were rows, and about half of those had IDs that didn't match the value in the DB.

Going deeper into the rathole I tried making a simple set of JDBC calls against the underlying org.springframework.jdbc.datasource.DriverManagerDataSource and got a java.sql.ResultSet back that made even less sense.

In the end I went back to basics and pulled the IDs directly out of the DB using straight JDBC, and now I have a full warehouse as the JMS and EJB3-managed entities on the server worked fine. Nonetheless, I'm incredibly confused by what happened with the Spring/Hibernate setup, and a little worried about what other issues may have gotten by the unit tests, as this only cropped up when I tried working with data sets in excess of 16,000 entries. If anyone out there has any ideas, please let me know.