Document exception wrapping in RestClient status handlers

This commit documents the fact that any (Unchecked)IOExceptions or
HttpMessageNotReadableExceptions thrown from the error handler will be
wrapped in a RestClientException.

Closes gh-31783
This commit is contained in:
Arjen Poutsma 2023-12-12 13:31:27 +01:00
parent 240a75f313
commit 134bb6e31f
3 changed files with 39 additions and 1 deletions

View File

@ -220,8 +220,15 @@ final class DefaultRestClient implements RestClient {
responseWrapper.getHeaders(), RestClientUtils.getBody(responseWrapper));
}
catch (UncheckedIOException | IOException | HttpMessageNotReadableException ex) {
Throwable cause;
if (ex instanceof UncheckedIOException uncheckedIOException) {
cause = uncheckedIOException.getCause();
}
else {
cause = ex;
}
throw new RestClientException("Error while extracting response for type [" +
ResolvableType.forType(bodyType) + "] and content type [" + contentType + "]", ex);
ResolvableType.forType(bodyType) + "] and content type [" + contentType + "]", cause);
}
}

View File

@ -705,6 +705,11 @@ public interface RestClient {
* Provide a function to map specific error status codes to an error handler.
* <p>By default, if there are no matching status handlers, responses with
* status codes &gt;= 400 wil throw a {@link RestClientResponseException}.
* <p>Note that {@link IOException IOExceptions},
* {@link java.io.UncheckedIOException UncheckedIOExceptions}, and
* {@link org.springframework.http.converter.HttpMessageNotReadableException HttpMessageNotReadableExceptions}
* thrown from {@code errorHandler} will be wrapped in a
* {@link RestClientException}.
* @param statusPredicate to match responses with
* @param errorHandler handler that typically, though not necessarily,
* throws an exception
@ -717,6 +722,11 @@ public interface RestClient {
* Provide a function to map specific error status codes to an error handler.
* <p>By default, if there are no matching status handlers, responses with
* status codes &gt;= 400 wil throw a {@link RestClientResponseException}.
* <p>Note that {@link IOException IOExceptions},
* {@link java.io.UncheckedIOException UncheckedIOExceptions}, and
* {@link org.springframework.http.converter.HttpMessageNotReadableException HttpMessageNotReadableExceptions}
* thrown from {@code errorHandler} will be wrapped in a
* {@link RestClientException}.
* @param errorHandler the error handler
* @return this builder
*/

View File

@ -592,6 +592,27 @@ class RestClientIntegrationTests {
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerIOException(ClientHttpRequestFactory requestFactory) {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
assertThatExceptionOfType(RestClientException.class).isThrownBy(() ->
this.restClient.get()
.uri("/greeting")
.retrieve()
.onStatus(HttpStatusCode::is5xxServerError, (request, response) -> {
throw new IOException("500 error!");
})
.body(String.class)
).withCauseInstanceOf(IOException.class);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerParameterizedTypeReference(ClientHttpRequestFactory requestFactory) {
startServer(requestFactory);