Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

post xml to Spring REST server returns Unsupported Media Type

I'm trying to create a simple spring based webservice that supports a "post" with xml content.

In spring, I define an 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>

And a jaxb based xml marshaller:

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

My controller is annotated as follows, where "Resource" is a class autogenerated by jaxb:

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

The result of a webservice call is always "HTTP/1.1 415 Unsupported Media Type". Here is an example service call:

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

It seems to me that I am setting the correct media type everywhere possible. Anyone have an ideas?

Edit: after further debugging, it looks as though it never gets as far as trying to unmarshal the object. I don't quite understand the black magic behind how the AnnotationMethodHandler knows that something of type application/xml should go to the MarshallingHttpConverter. Can anyone shed any light on that?

like image 842
Cheryl Simon Avatar asked Mar 08 '10 22:03

Cheryl Simon


1 Answers

The most likely reason is that the JAXB context doesn't know how to unmarshal to a Resource object.

Does Resource have an @XMLRootElement annotation? If not, then Jaxb2Marshaller will not accept the parameter, and you'll get the 415 error. This is done by delegation from Sprng to the JAXB runtime, Spring doesn't really have much say in the matter.

edit: The actual coercion of the data on to the @RequestBody parameter is done in HandlerMethodInvoker.resolveRequestBody(). There are quite a number of conditions that must be met before the match is made, including matching of MIME type and parameter class type, and if it fails, there's no logging, just the HTTP 415. Have a look at the source for that method, and better yet, do some remote debugging to see where the logic is failing for your setup.

like image 123
skaffman Avatar answered Oct 31 '22 18:10

skaffman