Spring Boot in standalone Tomcat ignores exceptions set in DeferredResults

五迷三道 提交于 2020-01-16 11:30:22

问题


I'm running a Spring Boot 1.2.1 application in standalone Tomcat.

I have two controller mappings, which both for simplicity always throw an exception. The first one is for a GET request and it returns a String for the view name:

    @RequestMapping(value = {
    "/index"
}, method = RequestMethod.GET)
public String init() throws MyRequestProcessingException {
    if (true) {
    throw new MyRequestProcessingException(
            "Something went wrong processing request");
    }
    return "init";
}

This is the exception definition:

@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
public class MyRequestProcessingException extends Exception {

public MyRequestProcessingException(String message) {
    super(message);
}   
}

In embedded Tomcat as well as in standalone Tomcat, trying to access /index always results in a 500 with some JSON error data being returned to the client.

My controller has another method which accepts a POST and returns a DeferredResult:

   @RequestMapping(value = "html/start", method = RequestMethod.POST, consumes = APPLICATION_FORM_URLENCODED)
public DeferredResult<String> start(final HttpServletResponse response,
                                    @Valid @ModelAttribute final InitialisationStartAttributes model,
                                    final SessionData sessionExisting) throws MyRequestProcessingException {
    final DeferredResult<String> finalResult = new DeferredResult<>(5000);

                // Just return an error, so we can test
                if (true) {
                    finalResult.setErrorResult(new MyRequestProcessingException(
                            "Something went wrong processing request"));
                }

    return finalResult;
}

In embedded Tomcat, a POST to /html/start returns a 500 with some JSON data in the response body, just like the other request method. However, when I try to reproduce this behaviour using a standalone Tomcat instance, I always get a 200 response with no response body.

I'm using Tomcat 8 in embedded and Tomcat 7.0.52 standalone, but I've also tried with standalone Tomcat 8 and it doesn't make a difference.

My application is deployed in the root application context by modifying /etc/tomcat/Catalina/localhost/ROOT.xml.

EDIT: I've done a bit more testing, and it does seem that DeferredResult is the culprit. I have yet to override handleErrorResult() to see what happens. I'm a bit surprised though, because I don't recall seeing anything in the documentation about the difference between returning a DeferredResult in embedded vs standalone Tomcat.


回答1:


If you throw an exception in a @RequestMapping and don't handle it anywhere, then the response status is not set before you hit the ErrorPageFilter. If you want to map status to error path in your customizer, you need to handle the error and get the status set in the filter chain somewhere (e.g. with an @ExceptionHandler or by using an Exception with a @ResponseStatus). Another way to get your custom error page to render would be to map exceptions instead of (or as well as) the HttpStatus, using new ErrorPage(Exception.class, "/html/error").




回答2:


This behaviour was due to a bug in Spring Boot's ErrorPageFilter; see bug report on GitHub. It was fixed in Spring Boot 1.2.3.



来源:https://stackoverflow.com/questions/29088066/spring-boot-in-standalone-tomcat-ignores-exceptions-set-in-deferredresults

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!