DefaultResponseErrorHandler updates

Deprecate handleError(response), and ensure it continues to be invoked
if overridden.

Closes gh-33980
This commit is contained in:
rstoyanchev
2024-11-28 17:57:32 +00:00
parent a0cc6419f4
commit 89b2a6500e
9 changed files with 62 additions and 63 deletions

View File

@@ -49,8 +49,8 @@ import org.springframework.util.ObjectUtils;
* {@link #hasError(HttpStatusCode)}. Unknown status codes will be ignored by
* {@link #hasError(ClientHttpResponse)}.
*
* <p>See {@link #handleError(ClientHttpResponse)} for more details on specific
* exception types.
* <p>See {@link #handleError(URI, HttpMethod, ClientHttpResponse)} for more
* details on specific exception types.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -116,27 +116,6 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR);
}
/**
* Handle the error in the given response with the given resolved status code.
* <p>The default implementation throws:
* <ul>
* <li>{@link HttpClientErrorException} if the status code is in the 4xx
* series, or one of its sub-classes such as
* {@link HttpClientErrorException.BadRequest} and others.
* <li>{@link HttpServerErrorException} if the status code is in the 5xx
* series, or one of its sub-classes such as
* {@link HttpServerErrorException.InternalServerError} and others.
* <li>{@link UnknownHttpStatusCodeException} for error status codes not in the
* {@link HttpStatus} enum range.
* </ul>
* @throws UnknownHttpStatusCodeException in case of an unresolvable status code
* @see #handleError(ClientHttpResponse, HttpStatusCode, URI, HttpMethod)
*/
@Override
public void handleError(ClientHttpResponse response) throws IOException {
handleError(response, response.getStatusCode(), null, null);
}
/**
* Handle the error in the given response with the given resolved status code
* and extra information providing access to the request URL and HTTP method.
@@ -157,9 +136,20 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
*/
@Override
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
handleError(response);
handleError(response, response.getStatusCode(), url, method);
}
/**
* {@inheritDoc}
* <p>As of 6.2.1 this method is a no-op unless overridden.
*/
@SuppressWarnings("removal")
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// no-op, but here for backwards compatibility
}
/**
* Handle the error based on the resolved status code.
* <p>The default implementation delegates to

View File

@@ -42,11 +42,12 @@ import org.springframework.util.CollectionUtils;
* mappings has a match for the {@linkplain ClientHttpResponse#getStatusCode()
* status code} of a given {@code ClientHttpResponse},
* {@link #hasError(ClientHttpResponse)} will return {@code true}, and
* {@link #handleError(ClientHttpResponse)} will attempt to use the
* {@linkplain #setMessageConverters(List) configured message converters} to
* convert the response into the mapped subclass of {@link RestClientException}.
* Note that the {@linkplain #setStatusMapping(Map) status mapping} takes
* precedence over {@linkplain #setSeriesMapping(Map) series mapping}.
* {@link #handleError(ClientHttpResponse, HttpStatusCode, URI, HttpMethod)}
* will attempt to use the {@linkplain #setMessageConverters(List) configured
* message converters} to convert the response into the mapped subclass of
* {@link RestClientException}. Note that the
* {@linkplain #setStatusMapping(Map) status mapping} takes precedence over
* {@linkplain #setSeriesMapping(Map) series mapping}.
*
* <p>If there is no match, this error handler will default to the behavior of
* {@link DefaultResponseErrorHandler}. Note that you can override this default
@@ -98,9 +99,10 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
* If this mapping has a match
* for the {@linkplain ClientHttpResponse#getStatusCode() status code} of a given
* {@code ClientHttpResponse}, {@link #hasError(ClientHttpResponse)} will return
* {@code true} and {@link #handleError(ClientHttpResponse)} will attempt to use the
* {@linkplain #setMessageConverters(List) configured message converters} to convert the
* response into the mapped subclass of {@link RestClientException}.
* {@code true} and {@link #handleError(ClientHttpResponse, HttpStatusCode, URI, HttpMethod)}
* will attempt to use the {@linkplain #setMessageConverters(List) configured
* message converters} to convert the response into the mapped subclass of
* {@link RestClientException}.
*/
public void setStatusMapping(Map<HttpStatusCode, Class<? extends RestClientException>> statusMapping) {
if (!CollectionUtils.isEmpty(statusMapping)) {
@@ -113,9 +115,10 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
* If this mapping has a match
* for the {@linkplain ClientHttpResponse#getStatusCode() status code} of a given
* {@code ClientHttpResponse}, {@link #hasError(ClientHttpResponse)} will return
* {@code true} and {@link #handleError(ClientHttpResponse)} will attempt to use the
* {@linkplain #setMessageConverters(List) configured message converters} to convert the
* response into the mapped subclass of {@link RestClientException}.
* {@code true} and {@link #handleError(ClientHttpResponse, HttpStatusCode, URI, HttpMethod)}
* will attempt to use the {@linkplain #setMessageConverters(List) configured
* message converters} to convert the response into the mapped subclass of
* {@link RestClientException}.
*/
public void setSeriesMapping(Map<HttpStatus.Series, Class<? extends RestClientException>> seriesMapping) {
if (!CollectionUtils.isEmpty(seriesMapping)) {

View File

@@ -43,9 +43,4 @@ public final class NoOpResponseErrorHandler implements ResponseErrorHandler {
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// never actually called
}
}

View File

@@ -45,14 +45,6 @@ public interface ResponseErrorHandler {
* Handle the error in the given response.
* <p>This method is only called when {@link #hasError(ClientHttpResponse)}
* has returned {@code true}.
* @param response the response with the error
* @throws IOException in case of I/O errors
*/
void handleError(ClientHttpResponse response) throws IOException;
/**
* Alternative to {@link #handleError(ClientHttpResponse)} with extra
* information providing access to the request URL and HTTP method.
* @param url the request URL
* @param method the HTTP method
* @param response the response with the error
@@ -63,4 +55,17 @@ public interface ResponseErrorHandler {
handleError(response);
}
/**
* Handle the error in the given response.
* <p>This method is only called when {@link #hasError(ClientHttpResponse)}
* has returned {@code true}.
* @param response the response with the error
* @throws IOException in case of I/O errors
* @deprecated in favor of {@link #handleError(URI, HttpMethod, ClientHttpResponse)}
*/
@Deprecated(since = "6.2.1", forRemoval = true)
default void handleError(ClientHttpResponse response) throws IOException {
// no-op unless overridden
}
}