Description
I have a scenario where entities are read in a database layer, serialized to JSON and then sent via JMS to a front end server. The front end has no connection to any database, hence no SessionFactory
.
In order to avoid to have to add @JsonType
annotations everywhere, I've enabled mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
This works until a PersistentCollection
is serialized. This yields something like:
..., "types": ["...PersistentSet", {...}]
The frontend has the class (Hibernate has to be on the class path, or I couldn't access the Entity beans at all, thanks to all the annotations). The problem is that Jackson eventually calls PersistentSet.add()
which then immediately throws LazyInitializationException( "could not initialize proxy - no Session" )
.
So far the only solution I could find was to comment out if (!usesLazyLoading(property))
in PersistentCollectionSerializer
and add this code to the serialize*()
methods:
if (_serializer == null) { // sanity check...
throw new JsonMappingException("PersistentCollection does not have serializer set");
}
value = convertToJavaCollection(value); // Strip PersistentCollection
_serializer.serializeWithType(value, jgen, provider, typeSer);
Here is the code for the new method:
private Object convertToJavaCollection(Object value) {
if (!(value instanceof PersistentCollection) ) {
return value;
}
if (value instanceof Set) {
return convertToSet((Set<?>)value);
}
if (value instanceof List
|| value instanceof Bag
) {
return convertToList((List<?>)value);
}
if (value instanceof Map) {
return convertToMap((Map<?,?>)value);
}
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
private Object convertToList(List<?> value) {
return Lists.newArrayList(value);
}
private Object convertToMap(Map<?, ?> value) {
return Maps.newHashMap(value);
}
private Object convertToSet(Set<?> value) {
return Sets.newHashSet(value);
}
It would be nice if you could integrate this as a new feature into your code.