- First of all, I use Hibernate 2. I know, it's old, but it does the work and I won't fix it unless it is broken. I expect most of the advice will also apply to Hibernate 3.
- I'm aliasing all classes using
XStream.alias()
. Reason being that on the server side, some data model classes are actually subclassed for additional (although non-Hibernate) related functionality. You might or might not need this. - This is however essential: We need to ensure that XStream will treat Hibernate lists, sets, and maps as Java lists, sets, and maps. I believe this is what helps avoid the infamous "com.thoughtworks.xstream.converters.ConversionException: Cannot handle CGLIB enhanced proxies with multiple callbacks..." problem. There are three things that need to be done:
- use
Xstream.addDefaultImplementation()
to tell XStream to treat all Hibernate-enhanced collection classes as plain Java collections:xstream.addDefaultImplementation(
net.sf.hibernate.collection.List.class, java.util.List.class);
xstream.addDefaultImplementation(
net.sf.hibernate.collection.Map.class, java.util.Map.class);
xstream.addDefaultImplementation(
net.sf.hibernate.collection.Set.class, java.util.Set.class); - Finally, in order for XStream to actually handle these collections I needed to define and register some custom converters that are able to handle Hibernate collections as Java collections:
Mapper mapper = xstream.getMapper();
These custom converter classes are rather trivial, here are their definitions. All they really do is extend the XStream built-in collection and map converters, and declare their ability to handle Hibernate lists, sets, and maps:
xstream.registerConverter(new HibernateCollectionConverter(mapper));
xstream.registerConverter(new HibernateMapConverter(mapper));import net.sf.hibernate.collection.List;
and
import net.sf.hibernate.collection.Set;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.mapper.Mapper;
class HibernateCollectionConverter extends CollectionConverter {
HibernateCollectionConverter(Mapper mapper) {
super(mapper);
}
public boolean canConvert(Class type) {
return super.canConvert(type) || type == List.class || type == Set.class;
}
}import net.sf.hibernate.collection.Map;
import com.thoughtworks.xstream.converters.collections.MapConverter;
import com.thoughtworks.xstream.mapper.Mapper;
class HibernateMapConverter extends MapConverter {
HibernateMapConverter(Mapper mapper) {
super(mapper);
}
public boolean canConvert(Class type) {
return super.canConvert(type) || type == Map.class;
}
}
- use
That's all I did and it eliminated all of my Hibernate+XStream problems - hope it will also help you.