I have a Java Spring 3.2 + Hibernate project.
I used jackson2 annotations (com.fasterxml.jackson.annotation) in the model, and I (guess) the spring rest controller should use jackson2 (aka com.fasterxml.jackson) when serializing the requested objects.
I configured the application with:
<!-- Use the HibernateAware mapper instead of the default -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="myProj.util.HibernateAwareObjectMapper">
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
The HibernateAwareObjectMapper
is defined this way:
package myProj.util;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HibernateAwareObjectMapper extends ObjectMapper {
private static final long serialVersionUID = -5002954669679467811L;
public HibernateAwareObjectMapper() {
Hibernate4Module hbm = new Hibernate4Module();
hbm.enable(Hibernate4Module.Feature.FORCE_LAZY_LOADING);
registerModule(hbm);
}
}
so I can state that it extends the com.fasterxml ObjectMapper
(OTOH I'm not sure why it was added, since I just inherited the code from other developers).
Note that from what I know spring3.2 should use jackson2 by default.
This is mostly working fine but then I have a serialization issue which only happens with a specific service/controller. I have an object which defines a parent, containing the same object as a child. This is resulting in a serialization loop, which ends with an exception on the server side:
[...]
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
[...]
and an incomplete JSON sent to the client.
This is the controller code:
@RequestMapping(value = "/getReleases", method = RequestMethod.POST)
public Map<String, Object> getReleases(@RequestBody Project project) {
Map<String, Object> subProjectsMap = new HashMap<String, Object>();
List<Release> releaseList = null;
try {
releaseList = jiraService.getReleases(project);
subProjectsMap.put("success", (releaseList.size() > 0) ? true : false);
subProjectsMap.put("data", releaseList);
} catch (Exception e) {
e.printStackTrace();
}
return subProjectsMap;
}
Serialization is performed implicitly by the framework.
The question is: why is spring apparently using org.codehaus.jackson rather than com.fasterxml.jackson as I would expect? Note that the model describing the serialized object is using jackson2 annotations (in particular @JsonBackReference and @JsonIgnore), so they are possibly ignored when using jackson1, which (I think) may result in the loop issue.
After many hours spent banging my head I still don't know why this is happening. Can you provide any hint?