2012-09-20 17 views
8

Tengo un número de entidades con anotaciones JAXB que me gustaría convertir a JSON utilizando un convertidor de mensajes.Registrer MappingJackson2HttpMessageConverter en Spring 3.1.2 con anotaciones JAXB

Yo sé que mi ObjectMapper que lee las anotaciones JAXB funciona:

String correctJsonText = jacksonObjectMapper.writeValueAsString(entityWithJAXB); 

Pero cuando llamo mi servicio resto del defecto registrado MappingJacksonHttpMessageConverter (que no está configurado para la lectura de JAXB) parece tomar más - lo que resulta en un stackoverflow debido a referencias cíclicas cuando se ignora @XmlTransient ...

¿Cómo configuro Spring para utilizar MappingJackson2HttpMessageConverter?

configuración actual

<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> 

servicio REST

@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); 
} 

Dependencias

<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> 

ACTUALIZACIÓN/Solución

Al depurar mi contexto, pude ver que la configuración en <mvc:annotation-driven> no tuvo ningún efecto.

Resultó que mi prueba unitaria con MockMcv siempre cargaba los controladores de dirección predeterminados, ignorando así mi mapa de objetos personalizado. Por conveniencia solo probé el controlador usando la prueba junit, ya que golpeó el controlador muy bien. No pensé en esto como un probable error, porque ...

Aún no he encontrado una solución para mi prueba, pero cuando Llamo al servicio usando curl ¡todo funciona!

ACTUALIZACIÓN/solución final

Sólo se encontró una solución para mi configuración de la prueba; cuando se utiliza MockMvc (primavera-test-MVC) debe especificar personalizados mensaje convertidores explícita:

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()); 
} 

La única cuestión que queda es que el jacksonMessageConverter no se puede autowired directamente hasta el siguiente JIRA se resuelve: https://jira.springsource.org/browse/SPR-9469. Hasta entonces, acabo de crear una copia del jacksonMessageConverter en mi contexto de prueba.

Respuesta

3

He replicado su configuración y funciona perfectamente para mí. Los conversores de mensajes predeterminados no deberían tener efecto, ya que ha especificado explícitamente el atributo register-defaults=false. Así es como se ve mi anotación @XmlTransient:

@XmlAccessorType(XmlAccessType.FIELD) 
public class EntityWithJAXB { 


    @XmlTransient 
    private EntityWithJAXB aChild; 
+0

Gracias, eso es información valiosa! mis anotaciones @Xml están en getters y setters en su lugar, pero no creo que esto haga la diferencia. Puede que haya otras cosas en mi configuración que estropeen las cosas ... Trataré de mover la configuración de jackson a un proyecto limpio para ver si me funciona. Publicaré la solución cuando la encuentre. – molholm

+1

Hice que la configuración funcione en un proyecto limpio tal como lo hizo, sin problemas.Sospeché que el problema fue causado por un WebServiceMessageReceiverHandlerAdapter que hace que el servlet de envío no cargue los adaptadores predeterminados o algún otro problema de configuración, pero no fue así. – molholm

+0

Actualizo la publicación original con la solución, ¡gracias! – molholm

Cuestiones relacionadas