Better handling for AsyncRequestTimeoutException
Avoid call to sendError when response is committed and log a short error message instead. Issue: SPR-14739
This commit is contained in:
		
							parent
							
								
									b1030eba3f
								
							
						
					
					
						commit
						afcc120b97
					
				|  | @ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation; | ||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Set; | 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.Log; | ||||||
| import org.apache.commons.logging.LogFactory; | 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.ServletRequestBindingException; | ||||||
| import org.springframework.web.bind.annotation.ControllerAdvice; | import org.springframework.web.bind.annotation.ControllerAdvice; | ||||||
| import org.springframework.web.bind.annotation.ExceptionHandler; | 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.WebRequest; | ||||||
| import org.springframework.web.context.request.async.AsyncRequestTimeoutException; | import org.springframework.web.context.request.async.AsyncRequestTimeoutException; | ||||||
| import org.springframework.web.multipart.support.MissingServletRequestPartException; | import org.springframework.web.multipart.support.MissingServletRequestPartException; | ||||||
|  | @ -439,14 +442,23 @@ public abstract class ResponseEntityExceptionHandler { | ||||||
| 	 * @param ex the exception | 	 * @param ex the exception | ||||||
| 	 * @param headers the headers to be written to the response | 	 * @param headers the headers to be written to the response | ||||||
| 	 * @param status the selected response status | 	 * @param status the selected response status | ||||||
| 	 * @param request the current request | 	 * @param webRequest the current request | ||||||
| 	 * @return a {@code ResponseEntity} instance | 	 * @return a {@code ResponseEntity} instance | ||||||
| 	 * @since 4.2.8 | 	 * @since 4.2.8 | ||||||
| 	 */ | 	 */ | ||||||
| 	protected ResponseEntity<Object> handleAsyncRequestTimeoutException( | 	protected ResponseEntity<Object> 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); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -469,7 +469,12 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes | ||||||
| 	protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex, | 	protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex, | ||||||
| 			HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { | 			HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { | ||||||
| 
 | 
 | ||||||
|  | 		if (!response.isCommitted()) { | ||||||
| 			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); | 			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); | ||||||
|  | 		} | ||||||
|  | 		else if (logger.isErrorEnabled()) { | ||||||
|  | 			logger.error("Async timeout for " + request.getMethod() + " [" + request.getRequestURI() + "]"); | ||||||
|  | 		} | ||||||
| 		return new ModelAndView(); | 		return new ModelAndView(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -481,6 +486,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes | ||||||
| 	protected void sendServerError(Exception ex, HttpServletRequest request, HttpServletResponse response) | 	protected void sendServerError(Exception ex, HttpServletRequest request, HttpServletResponse response) | ||||||
| 			throws IOException { | 			throws IOException { | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 		request.setAttribute("javax.servlet.error.exception", ex); | 		request.setAttribute("javax.servlet.error.exception", ex); | ||||||
| 		response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | 		response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue