2010-03-08 6 views
6

Próbuję utworzyć prosty serwis internetowy oparty na źródle, który obsługuje "post" z zawartością XML.po xml do Spring REST server zwraca Nieobsługiwany typ nośnika

Na wiosnę, I zdefiniować AnnotationMethodHandler:

<bean id="inboundMessageAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
     <property name="messageConverters"> 
      <util:list> 
       <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> 
        <property name="marshaller" ref="xmlMarshaller"/> 
        <property name="unmarshaller" ref="xmlMarshaller"/> 
       </bean> 
      </util:list> 
     </property> 
    </bean> 

I JAXB oparte xml naziemnego:

<bean id="xmlMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
     <property name="contextPaths"> 
      <array> 
       <value>com.company.schema</value> 
      </array> 
     </property> 
     <property name="schemas"> 
      <array> 
       <value>classpath:core.xsd</value> 
      </array> 
     </property> 
    </bean> 

Moje kontroler jest odnotowany w następujący sposób, gdzie "zasób" jest klasą wygenerowany automatycznie przez JAXB :

@RequestMapping(method = POST, value = "/resource") 
    public Resource createResource(@RequestBody Resource resource) { 
     // do work 
    } 

Wynikiem wywołania usługi internetowej jest zawsze "HTTP/1.1 415 Nieobsługiwany plik Med ia Wpisz ". Oto przykładowa rozmowa serwisowa:

HttpPost post = new HttpPost(uri); 
post.addHeader("Accept", "application/xml"); 
post.addHeader("Content-Type", "application/xml"); 

StringEntity entity = new StringEntity(request, "UTF-8"); 
entity.setContentType("application/xml"); 
post.setEntity(entity); 

Wydaje mi się, że ustawiam właściwy typ mediów wszędzie, gdzie to możliwe. Ktoś ma pomysły?

Edycja: po dalszym debugowaniu wygląda na to, że nigdy nie jest tak daleko, jak próba zwolnienia obiektu. Nie bardzo rozumiem czarną magię stojącą za tym, jak AnnotationMethodHandler wie, że coś typu application/xml powinno trafić do MarshallingHttpConverter. Czy ktoś może rzucić na to jakiekolwiek światło?

Odpowiedz

5

Najbardziej prawdopodobną przyczyną jest to, że kontekst JAXB nie wie, jak usunąć niestosowny do obiektu Resource.

Czy Resource ma adnotację @XMLRootElement? Jeśli nie, to Jaxb2Marshaller nie zaakceptuje parametru, a otrzymasz błąd 415. Odbywa się to przez delegację Sprnga do środowiska wykonawczego JAXB, Spring nie ma wiele do powiedzenia w tej sprawie.

edit: Rzeczywista przymus danych na parametr @RequestBody odbywa się w HandlerMethodInvoker.resolveRequestBody(). Istnieje wiele warunków, które muszą zostać spełnione przed dopasowaniem, w tym dopasowanie typu MIME i typu klasy parametrów, a jeśli się nie powiedzie, nie ma rejestrowania, tylko HTTP 415. Spójrz na źródło tej metody , a jeszcze lepiej, wykonaj zdalne debugowanie, aby zobaczyć, gdzie logika zawodzi w twojej konfiguracji.

+0

Dzięki za sugestię, skaffman. Sprawdzam, a klasa rzeczywiście ma znacznik @XMLRootElement. –

+0

@Mayra: A 'Resource' jest w pakiecie' com.company.schema'? Spróbuj napisać test jednostkowy, który skonstruuje 'Jaxb2Marshaller' z twoją konfiguracją i upewnij się, że' support (Resource.class) 'zwraca' true'. To musi zadziałać, zanim będziesz mógł się posunąć dalej. – skaffman

+0

Bez kostki, utworzyłem obiekt Jaxb2Marshaller, ustawiłem ścieżkę contextPath i schemat tak jak w moim pliku źródłowym i napisałem, że obsługuje moją klasę. –