When use ResponseEntity<T> and @RestController for Spring RESTful applications

Manuel Jordan picture Manuel Jordan · Oct 24, 2014 · Viewed 270.4k times · Source

I am working with Spring Framework 4.0.7, together with MVC and Rest

I can work in peace with:

  • @Controller
  • ResponseEntity<T>

For example:

@Controller
@RequestMapping("/person")
@Profile("responseentity")
public class PersonRestResponseEntityController {

With the method (just to create)

@RequestMapping(value="/", method=RequestMethod.POST)
public ResponseEntity<Void> createPerson(@RequestBody Person person, UriComponentsBuilder ucb){
    logger.info("PersonRestResponseEntityController  - createPerson");
    if(person==null)
        logger.error("person is null!!!");
    else
        logger.info("{}", person.toString());

    personMapRepository.savePerson(person);
    HttpHeaders headers = new HttpHeaders();
    headers.add("1", "uno");
    //http://localhost:8080/spring-utility/person/1
    headers.setLocation(ucb.path("/person/{id}").buildAndExpand(person.getId()).toUri());

    return new ResponseEntity<>(headers, HttpStatus.CREATED);
}

to return something

@RequestMapping(value="/{id}", method=RequestMethod.GET)
public ResponseEntity<Person> getPerson(@PathVariable Integer id){
    logger.info("PersonRestResponseEntityController  - getPerson - id: {}", id);
    Person person = personMapRepository.findPerson(id);
    return new ResponseEntity<>(person, HttpStatus.FOUND);
}

Works fine

I can do the same with:

  • @RestController (I know it is the same than @Controller + @ResponseBody)
  • @ResponseStatus

For example:

@RestController
@RequestMapping("/person")
@Profile("restcontroller")
public class PersonRestController {

With the method (just to create)

@RequestMapping(value="/", method=RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void createPerson(@RequestBody Person person, HttpServletRequest request, HttpServletResponse response){
    logger.info("PersonRestController  - createPerson");
    if(person==null)
        logger.error("person is null!!!");
    else
        logger.info("{}", person.toString());

    personMapRepository.savePerson(person);
    response.setHeader("1", "uno");

    //http://localhost:8080/spring-utility/person/1
    response.setHeader("Location", request.getRequestURL().append(person.getId()).toString());
}

to return something

@RequestMapping(value="/{id}", method=RequestMethod.GET)
@ResponseStatus(HttpStatus.FOUND)
public Person getPerson(@PathVariable Integer id){
    logger.info("PersonRestController  - getPerson - id: {}", id);
    Person person = personMapRepository.findPerson(id);
    return person;
}

My questions are:

  1. when for a solid reason or specific scenario one option must be used mandatorily over the other
  2. If (1) does not matter, what approach is suggested and why.

Answer

Sotirios Delimanolis picture Sotirios Delimanolis · Oct 24, 2014

ResponseEntity is meant to represent the entire HTTP response. You can control anything that goes into it: status code, headers, and body.

@ResponseBody is a marker for the HTTP response body and @ResponseStatus declares the status code of the HTTP response.

@ResponseStatus isn't very flexible. It marks the entire method so you have to be sure that your handler method will always behave the same way. And you still can't set the headers. You'd need the HttpServletResponse or a HttpHeaders parameter.

Basically, ResponseEntity lets you do more.