Skip to content

Commit ef8d1db

Browse files
committed
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
1 parent a3636af commit ef8d1db

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.Map;
2323
import java.util.concurrent.Callable;
2424
import java.util.concurrent.Future;
25-
import java.util.concurrent.RejectedExecutionException;
2625

2726
import jakarta.servlet.http.HttpServletRequest;
2827
import org.apache.commons.logging.Log;
@@ -344,10 +343,9 @@ public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object..
344343
});
345344
interceptorChain.setTaskFuture(future);
346345
}
347-
catch (RejectedExecutionException ex) {
346+
catch (Throwable ex) {
348347
Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
349348
setConcurrentResultAndDispatch(result);
350-
throw ex;
351349
}
352350
}
353351

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.web.context.request.async;
1818

1919
import java.util.concurrent.Callable;
20+
import java.util.concurrent.Future;
2021
import java.util.function.Consumer;
2122

2223
import jakarta.servlet.http.HttpServletRequest;
@@ -46,18 +47,18 @@
4647
*/
4748
class WebAsyncManagerTests {
4849

49-
private AsyncWebRequest asyncWebRequest = mock();
50+
private final AsyncWebRequest asyncWebRequest = mock();
5051

51-
private MockHttpServletRequest servletRequest = new MockHttpServletRequest();
52+
private final MockHttpServletRequest servletRequest = new MockHttpServletRequest();
5253

53-
private WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
54+
private final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
5455

5556

5657
@BeforeEach
5758
void setup() {
5859
this.asyncManager.setTaskExecutor(new SyncTaskExecutor());
5960
this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
60-
verify(this.asyncWebRequest).addCompletionHandler((Runnable) notNull());
61+
verify(this.asyncWebRequest).addCompletionHandler(notNull());
6162
reset(this.asyncWebRequest);
6263
}
6364

@@ -135,6 +136,26 @@ void startCallableProcessingCallableException() throws Exception {
135136
verify(interceptor).postProcess(this.asyncWebRequest, task, concurrentResult);
136137
}
137138

139+
@Test // gh-30232
140+
void startCallableProcessingSubmitException() throws Exception {
141+
RuntimeException ex = new RuntimeException();
142+
143+
setupDefaultAsyncScenario();
144+
145+
this.asyncManager.setTaskExecutor(new SimpleAsyncTaskExecutor() {
146+
@Override
147+
public Future<?> submit(Runnable task) {
148+
throw ex;
149+
}
150+
});
151+
this.asyncManager.startCallableProcessing(() -> "not used");
152+
153+
assertThat(this.asyncManager.hasConcurrentResult()).isTrue();
154+
assertThat(this.asyncManager.getConcurrentResult()).isEqualTo(ex);
155+
156+
verifyDefaultAsyncScenario();
157+
}
158+
138159
@Test
139160
void startCallableProcessingBeforeConcurrentHandlingException() throws Exception {
140161
Callable<Object> task = new StubCallable(21);

0 commit comments

Comments
 (0)