From fe333e49bc1bb51593b3195569b9c06cc3f7e77e Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 28 Oct 2016 17:41:48 +0300 Subject: [PATCH] Better handling for AsyncRequestTimeoutException Avoid call to sendError when response is committed and log a short error message instead. Issue: SPR-14739 --- .../ResponseEntityExceptionHandler.java | 18 +++++++++++++++--- .../DefaultHandlerExceptionResolver.java | 8 +++++++- 2 files changed, 22 insertions(+), 4 deletions(-) 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 c591be11c7..ca3a4705e4 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; @@ -462,14 +465,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) { + AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest webRequest) { - return handleExceptionInternal(ex, null, headers, status, request); + 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 f5b0343c3f..d3796b3e5e 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 @@ -496,7 +496,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(); } @@ -508,6 +513,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); }