Improve async request timeout handling

Rather than setting the status to 503 directly from the timeout
interceptor which no longer seems to work reliably with Servlet
containers like Jetty even performing an additional ERROR dispatch back
to the original URL, we know rather set the DeferredResult to an
AsyncTimeoutException, which results in a dispatch and standard
handling within Spring MVC. This should be a more reliable way of
dealing with timeouts.

Issue: SPR-14669
This commit is contained in:
Rossen Stoyanchev
2016-09-14 21:31:30 -04:00
parent 07d5f8b123
commit 5dbfe48d24
8 changed files with 124 additions and 29 deletions

View File

@@ -18,7 +18,6 @@ package org.springframework.web.context.request.async;
import java.util.concurrent.Callable;
import javax.servlet.AsyncEvent;
import javax.servlet.DispatcherType;
import org.junit.Before;
import org.junit.Test;
@@ -29,9 +28,12 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.web.context.request.NativeWebRequest;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.web.context.request.async.CallableProcessingInterceptor.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.verify;
import static org.springframework.web.context.request.async.CallableProcessingInterceptor.RESULT_NONE;
/**
* {@link WebAsyncManager} tests where container-triggered timeout/completion
@@ -79,9 +81,8 @@ public class WebAsyncManagerTimeoutTests {
this.asyncWebRequest.onTimeout(ASYNC_EVENT);
this.asyncWebRequest.onComplete(ASYNC_EVENT);
assertFalse(this.asyncManager.hasConcurrentResult());
assertEquals(DispatcherType.REQUEST, this.servletRequest.getDispatcherType());
assertEquals(503, this.servletResponse.getStatus());
assertTrue(this.asyncManager.hasConcurrentResult());
assertEquals(AsyncRequestTimeoutException.class, this.asyncManager.getConcurrentResult().getClass());
verify(interceptor).beforeConcurrentHandling(this.asyncWebRequest, callable);
verify(interceptor).afterCompletion(this.asyncWebRequest, callable);
@@ -163,9 +164,8 @@ public class WebAsyncManagerTimeoutTests {
this.asyncWebRequest.onTimeout(ASYNC_EVENT);
this.asyncWebRequest.onComplete(ASYNC_EVENT);
assertFalse(this.asyncManager.hasConcurrentResult());
assertEquals(DispatcherType.REQUEST, this.servletRequest.getDispatcherType());
assertEquals(503, this.servletResponse.getStatus());
assertTrue(this.asyncManager.hasConcurrentResult());
assertEquals(AsyncRequestTimeoutException.class, this.asyncManager.getConcurrentResult().getClass());
verify(interceptor).beforeConcurrentHandling(this.asyncWebRequest, deferredResult);
verify(interceptor).preProcess(this.asyncWebRequest, deferredResult);