diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java index 50f10e4bb9a..0faabda8bc9 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java @@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation; import java.util.List; import java.util.Set; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,6 +45,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.async.AsyncRequestTimeoutException; import org.springframework.web.multipart.support.MissingServletRequestPartException; @@ -464,14 +467,23 @@ public abstract class ResponseEntityExceptionHandler { * @param ex the exception * @param headers the headers to be written to the response * @param status the selected response status - * @param request the current request + * @param webRequest the current request * @return a {@code ResponseEntity} instance * @since 4.2.8 */ protected ResponseEntity handleAsyncRequestTimeoutException( - AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { - - return handleExceptionInternal(ex, null, headers, status, request); + AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest webRequest) { + + if (webRequest instanceof ServletWebRequest) { + ServletWebRequest servletRequest = (ServletWebRequest) webRequest; + HttpServletRequest request = servletRequest.getNativeRequest(HttpServletRequest.class); + HttpServletResponse response = servletRequest.getNativeResponse(HttpServletResponse.class); + if (response.isCommitted()) { + logger.error("Async timeout for " + request.getMethod() + " [" + request.getRequestURI() + "]"); + return null; + } + } + return handleExceptionInternal(ex, null, headers, status, webRequest); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java index f29e99dde0f..c7a41e5ef32 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java @@ -498,7 +498,12 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); + if (!response.isCommitted()) { + response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); + } + else if (logger.isErrorEnabled()) { + logger.error("Async timeout for " + request.getMethod() + " [" + request.getRequestURI() + "]"); + } return new ModelAndView(); } @@ -510,6 +515,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes protected void sendServerError(Exception ex, HttpServletRequest request, HttpServletResponse response) throws IOException { + request.setAttribute("javax.servlet.error.exception", ex); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); }