That means that when your JSON serialization happens your Hibernate session is closed. Adding this to your web.xml might help (this is for JPA, if you are using pure Hibernate, there is a Hibernate filter for that too):
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
If that doesn't help, you might need to override Gson's mapper to account for uninitialized persistent collections, here is some code for that:
import org.hibernate.collection.internal.AbstractPersistentCollection;
public class PersistentCollectionUtils {
public boolean isAbstractPersistentCollection(Object object) {
return object instanceof AbstractPersistentCollection;
}
public boolean wasAbstractPersistentCollectionInitialized(Object collection) {
return ((AbstractPersistentCollection) collection).wasInitialized();
}
public boolean isObjectSafeToUse(Object object) {
return isAbstractPersistentCollection(object) ?
wasAbstractPersistentCollectionInitialized(object) :
true;
}
public boolean tryToInitializeCollection(Collection<?> collection) {
if(collection != null) {
try {
collection.iterator().hasNext();
return true;
} catch (Exception t) {}
}
return false;
}
}
Below is sample code used (this particular implementation is for Dozer, but you can easily translate it into Gson's mapper/adapter version).
public class PersistentSetMapper implements CustomFieldMapper {
private PersistentCollectionUtils mapperUtils = new PersistentCollectionUtils();
@Override
public boolean mapField(Object source, Object destination, Object sourceFieldValue, ClassMap classMap, FieldMap fieldMapping) {
// return true => the field has been mapped, no need to map it further
// return false => the field was not mapped, use downstream mappers
// check if field is derived from Persistent Collection
if (!mapperUtils.isAbstractPersistentCollection(sourceFieldValue)) {
return false;
}
// check if field is already initialized
if (mapperUtils.wasAbstractPersistentCollectionInitialized(sourceFieldValue)) {
return false;
} else {
// if not initialized, try to initialize it
boolean wasInitialized = mapperUtils.tryToInitializeCollection((Collection<?>) sourceFieldValue);
if(wasInitialized) {
return false;
} else {
destination = null;
return true;
}
}
}
}