posting xml to a spring REST endpoint is not getting unmarshalled into the relevant Java object

13,357

Solution 1

I was running across the same issue as well. Here's what my Controller method looked like:

@RequestMapping(method=RequestMethod.POST, value="/users/create",
        headers="Accept=application/xml")
public @ResponseBody User createUser(@RequestBody User user) {
    return user;
}

Basically, I was just going to return the user object as a proof-of-concept to make sure that my POST was working correctly. However, I kept running into the 'syntactically incorrect' message. Once I actually updated my code to retrieve a valid User object like so:

@RequestMapping(method=RequestMethod.POST, value="/users/create",
        headers="Accept=application/xml")
public @ResponseBody User createUser(@RequestBody User user) {
    userService.createUser(user);
    // do work
    User newUser = userService.getUserById(user.getId());
    return newUser;
}

it started working correctly.

I tested my REST API using the following CURL command:

curl -X POST -HContent-type:application/xml -HAccept:application/xml --data "<user><username>Quinnster</username><password>password</password></user>" http://localhost:8080/api/users/create

Using a different API to list users, I was able to verify that my new user was created properly.

Again, not sure if this is the exact same problem you're having, but this solved it for me.

Thanks, Quinn

Solution 2

You might try change the @RequestMapping on the class from:

@RequestMapping("/users")

to:

@RequestMapping("/users/*")

And then change the method declaration to:

@RequestMaqpping(method=RequestMethod.POST)
@ResponseBody
public void  create(@RequestBody User user) {

The url would then become: http://localhost:8080/rest/users/create, because spring will take the final portion of the url from the method name.

Share:
13,357
Uma Shankar
Author by

Uma Shankar

Updated on June 05, 2022

Comments

  • Uma Shankar
    Uma Shankar almost 2 years

    I have a project where xsd are given. I use the xjc compiler to generate the Java classes. And then I annotate the class with XmlRootElement attribute. I have configured the sevlet with the Jaxb2 marshalling/unmarshalling bean in the AnnotationMethodHandlerAdapter. when I send an xml, without the namespaces, I get the 415 error.

    The source code is as follows file - web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>Test</display-name>
      <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/rest/*</url-pattern>
      </servlet-mapping>
    </web-app>
    

    file - dispatcher-servlet.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"
        xmlns:oxm="http://www.springframework.org/schema/oxm">
    
        <context:component-scan base-package="com.test.endpoints" />
    
        <tx:annotation-driven />
    
        <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
            <property name="messageConverters">
              <list> 
                <ref bean="marshallingHttpMessageConverter"/>
              </list>
            </property>
        </bean>
        <bean id="marshallingHttpMessageConverter" 
              class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
               <constructor-arg ref="jaxb2Marshaller" />
        </bean> 
        <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            <property name="classesToBeBound">
                <list>
                    <value>com.test.users.User</value>
                    <value>com.test.users.Users</value>
                </list>
            </property>
        </bean>
        <!-- Should be defined last! -->
    <!--    <mvc:annotation-driven />-->
    </beans>
    

    file - user.xsd

        <element name="users">
            <complexType>
                <sequence>
                    <element name="user" type="tns:user" minOccurs="0"
                        maxOccurs="unbounded" />
                </sequence>
            </complexType>
        </element>
        <complexType name="user">
            <sequence>
                <element name="id" type="int" />            
                <element name="email" type="string"></element>
                <element name="first_name" type="string"></element>
                <element name="last_name" type="string"></element>          
            </sequence>
        </complexType>
    </schema>
    

    Used this command to generate the Java classes for the above xsd.

    xjc -p com.test.users ..\xsd\user.xsd
    

    Output of this command is

    parsing a schema...
    compiling a schema...
    com\test\users\ObjectFactory.java
    com\test\users\User.java
    com\test\users\Users.java
    com\test\users\package-info.java
    

    Annotated User.java with @XmlRootElement(name="user").

    file - UserService.java

    package com.test.endpoints;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.test.users.User;
    
    @Controller
    @RequestMapping("/users")
    public class UserService {
        @RequestMapping(value="/new", method=RequestMethod.POST)
        @ResponseBody
        public User createUser(@RequestBody User user) {
            System.out.println(user.getFirstName());
    
            return user;
        }
    }
    

    Tested the REST api with this curl command

    curl -X POST -HContent-type:application/xml -HAccept:application/xml  --data "<?xml version="1.0" encoding="UTF-8"?><user><id>1</id><email>[email protected]</email><first_name>first_name</first_name><last_name>last_name</last_name></user>" http://localhost:8080/Test/rest/users/new
    

    Output is

    The request sent by the client was syntactically incorrect ()
    

    Can somebody please point me where I am going wrong.

    Thanks