Merge branch '6.1.x'
This commit is contained in:
@@ -875,7 +875,21 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
|
||||
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
|
||||
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
|
||||
|
||||
asyncManager.setTaskExecutor(this.taskExecutor);
|
||||
asyncManager.setAsyncWebRequest(asyncWebRequest);
|
||||
asyncManager.registerCallableInterceptors(this.callableInterceptors);
|
||||
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
|
||||
|
||||
// Obtain wrapped response to enforce lifecycle rule from Servlet spec, section 2.3.3.4
|
||||
response = asyncWebRequest.getNativeResponse(HttpServletResponse.class);
|
||||
|
||||
ServletWebRequest webRequest = (asyncWebRequest instanceof ServletWebRequest ?
|
||||
(ServletWebRequest) asyncWebRequest : new ServletWebRequest(request, response));
|
||||
|
||||
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
|
||||
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
|
||||
|
||||
@@ -895,15 +909,6 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
|
||||
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
|
||||
|
||||
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
|
||||
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
|
||||
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
asyncManager.setTaskExecutor(this.taskExecutor);
|
||||
asyncManager.setAsyncWebRequest(asyncWebRequest);
|
||||
asyncManager.registerCallableInterceptors(this.callableInterceptors);
|
||||
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
|
||||
|
||||
if (asyncManager.hasConcurrentResult()) {
|
||||
Object result = asyncManager.getConcurrentResult();
|
||||
Object[] resultContext = asyncManager.getConcurrentResultContext();
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.context.request.async.AsyncRequestNotUsableException;
|
||||
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
|
||||
import org.springframework.web.method.annotation.HandlerMethodValidationException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@@ -118,6 +119,10 @@ import org.springframework.web.util.WebUtils;
|
||||
* <td><div class="block">400 (SC_BAD_REQUEST)</div></td>
|
||||
* </tr>
|
||||
* <tr class="odd-row-color">
|
||||
* <td><div class="block">{@link MethodValidationException}</div></td>
|
||||
* <td><div class="block">500 (SC_INTERNAL_SERVER_ERROR)</div></td>
|
||||
* </tr>
|
||||
* <tr class="odd-row-color">
|
||||
* <td><div class="block">{@link HandlerMethodValidationException}</div></td>
|
||||
* <td><div class="block">400 (SC_BAD_REQUEST)</div></td>
|
||||
* </tr>
|
||||
@@ -133,9 +138,9 @@ import org.springframework.web.util.WebUtils;
|
||||
* <td><div class="block">AsyncRequestTimeoutException</div></td>
|
||||
* <td><div class="block">503 (SC_SERVICE_UNAVAILABLE)</div></td>
|
||||
* </tr>
|
||||
* <tr class="odd-row-color">
|
||||
* <td><div class="block">{@link MethodValidationException}</div></td>
|
||||
* <td><div class="block">500 (SC_INTERNAL_SERVER_ERROR)</div></td>
|
||||
* <tr class="even-row-color">
|
||||
* <td><div class="block">AsyncRequestNotUsableException</div></td>
|
||||
* <td><div class="block">Not applicable</div></td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
@@ -237,6 +242,10 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
else if (ex instanceof MethodValidationException theEx) {
|
||||
return handleMethodValidationException(theEx, request, response, handler);
|
||||
}
|
||||
else if (ex instanceof AsyncRequestNotUsableException) {
|
||||
return handleAsyncRequestNotUsableException(
|
||||
(AsyncRequestNotUsableException) ex, request, response, handler);
|
||||
}
|
||||
}
|
||||
catch (Exception handlerEx) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
@@ -488,6 +497,24 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the case of an I/O failure from the ServletOutputStream.
|
||||
* <p>By default, do nothing since the response is not usable.
|
||||
* @param ex the {@link AsyncRequestTimeoutException} to be handled
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @param handler the executed handler, or {@code null} if none chosen
|
||||
* at the time of the exception (for example, if multipart resolution failed)
|
||||
* @return an empty ModelAndView indicating the exception was handled
|
||||
* @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
|
||||
* @since 5.3.33
|
||||
*/
|
||||
protected ModelAndView handleAsyncRequestNotUsableException(AsyncRequestNotUsableException ex,
|
||||
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) {
|
||||
|
||||
return new ModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an {@link ErrorResponse} exception.
|
||||
* <p>The default implementation sets status and the headers of the response
|
||||
|
||||
@@ -107,6 +107,10 @@ class ResponseEntityExceptionHandlerTests {
|
||||
.filter(method -> method.getName().startsWith("handle") && (method.getParameterCount() == 4))
|
||||
.filter(method -> !method.getName().equals("handleErrorResponse"))
|
||||
.map(method -> method.getParameterTypes()[0])
|
||||
.filter(exceptionType -> {
|
||||
String name = exceptionType.getSimpleName();
|
||||
return !name.equals("AsyncRequestNotUsableException");
|
||||
})
|
||||
.forEach(exceptionType -> assertThat(annotation.value())
|
||||
.as("@ExceptionHandler is missing declaration for " + exceptionType.getName())
|
||||
.contains((Class<Exception>) exceptionType));
|
||||
|
||||
Reference in New Issue
Block a user