views:

1228

answers:

4

I've been facing this issue where, the hibernate objects on serialization produces unexpect xmls containing all the instrumented code from Hibernate.

We did some cleaning of the object before serializing the object.

But, is there a standard option available to serialize the object directly?

+1  A: 

I've not used XStream before, but I have serialized Hibernate-managed entities. It isn't fun.

There are two big issues:

  • Lazy loading;
  • One-to-many relationships.

The former is obvious - you need the actual data to serialize. The latter is less so - any one-to-many relationships you declare against collection interfaces (eg: Set<T>) will get plugged by Hibernate's own (unserializable!) collection implementations. This may well be where Hibernate's classes are bleeding into your objects.

I ended up writing reflective code (actually introspective) that did this:

  1. With the session open, touched the entire object graph to force-load any unloaded entities;
  2. Closed the Hibernate session (including any transactions involving its connection);
  3. Walked the object graph, replacing any lists, sets or maps with instances of ArrayList, HashSet or HashMap (known-serializable collections).

Note that step 2 is important - if you replace the collections prior to closing the session, Hibernate will just put its own collections right back upon close...

Edit: @brd6644 spotted a detail of the implementation I forgot to mention: if you do this, you need to limit object graph walking only to your own entities, and watch for circular reference paths (eg: by caching references to objects you've already walked).

Dan Vinton
+1  A: 

There is some info on this (and sample code) over at the Codehaus JIRA:

http://jira.codehaus.org/browse/XSTR-226

We wrote some tools to work around this sort of issue for a bunch of other remoting implementations (Axis 1, Blaze DS, etc). What we did is very similar to Dan's solution, although we added the ability to declare which object paths to walk and which to "snip" because in many situations we were not interested in all the data; it also would have led to serious issues with the "n+1 selects" problem happening thousands of times! :) I think implementing an XStream converter would be the optimal approach since you'd only have to walk the object graph once. If you set FlushMode.MANUAL on your Session you should also be able to modify the object graph as you go without Hibernate doing anything nasty. Use this with caution though as it's a somewhat advanced technique.

cliff.meyers
Whoops, forgot to initially mention limiting object types to descend into (your snip syntax) - thanks for the correction...
Dan Vinton
A: 

I faced a similar problem although Im not using hibernate. I looked at the enitity-pruner but its not quite what i was looking for as I was looking for a more simpler solution.

I came up with a very simple solution using reflection that deproxies CGLIB enhaned objects like a charm.

please visit http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/ for example and code.

anzaan
A: 

Instead of XStream you could use EclipseLink MOXy (a JAXB implementation) to marshal your entities to XML. EclipseLink also contains a JPA implementation (the JPA RI, open sourced from TopLink).

Here are some examples:

Blaise Doughan
Not sure where all the down votes are coming from all of a sudden. I am simply offering that MOXy a tool specifically written for supporting marshalling JPA entities to XML (with years of experience from TopLink/EclipseLink) may be a better fit than XStream.
Blaise Doughan