Spring MVC - Building RESTful Web Service using @RestController

[Updated: Aug 16, 2017, Created: Mar 4, 2016]

It's a very common use case to have Controllers implement a REST API, thus serving only JSON, XML or custom MediaType content. For convenience, instead of annotating all your @RequestMapping methods with @ResponseBody, you can annotate your Controller Class with @RestController.

@RestController is a stereotype annotation that combines @ResponseBody and @Controller. More than that, it gives more meaning to your Controller and also may carry additional semantics in future releases of the framework.



The annotation @RestController is meta annotated with @Controller and @ResponseBody, that means we don't have to explicitly annotate our handler methods with @ResponseBody, but we still have to use @RequestBody in our handler method parameters.


Example using @RestController


Create Backing Object

public class User implements Serializable {
    private Long id;
    private String name;
    private String password;
    private String emailAddress;

    //getters and setters
}




Create Controller

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

    @Autowired
    private UserService userService;

    @RequestMapping(value = "register", method = RequestMethod.POST,
                        consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.CREATED)
    public void handleJsonPostRequest (@RequestBody User user, Model model) {
        System.out.println("saving user: "+user);
        userService.saveUser(user);
    }

    @RequestMapping(method = RequestMethod.GET,
                        produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.OK)
    public List<User> handleAllUserRequest () {
        return userService.getAllUsers();
    }
}



Unit Test

Using Spring MVC Test Framework

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

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

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

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

       // create one more user
        builder = MockMvcRequestBuilders.post("/users/register")
                                        .contentType(MediaType.APPLICATION_JSON)
                                        .content(createUserInJson("mike",
                                                                  "mike@example.com",
                                                                  "123"));

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

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

    }

    private static String createUserInJson (String name, String email, String password) {
        return "{ \"name\": \"" + name + "\", " +
                            "\"emailAddress\":\"" + email + "\"," +
                            "\"password\":\"" + password + "\"}";
    }
}


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/json]}

Handler:
             Type = com.logicbig.example.UserController
           Method = public java.util.List<com.logicbig.example.User> 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/json]}
     Content type = application/json
             Body = [{"id":1,"name":"joe","password":"abc","emailAddress":"joe@example.com"},{"id":2,"name":"mike","password":"123","emailAddress":"mike@example.com"}]
    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.
  • jackson-databind 2.7.2: General data-binding functionality for Jackson: works on core streaming API.
  • JDK 1.8
  • Maven 3.0.4

Spring Rest Controller Example Select All Download
  • spring-rest-controller
    • src
      • main
        • java
          • com
            • logicbig
              • example
      • test
        • java
          • com
            • logicbig
              • example

See Also