Spring MVC - Convert XML Message to Object using @RequestBody and @ResponseBody

[Updated: Jun 16, 2017, Created: Mar 1, 2016]

By default Spring provides support for XML content-type to backing object conversion by using Jaxb2RootElementHttpMessageConverter. We just need to use @RequestBody or @ResponseBody on the target type.


Let's see some examples.


Create Backing Object

package com.logicbig.example;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@XmlRootElement
public class User implements Serializable {
    private Long id;
    private String name;
    private String password;
    private String emailAddress;

    //getters and setters
}

Note that we have to use JAXB bind annotations for message conversion to work.


Using @RequestBody in our Controller

@Controller
@RequestMapping("users")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "register",
                    method = RequestMethod.POST,
                    consumes = MediaType.APPLICATION_XML_VALUE)
    @ResponseStatus(HttpStatus.CREATED)
    public void handleXMLPostRequest (@RequestBody User user) {
        System.out.println(user);
        userService.saveUser(user);
    }
}

The Unit test

Using Spring MVC Test Framework:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class RegistrationControllerTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup () {
        DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
        this.mockMvc = builder.build();
    }

    @Test
    public void testUserController () throws Exception {
        ResultMatcher ok = MockMvcResultMatchers.status()
                                                .isOk();

        MockHttpServletRequestBuilder builder =
                            MockMvcRequestBuilders.post("/users/register")
                                                  .contentType(MediaType.APPLICATION_XML)
                                                  .content(createUserInXml(
                                                                      "joe",
                                                                      "joe@example.com",
                                                                      "abc"));

        this.mockMvc.perform(builder)
                    .andExpect(MockMvcResultMatchers.status()
                                                    .isCreated());
    }

    private static String createUserInXml (String name, String email, String password) {
        return "<user>" +
        "<name>" + name + "</name>" +
        "<emailAddress>" + email + "</emailAddress>" +
        "<password>" + password + "</password>" +
        "</user>";
    }
}


Using @ResponseBody in our Controller

In this example we are going to show how to return a List of users. JAXB requires to wrap the collection in a separate class to handle generic properly:

package com.logicbig.example;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement
public class UserList {
    private List<User> users;
    //getter and setter
}


@Controller
@RequestMapping("users")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET,
                  produces = MediaType.APPLICATION_XML_VALUE)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public UserList handleAllUserRequest () {
        UserList list = new UserList();
        list.setUsers(userService.getAllUsers());
        return list;
    }
}



The Unit test

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class RegistrationControllerTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup () {
        DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
        this.mockMvc = builder.build();
    }

    @Test
    public void testUserController () throws Exception {
        ResultMatcher ok = MockMvcResultMatchers.status()
                                                .isOk();

        MockHttpServletRequestBuilder builder =
                            MockMvcRequestBuilders.post("/users/register")
                                                  .contentType(MediaType.APPLICATION_XML)
                                                  .content(createUserInXml(
                                                                      "joe",
                                                                      "joe@example.com",
                                                                      "abc"));

        //create one more user
        this.mockMvc.perform(builder)
                    .andExpect(MockMvcResultMatchers.status()
                                                    .isCreated());

        builder = MockMvcRequestBuilders.post("/users/register")
                                        .contentType(MediaType.APPLICATION_XML)
                                        .content(createUserInXml("mike",
                                                                 "mike@example.com",
                                                                 "123"));

        this.mockMvc.perform(builder)
                    .andExpect(MockMvcResultMatchers.status()
                                                    .isCreated());

       //getting all users and print them
        builder = MockMvcRequestBuilders.get("/users")
                                        .accept(MediaType.APPLICATION_XML);
        this.mockMvc.perform(builder)
                    .andExpect(MockMvcResultMatchers.status()
                                                    .isOk())
                    .andDo(MockMvcResultHandlers.print());

    }
 ....
}


Output:

saving user: User{id=null, name='joe', password='abc', emailAddress='joe@example.com'}
saving user: User{id=null, name='mike', password='123', emailAddress='mike@example.com'}

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /users
       Parameters = {}
          Headers = {Accept=[application/xml]}

Handler:
             Type = com.logicbig.example.UserController
           Method = public com.logicbig.example.UserList com.logicbig.example.UserController.handleAllUserRequest()

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[application/xml]}
     Content type = application/xml
             Body = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><userList><users><emailAddress>joe@example.com</emailAddress><id>1</id><name>joe</name><password>abc</password></users><users><emailAddress>mike@example.com</emailAddress><id>2</id><name>mike</name><password>123</password></users></userList>
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

Example Project

Dependencies and Technologies Used :

  • Spring Web MVC 4.2.4.RELEASE: Spring Web MVC.
  • Spring TestContext Framework 4.2.4.RELEASE: Spring TestContext Framework.
  • Java Servlet API 3.0.1
  • JUnit 4.12: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
  • JDK 1.8
  • Maven 3.0.4

Spring Xml Message Conversion Select All Download
  • spring-xml-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
      • test
        • java
          • com
            • logicbig
              • example

See Also