Hibernate 3.6.0.Final + PostgreSQL + CLOBs

I recently upgraded a project I’m working on to Hibernate 3.6.0.Final from 3.5.6 and realized that one of my entities that had a CLOB (character large object) was pooping out.  I was getting an exception stack track similar to:

Caused by: org.postgresql.util.PSQLException: Bad value for type long : <table border="0" cellspacing="0" cellpadding="0" id="productDetailLineItems"><thead><tr><td rowspan="2"><input type="hidden" name="productGroupId" id="productGroupId" value="101111"/>Item Number</td><td rowspan="2">Motor HP</td><td rowspan="2">Price</td></tr></thead><tbody><tr><form method="post" id="4581000" name="4581000" action=""><td>4581000</td><td><span style="fraction"><sup>1</sup>/<sub>2</sub></span></td><td><input type="button" onclick="javascript:addToCart('4581000');" value="$prc4581000" /></td></form></tr></tbody></table>
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2690) [:]
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:1995) [:]
at org.postgresql.jdbc3.Jdbc3ResultSet.getClob(Jdbc3ResultSet.java:44) [:]
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:373) [:]
at org.jboss.resource.adapter.jdbc.WrappedResultSet.getClob(WrappedResultSet.java:516) [:6.0.0.Final]
at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$2.doExtract(ClobTypeDescriptor.java:70) [:3.6.0.Final]
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) [:3.6.0.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) [:3.6.0.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:249) [:3.6.0.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:229) [:3.6.0.Final]
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:330) [:3.6.0.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2265) [:3.6.0.Final]
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1527) [:3.6.0.Final]
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1455) [:3.6.0.Final]
at org.hibernate.loader.Loader.getRow(Loader.java:1355) [:3.6.0.Final]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611) [:3.6.0.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:829) [:3.6.0.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) [:3.6.0.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2037) [:3.6.0.Final]
... 167 more

I do local development on my MacBook Pro with PostgreSQL 9.0.2 and will point my machine at the client’s DB2 database once in a while for pushes to their development system.  When I point the system at their DB dev database, everything works fine.  Pointing back at my PostgreSQL, the entity craps out.  I tried going back to the old 8.0 driver like some people online suggested with no luck.  I hadn’t tried using this entity since I upgraded to Hibernate 3.6 because I also have been moving from OpenEJB to JBoss 6 so it could have been that as well.

Ultimately I found a simple solution.  PostgreSQL apparently doesn’t play well with Hibernate 3.6 and requires a specific Hibernate annotation on your entity (I’m using JPA entities by the way).  On your CLOB, in addition to the @Lob, add:

@Type(type="org.hibernate.type.StringClobType")

Redeploy your application and Hibernate should behave properly.

Flush THIS Hibernate!

I’ve been working with Hibernate 3.3.2 and Hibernate Search 3.1 for the past few months.  We finally got to a point in our project where we are sucking in mass amounts of data into our application from a large business application via JMS.  Suddenly, I’m getting the following errors during persistence:

org.hibernate.AssertionFailure: collection [ class name here ] was not processed by flush()

I tried changing the owning side of the collection, made a join table, and nothing helped.  The error started when I added an @IndexEmbedded annotation to the collection, and I discovered I was missing the @ContainedIn annotation in the collection entity.  That didn’t fix it.  After weeks of doing little tweaks, breaking, fixing, breaking, fixing, I finally discovered the problem.  I was using an older manual for Hibernate Search (3.0 specifically) and I had the following configuration parameter pushed into my SessionFactory:

hibernate.search.worker.batch_size = 1

As of Hibernate Search 3.1, that parameter has been deprecated.  It has been replaced by a number of other settings allowing finer-grained control over your batch processing in Hibernate Search.  Eventually we’re upgrading to Hibernate Search 3.2 which handles batches altogether differently/better.  Thought I’d share, because this one had me stumped.

Google App Engine & Java

So I’ve spent a few days going over Google App Engine for Java.  So far, I have to say, I’m impressed.  Google has created a really cool service that lets anyone write a Java web application and host it on their multitude of servers.  This is all for free, I might add.  You have to be aware of a number of limitations including no threading and you’re limited to their data store for persistence.  Once you get over that, you’ll see the advantage of it:

  1. Reliability
  2. Durability
  3. Security
  4. Scalability

So I got a little overwhelmed with the “ity” words, but it’s very appropriate.  App Engine for Java will take the “cloud” by storm, I think.  I have been looking for a Java web host and am always discouraged by the price and the limitation on memory and disk space.  With Google, you can get a decently sized application running for free and they provide all the nuts & bolts.

Nice, Google.  Computing in the cloud isn’t such a farce as I thought it was.

Microsoft WCF Web Services & Java

I spent a good 50+ hours on trying to consume a Microsoft WCF secure web service with a Java solution.  I tried Spring Web Services, Axis2, and looked at Metro/Tango and decided Axis2 was the “easiest” solution.  The web service I’m connecting to implements WS-Security, WS-SecureConversation, WS-Policy, WS-Trust and WS-Addressing (at least) and it’s provided through a .NET 3.5 WCF endpoint.

It doesn’t work.

Axis2 can’t handle SpNego which is a WCF closed protocol allowing two WCF machines to negotiate the credentials between them.  The client has spent way too much money paying me to continue to figure out a Java solution, so I wrote a .NET 3.5 C# client.  Took me literally five lines of code and it’s working.  That’s great for .NET developers but a whole lotta horse shit for the rest of the world.  I’m hoping Axis2’s Rampart module is updated to play nice with WS-SecureConversation and a .NET WCF web service.  Until then, I’m using the .NET client to download the data and I’m storing the SOAP body into a database table.  On the Java side, I’m still using JAXB2 to unmarshall the data into Java objects and process it through our existing persistence framework.

Go me!