Skip to content

Commit afcc120

Browse files
committed
Better handling for AsyncRequestTimeoutException
Avoid call to sendError when response is committed and log a short error message instead. Issue: SPR-14739
1 parent b1030eb commit afcc120

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.util.List;
2020
import java.util.Set;
21+
import javax.servlet.http.HttpServletRequest;
22+
import javax.servlet.http.HttpServletResponse;
2123

2224
import org.apache.commons.logging.Log;
2325
import org.apache.commons.logging.LogFactory;
@@ -43,6 +45,7 @@
4345
import org.springframework.web.bind.ServletRequestBindingException;
4446
import org.springframework.web.bind.annotation.ControllerAdvice;
4547
import org.springframework.web.bind.annotation.ExceptionHandler;
48+
import org.springframework.web.context.request.ServletWebRequest;
4649
import org.springframework.web.context.request.WebRequest;
4750
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
4851
import org.springframework.web.multipart.support.MissingServletRequestPartException;
@@ -439,14 +442,23 @@ protected ResponseEntity<Object> handleNoHandlerFoundException(
439442
* @param ex the exception
440443
* @param headers the headers to be written to the response
441444
* @param status the selected response status
442-
* @param request the current request
445+
* @param webRequest the current request
443446
* @return a {@code ResponseEntity} instance
444447
* @since 4.2.8
445448
*/
446449
protected ResponseEntity<Object> handleAsyncRequestTimeoutException(
447-
AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
448-
449-
return handleExceptionInternal(ex, null, headers, status, request);
450+
AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest webRequest) {
451+
452+
if (webRequest instanceof ServletWebRequest) {
453+
ServletWebRequest servletRequest = (ServletWebRequest) webRequest;
454+
HttpServletRequest request = servletRequest.getNativeRequest(HttpServletRequest.class);
455+
HttpServletResponse response = servletRequest.getNativeResponse(HttpServletResponse.class);
456+
if (response.isCommitted()) {
457+
logger.error("Async timeout for " + request.getMethod() + " [" + request.getRequestURI() + "]");
458+
return null;
459+
}
460+
}
461+
return handleExceptionInternal(ex, null, headers, status, webRequest);
450462
}
451463

452464
}

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,12 @@ protected ModelAndView handleNoHandlerFoundException(NoHandlerFoundException ex,
469469
protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex,
470470
HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
471471

472-
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
472+
if (!response.isCommitted()) {
473+
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
474+
}
475+
else if (logger.isErrorEnabled()) {
476+
logger.error("Async timeout for " + request.getMethod() + " [" + request.getRequestURI() + "]");
477+
}
473478
return new ModelAndView();
474479
}
475480

@@ -481,6 +486,7 @@ protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutExc
481486
protected void sendServerError(Exception ex, HttpServletRequest request, HttpServletResponse response)
482487
throws IOException {
483488

489+
484490
request.setAttribute("javax.servlet.error.exception", ex);
485491
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
486492
}

0 commit comments

Comments
 (0)