Spring MVC: using @ResponseStatus(reason = '') on a @ResponseBody exception handler in tomcat

11,904

Solution 1

It seems that this is a direct result of the following code from AnnotationMethodHandlerExceptionResolver

private ModelAndView getModelAndView(Method handlerMethod, Object returnValue, ServletWebRequest webRequest)
        throws Exception {

    ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
    if (responseStatusAnn != null) {
        HttpStatus responseStatus = responseStatusAnn.value();
        String reason = responseStatusAnn.reason();
        if (!StringUtils.hasText(reason)) {
            // this doesn't commit the response
            webRequest.getResponse().setStatus(responseStatus.value());
        }
        else {
            // this commits the response such that any more calls to write to the 
            // response are ignored
            webRequest.getResponse().sendError(responseStatus.value(), reason);
        }
    }
    /// snip
}

This has been reported to Springsource in SPR-8251:

Solution 2

For the record, since Spring 3.2, this got even worse because the AnnotationMethodHandlerExceptionResolver has been replaced by the ResponseStatusExceptionResolver and it does:

protected ModelAndView resolveResponseStatus(ResponseStatus responseStatus, HttpServletRequest request,
  HttpServletResponse response, Object handler, Exception ex) throws Exception {

  int statusCode = responseStatus.value().value();
  String reason = responseStatus.reason();
  if (this.messageSource != null) {
    reason = this.messageSource.getMessage(reason, null, reason, LocaleContextHolder.getLocale());
  }
  if (!StringUtils.hasLength(reason)) {
    response.sendError(statusCode);
  }
  else {
    response.sendError(statusCode, reason);
  }
  return new ModelAndView();
}

This is worth a bug report. Moreover, the @ResponseStatus is documented with setStatus and is ill-designed. It should have been called @ResponseError.

I have created two issues for this finally: SPR-11192 and SPR-11193.

Almost a year has passed and my two issues are still open. I do not consider Spring WebMVC as a first-class REST framework which it isn't imho, WebMVC is for humas and not machines :-(

Share:
11,904

Related videos on Youtube

Gareth Davis
Author by

Gareth Davis

programmer that just loves that coding thing. Logical Practice Systems Me on Twitter

Updated on June 04, 2022

Comments

  • Gareth Davis
    Gareth Davis almost 2 years

    Does anybody know why I cannot use @ResponseStatus(reason = "My message") on an exception handler in spring MVC while still returning a @ResponseBody. What seems to happen is that if I use the reason attribute

    // this exception handle works, the result is a 404 and the http body is the json serialised
    // {"message", "the message"}
    @ExceptionHandler
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public Map<String, String> notFoundHandler(NotFoundException e){
        return Collections.singletonMap("message", e.getMessage());
    }
    
    // this doesn't... the response is a 404 and the status line reads 'Really really not found'
    // but the body is actually the standard Tomcat 404 page
    @ExceptionHandler
    @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Really really not found")
    public Map<String, String> reallyNotFoundHandler(ReallyNotFoundException e){
        return Collections.singletonMap("message", e.getMessage());
    }
    

    The code for this example is over on github.

  • Michael-O
    Michael-O over 8 years
    @BartoszKP Why did you removed the edits on MY answer?
  • BartoszKP
    BartoszKP over 8 years
    1) I only edited out "edit indicators". The answer should be consistent as a whole, the fact which part was added when is completely irrelevant to a person looking for a solution to their problem. Should someone be interested in post's history, it is still easily available. 2) This is not your answer. You are the author, but it belongs to SO.
  • Michael-O
    Michael-O over 8 years
    @BartoszKP Ridiculous, seriously!
  • BartoszKP
    BartoszKP over 8 years
    What is it that you don't understand? I've improved your post (removed redundant information that's not relevant to the technical issue you've provided solution for). You are free to rollback my edit, and I won't go into an edit war with you. However, please do consider the arguments I've provided in the context SO's rules.

Related