posting xml to a spring REST endpoint is not getting unmarshalled into the relevant Java object
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@email.com</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
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
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.
Try change the curl line to
curl -X POST -HContent-type:application/xml -HAccept:application/xml \
--data '<?xml version="1.0" encoding="UTF-8"?><user><id>1</id><email>email@email.com</email><first_name>first_name</first_name><last_name>last_name</last_name></user>' \
http://localhost:8080/Test/rest/users/new
Their were quotation marks in the XML which may have interfered with the input
精彩评论