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

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

@ -17,6 +17,7 @@
package org.springframework.web.context.request.async; package org.springframework.web.context.request.async;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.function.Consumer; import java.util.function.Consumer;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@ -46,18 +47,18 @@ import static org.mockito.Mockito.verify;
*/ */
class WebAsyncManagerTests { 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 @BeforeEach
void setup() { void setup() {
this.asyncManager.setTaskExecutor(new SyncTaskExecutor()); this.asyncManager.setTaskExecutor(new SyncTaskExecutor());
this.asyncManager.setAsyncWebRequest(this.asyncWebRequest); this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
verify(this.asyncWebRequest).addCompletionHandler((Runnable) notNull()); verify(this.asyncWebRequest).addCompletionHandler(notNull());
reset(this.asyncWebRequest); reset(this.asyncWebRequest);
} }
@ -135,6 +136,26 @@ class WebAsyncManagerTests {
verify(interceptor).postProcess(this.asyncWebRequest, task, concurrentResult); 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 @Test
void startCallableProcessingBeforeConcurrentHandlingException() throws Exception { void startCallableProcessingBeforeConcurrentHandlingException() throws Exception {
Callable<Object> task = new StubCallable(21); Callable<Object> task = new StubCallable(21);

Loading…
Cancel
Save