Skip to content

Commit b119a9c

Browse files
committed
FutureAdapter should wrap RuntimeExceptions
RuntimeExceptions thrown from FutureAdapter.adapt() should be wrapped in an ExecutionException, not thrown as is. Issue: SPR-12887
1 parent e5b5052 commit b119a9c

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

spring-core/src/main/java/org/springframework/util/concurrent/FutureAdapter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ final T adaptInternal(S adapteeResult) throws ExecutionException {
107107
this.state = State.FAILURE;
108108
throw ex;
109109
}
110+
catch (RuntimeException ex) {
111+
ExecutionException execEx = new ExecutionException(ex);
112+
this.result = execEx;
113+
this.state = State.FAILURE;
114+
throw execEx;
115+
}
110116
default:
111117
throw new IllegalStateException();
112118
}

spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.charset.Charset;
2121
import java.util.EnumSet;
2222
import java.util.Set;
23+
import java.util.concurrent.ExecutionException;
2324
import java.util.concurrent.Future;
2425

2526
import org.junit.Before;
@@ -317,16 +318,47 @@ public void deleteCallbackWithLambdas() throws Exception {
317318
}
318319

319320
@Test
320-
public void notFound() throws Exception {
321+
public void identicalExceptionThroughGetAndCallback() throws Exception {
322+
final HttpClientErrorException[] callbackException = new HttpClientErrorException[1];
323+
324+
ListenableFuture<?> future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null);
325+
future.addCallback(new ListenableFutureCallback<Object>() {
326+
@Override
327+
public void onSuccess(Object result) {
328+
fail("onSuccess not expected");
329+
}
330+
@Override
331+
public void onFailure(Throwable t) {
332+
assertTrue(t instanceof HttpClientErrorException);
333+
callbackException[0] = (HttpClientErrorException) t;
334+
}
335+
});
336+
337+
try {
338+
future.get();
339+
fail("Exception expected");
340+
}
341+
catch (ExecutionException ex) {
342+
Throwable cause = ex.getCause();
343+
assertTrue(cause instanceof HttpClientErrorException);
344+
assertSame(callbackException[0], cause);
345+
}
346+
}
347+
348+
@Test
349+
public void notFoundGet() throws Exception {
321350
try {
322351
Future<?> future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null);
323352
future.get();
324353
fail("HttpClientErrorException expected");
325354
}
326-
catch (HttpClientErrorException ex) {
327-
assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode());
328-
assertNotNull(ex.getStatusText());
329-
assertNotNull(ex.getResponseBodyAsString());
355+
catch (ExecutionException ex) {
356+
assertTrue(ex.getCause() instanceof HttpClientErrorException);
357+
HttpClientErrorException cause = (HttpClientErrorException)ex.getCause();
358+
359+
assertEquals(HttpStatus.NOT_FOUND, cause.getStatusCode());
360+
assertNotNull(cause.getStatusText());
361+
assertNotNull(cause.getResponseBodyAsString());
330362
}
331363
}
332364

@@ -372,10 +404,13 @@ public void serverError() throws Exception {
372404
future.get();
373405
fail("HttpServerErrorException expected");
374406
}
375-
catch (HttpServerErrorException ex) {
376-
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, ex.getStatusCode());
377-
assertNotNull(ex.getStatusText());
378-
assertNotNull(ex.getResponseBodyAsString());
407+
catch (ExecutionException ex) {
408+
assertTrue(ex.getCause() instanceof HttpServerErrorException);
409+
HttpServerErrorException cause = (HttpServerErrorException)ex.getCause();
410+
411+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, cause.getStatusCode());
412+
assertNotNull(cause.getStatusText());
413+
assertNotNull(cause.getResponseBodyAsString());
379414
}
380415
}
381416

0 commit comments

Comments
 (0)