tags:

views:

91

answers:

1

I'm having a bit of an odd problem. This is Hibernate 3.3.2-GA with DB2400Dialect. I'm seeing the following exception --

java.lang.NullPointerException
at org.hibernate.loader.Loader.doQuery(Loader.java:720)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2232)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2129)
at org.hibernate.loader.Loader.list(Loader.java:2124)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1723)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175)
at com.example.WidgetDao.getAllWidgets(WidgetDao.java:28)
at com.example.TestWidgetDao.testGetAllWidgets(TestWidgetDao.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:618)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

The testGetAllWidgets() method is calling WidgetDao.getAllWidgets() twice in a row. The first call works perfectly fine. The result set and mapped objects returned are exactly as I expect. However, I call getAllWidgets() immediately again and the above NPE is thrown. I've tracked it down a bit deeper and the following line in Loader.java is returning a null result set --

// Line 1809 in     
rs = session.getBatcher().getResultSet( (CallableStatement) st, dialect );

The DAO method is executed a stored procedure defined via in the mapping document.

I'm really stumped here. I've literally mapped a few dozen classes to different stored procedures. Suddenly this one has decided to give me fits. There's nothing special about the proc and it simply returns a few String columns.

Anyone have an idea how to track this down further?

Thanks!

+2  A: 

This is more likely then not a problem with DB2 JDBC driver.

Put a breakpoint in DB2Dialect.getResultSet() method and check the ResultSet you're getting there. Perhaps it's trying to be smart and cache the CallableStatement and something goes awry.

When you say "call it immediately again" do you really mean "immediately" - e.g. within the same session? Does it work in a new session (it should)? If you don't find a JDBC-level solution (some connection parameter to turn caching off), that maybe an alternative solution.

ChssPly76
Thanks. I'll dig into that. Immediate is immediate!! Here's the exact code. I've also tried different sessions and it still fails exactly the same way. @Test public void testGetAllWidgets() { // ThreadLocal sessions Session s = SessionFactory.currentSession(); WidgetDao dao = new WidgetDao(s); List widgets = dao.getAllWidgets(); // Works widgets = dao.getAllWidgets(); // Vomits SessionFactory.closeSession(); }
K-Boo
I've done as suggested and put a break in Db2Dialect.getResultSet(). Sure enough, the first time through ResultSet rs = ps.getResultSet(); returns a valid set. 2nd time it returns null.
K-Boo
Are you using a DB pool with more than one connection? If you are and this fails with different sessions, this must be a bug in JDBC (I don't think callable statement can be cached across connections). Are you using the latest and greatest jdbc version? Are there any bug reports for it?
ChssPly76
Either a JDBC bug or Hibernate. I'm using the latest JTOPEN driver and Hibernate 3.3.2-GA. I may try a dev build of Hibernate. I'm using pooling but have stripped that out to simplify the problem. It's still there. No difference if pooling is in or out.
K-Boo
The reason I've mentioned pooling is because there's potentially a difference between doing this on the same connection vs different connections (apparently, neither works in your case so ignore that). Anyway, this is definitely not a Hibernate core bug. Either it's a JDBC problem (most likely) or the way `Db2Dialect` deals with `CallableStatement` is not applicable to this particular JDBC driver. Have you tried doing this in straight-up JDBC? Should be reasonably trivial to throw together a test case. If it still fails, submit a bug to JTOpen.
ChssPly76