Browse Source

Improve exception handling in startCallableProcessing

Absorb any exception from the submission to the executor. It will be
handled in the resulting ASYNC dispatch.

Closes gh-30232
pull/29430/head
rstoyanchev 1 year ago
parent
commit
ef8d1db403
  1. 4
      spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java
  2. 29
      spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java

4
spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java

@ -22,7 +22,6 @@ import java.util.List; @@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
@ -344,10 +343,9 @@ public final class WebAsyncManager { @@ -344,10 +343,9 @@ public final class WebAsyncManager {
});
interceptorChain.setTaskFuture(future);
}
catch (RejectedExecutionException ex) {
catch (Throwable ex) {
Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
setConcurrentResultAndDispatch(result);
throw ex;
}
}

29
spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.web.context.request.async;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import jakarta.servlet.http.HttpServletRequest;
@ -46,18 +47,18 @@ import static org.mockito.Mockito.verify; @@ -46,18 +47,18 @@ import static org.mockito.Mockito.verify;
*/
class WebAsyncManagerTests {
private AsyncWebRequest asyncWebRequest = mock();
private final AsyncWebRequest asyncWebRequest = mock();
private MockHttpServletRequest servletRequest = new MockHttpServletRequest();
private final MockHttpServletRequest servletRequest = new MockHttpServletRequest();
private WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
private final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
@BeforeEach
void setup() {
this.asyncManager.setTaskExecutor(new SyncTaskExecutor());
this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
verify(this.asyncWebRequest).addCompletionHandler((Runnable) notNull());
verify(this.asyncWebRequest).addCompletionHandler(notNull());
reset(this.asyncWebRequest);
}
@ -135,6 +136,26 @@ class WebAsyncManagerTests { @@ -135,6 +136,26 @@ class WebAsyncManagerTests {
verify(interceptor).postProcess(this.asyncWebRequest, task, concurrentResult);
}
@Test // gh-30232
void startCallableProcessingSubmitException() throws Exception {
RuntimeException ex = new RuntimeException();
setupDefaultAsyncScenario();
this.asyncManager.setTaskExecutor(new SimpleAsyncTaskExecutor() {
@Override
public Future<?> submit(Runnable task) {
throw ex;
}
});
this.asyncManager.startCallableProcessing(() -> "not used");
assertThat(this.asyncManager.hasConcurrentResult()).isTrue();
assertThat(this.asyncManager.getConcurrentResult()).isEqualTo(ex);
verifyDefaultAsyncScenario();
}
@Test
void startCallableProcessingBeforeConcurrentHandlingException() throws Exception {
Callable<Object> task = new StubCallable(21);

Loading…
Cancel
Save