I have a number of entities with JAXB annotations that I would like to convert to JSON using a message-converter.
I know that my ObjectMapper that reads the JAXB annotations works:
String correctJsonText = jacksonObjectMapper.writeValueAsString(entityWithJAXB);
But when i call my rest service the default registered MappingJacksonHttpMessageConverter (which is not configured for reading JAXB) seems to take over - resulting in a stackoverflow due to cyclic references when @XmlTransient is ignored...
How do i configure Spring to use MappingJackson2HttpMessageConverter ?
Current Configuration
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application" />
<constructor-arg index="1" value="json" />
<constructor-arg index="2" value="UTF-8" />
</bean>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="jaxbAnnotationInspector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />
<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="annotationIntrospector" ref="jaxbAnnotationInspector" />
</bean>
REST service
@RequestMapping(value="/{id}", method=RequestMethod.GET, produces = "application/json;charset=UTF-8")
public @ResponseBody EntityWithJAXB readEntityWithJAXB(@PathVariable int id, Model model) {
return entityService.getById(id);
}
Dependencies
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.0.5</version>
</dependency>
UPDATE / Solution
By debugging my context I could see that the configuration in <mvc:annotation-driven>
had no effect.
It turned out that my unit test with MockMcv always loaded the default handleradapters, thus ignoring my custom objectmapper. Due to convenience I only tested the controller using junit test, since it hit the controller just fine I did not think of this as a probable error cause...
I did not find a fix for my test yet, but when I call the service using curl everything works!
UPDATE / Final solution
Just found a solution for my test setup; when using MockMvc (spring-test-mvc) you must specify custom message-converters explicit:
private MockMvc mockMvc;
@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
@Autowired
private RestController restController;
@Before
public void initMockMvc(){
mockMvc = MockMvcBuilders.standaloneSetup(restController)
.setMessageConverters(jacksonMessageConverter).build();
}
@Test
public void testRestController() throws Exception{
DefaultRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/json/42");
this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}
The only remaining issue is that the jacksonMessageConverter
can't be autowired directly until the following JIRA is resolved: https://jira.springsource.org/browse/SPR-9469. Until then, I have just created a copy of the jacksonMessageConverter in my test context.
See Question&Answers more detail:
os