2012-09-20 14 views
8

Ho un numero di entità con annotazioni JAXB che vorrei convertire in JSON utilizzando un convertitore di messaggi.Registrer MappingJackson2HttpMessageConverter in Spring 3.1.2 con annotazioni JAXB

So che il mio ObjectMapper che legge le annotazioni JAXB funziona:

String correctJsonText = jacksonObjectMapper.writeValueAsString(entityWithJAXB); 

Ma quando chiamo il mio servizio resto il default registrato MappingJacksonHttpMessageConverter (che non è configurato per la lettura JAXB) sembra prendere il sopravvento - con conseguente uno stackoverflow dovuto a riferimenti ciclici quando @XmlTransient viene ignorato ...

Come configurare Spring per utilizzare MappingJackson2HttpMessageConverter?

configurazione corrente

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

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

Dipendenze

<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

Effettuando il debug del mio contesto, ho notato che la configurazione in <mvc:annotation-driven> non ha avuto alcun effetto.

Si è scoperto che il mio test di unità con MockMcv ha sempre caricato i handleradapters predefiniti, ignorando quindi il mio objectmapper personalizzato. A causa della praticità ho testato il controller solo con junit test, dato che ha colpito il controller bene non ho pensato a questo come un probabile errore causa ...

Non ho ancora trovato una soluzione per il mio test, ma quando Chiamo il servizio usando curl funziona tutto!

UPDATE/Soluzione finale

Appena trovato una soluzione per il mio setup di prova; quando si utilizza MockMvc (primavera-test-MVC) è necessario specificare dei messaggi convertitori personalizzati esplicito:

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 questione unica rimasta è che il jacksonMessageConverter non può essere autowired direttamente fino alla successiva JIRA è risolto: https://jira.springsource.org/browse/SPR-9469. Fino ad allora, ho appena creato una copia di jacksonMessageConverter nel mio contesto di test.

risposta

3

Ho replicato la configurazione e funziona perfettamente per me. I convertitori di messaggi predefiniti non dovrebbero avere effetto, poiché è stato esplicitamente specificato l'attributo register-defaults=false. Ecco come appare la mia annotazione @XmlTransient:

@XmlAccessorType(XmlAccessType.FIELD) 
public class EntityWithJAXB { 


    @XmlTransient 
    private EntityWithJAXB aChild; 
+0

Grazie, questa è un'informazione preziosa! le mie annotazioni @Xml si trovano invece sui getter e sui setter, ma non penso che ciò dovrebbe fare alcuna differenza. Potrebbero esserci altre cose nella mia configurazione che rovinano le cose allora ... Proverò a spostare la configurazione di Jackson in un progetto pulito per vedere se funziona per me. Pubblicherò la soluzione quando la trovo. – molholm

+1

Ho fatto funzionare la configurazione in un progetto pulito proprio come hai fatto tu, nessun problema.Sospettavo che il problema fosse causato da un WebServiceMessageReceiverHandlerAdapter che faceva sì che il dispatch-servlet non caricasse gli adattatori predefiniti o qualche altro problema di configurazione, ma non lo era. – molholm

+0

Aggiorno il post originale con la soluzione, grazie! – molholm

Problemi correlati