From 2216964b54dee4a64d634ecb6dc9922f4f07b4bf Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 6 Aug 2018 14:27:08 +0300 Subject: [PATCH] Polish RestTemplate exception hierarchy Issue: SPR-15404 --- .../client/DefaultResponseErrorHandler.java | 76 ++- .../web/client/HttpClientErrorException.java | 547 ++---------------- .../web/client/HttpServerErrorException.java | 271 ++------- ...tResponseErrorHandlerHttpStatusTests.java} | 39 +- 4 files changed, 155 insertions(+), 778 deletions(-) rename spring-web/src/test/java/org/springframework/web/client/{DefaultReponseHanderSpecificErrorsTests.java => DefaultResponseErrorHandlerHttpStatusTests.java} (64%) diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java index a11baa57b3b..711c3f193b2 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java @@ -88,84 +88,74 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { * @since 5.0 */ protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { + + String statusText = response.getStatusText(); + HttpHeaders headers = response.getHeaders(); + byte[] body = getResponseBody(response); + Charset charset = getCharset(response); + switch (statusCode.series()) { case CLIENT_ERROR: - handleClientError(response, statusCode); + handleClientError(statusCode, statusText, headers, body, charset); return; case SERVER_ERROR: - handleServerError(response, statusCode); + handleServerError(statusCode, statusText, headers, body, charset); return; default: - throw new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new UnknownHttpStatusCodeException(statusCode.value(), statusText, headers, body, charset); } } - private void handleClientError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { + private void handleClientError(HttpStatus statusCode, + String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + switch (statusCode) { case BAD_REQUEST: - throw new HttpClientErrorException.BadRequest(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.BadRequest(statusText, headers, body, charset); case UNAUTHORIZED: - throw new HttpClientErrorException.Unauthorized(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.Unauthorized(statusText, headers, body, charset); case FORBIDDEN: - throw new HttpClientErrorException.Forbidden(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.Forbidden(statusText, headers, body, charset); case NOT_FOUND: - throw new HttpClientErrorException.NotFound(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.NotFound(statusText, headers, body, charset); case METHOD_NOT_ALLOWED: - throw new HttpClientErrorException.MethodNotAllowed(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.MethodNotAllowed(statusText, headers, body, charset); case NOT_ACCEPTABLE: - throw new HttpClientErrorException.NotAcceptable(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.NotAcceptable(statusText, headers, body, charset); case CONFLICT: - throw new HttpClientErrorException.Conflict(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.Conflict(statusText, headers, body, charset); case GONE: - throw new HttpClientErrorException.Gone(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.Gone(statusText, headers, body, charset); case UNSUPPORTED_MEDIA_TYPE: - throw new HttpClientErrorException.UnsupportedMediaType(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.UnsupportedMediaType(statusText, headers, body, charset); case TOO_MANY_REQUESTS: - throw new HttpClientErrorException.TooManyRequests(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.TooManyRequests(statusText, headers, body, charset); case UNPROCESSABLE_ENTITY: - throw new HttpClientErrorException.UnprocessableEntity(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException.UnprocessableEntity(statusText, headers, body, charset); default: - throw new HttpClientErrorException(statusCode, response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpClientErrorException(statusCode, statusText, headers, body, charset); } } - private void handleServerError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { + private void handleServerError(HttpStatus statusCode, + String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + switch (statusCode) { case INTERNAL_SERVER_ERROR: - throw new HttpServerErrorException.InternalServerError(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException.InternalServerError(statusText, headers, body, charset); case NOT_IMPLEMENTED: - throw new HttpServerErrorException.NotImplemented(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException.NotImplemented(statusText, headers, body, charset); case BAD_GATEWAY: - throw new HttpServerErrorException.BadGateway(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException.BadGateway(statusText, headers, body, charset); case SERVICE_UNAVAILABLE: - throw new HttpServerErrorException.ServiceUnavailable(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException.ServiceUnavailable(statusText, headers, body, charset); case GATEWAY_TIMEOUT: - throw new HttpServerErrorException.GatewayTimeout(response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException.GatewayTimeout(statusText, headers, body, charset); default: - throw new HttpServerErrorException(statusCode, response.getStatusText(), - response.getHeaders(), getResponseBody(response), getCharset(response)); + throw new HttpServerErrorException(statusCode, statusText, headers, body, charset); } } - /** * Determine the HTTP status of the given response. * @param response the response to inspect diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java index c2a86a5a3ec..c7cb53707a8 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,602 +35,171 @@ public class HttpClientErrorException extends HttpStatusCodeException { /** - * Construct a new instance of {@code HttpClientErrorException} based on - * an {@link HttpStatus}. - * @param statusCode the status code + * Constructor with a status code only. */ public HttpClientErrorException(HttpStatus statusCode) { super(statusCode); } /** - * Construct a new instance of {@code HttpClientErrorException} based on - * an {@link HttpStatus} and status text. - * @param statusCode the status code - * @param statusText the status text + * Constructor with a status code and status text. */ public HttpClientErrorException(HttpStatus statusCode, String statusText) { super(statusCode, statusText); } /** - * Construct a new instance of {@code HttpClientErrorException} based on - * an {@link HttpStatus}, status text, and response body content. - * @param statusCode the status code - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) + * Constructor with a status code and status text, and content. */ - public HttpClientErrorException(HttpStatus statusCode, String statusText, - @Nullable byte[] responseBody, @Nullable Charset responseCharset) { + public HttpClientErrorException( + HttpStatus statusCode, String statusText, @Nullable byte[] body, @Nullable Charset responseCharset) { - super(statusCode, statusText, responseBody, responseCharset); + super(statusCode, statusText, body, responseCharset); } /** - * Construct a new instance of {@code HttpClientErrorException} based on - * an {@link HttpStatus}, status text, and response body content. - * @param statusCode the status code - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - * @since 3.1.2 + * Constructor with a status code and status text, headers, and content. */ public HttpClientErrorException(HttpStatus statusCode, String statusText, - @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { + @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) { - super(statusCode, statusText, responseHeaders, responseBody, responseCharset); + super(statusCode, statusText, headers, body, responseCharset); } + + // Sub-classes for specific HTTP status codes.. + + /** - * Exception thrown when an HTTP 400 Bad Request is received. - * + * {@link HttpClientErrorException} for status HTTP 400 Bad Request. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class BadRequest extends HttpClientErrorException { - private static final long serialVersionUID = -2064198172908428197L; - - /** - * Construct a new instance of {@code HttpClientErrorException.BadRequest}. - */ - public BadRequest() { - super(HttpStatus.BAD_REQUEST); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.BadRequest} based on status text. - * @param statusText the status text - */ - public BadRequest(String statusText) { - super(HttpStatus.BAD_REQUEST, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.BadRequest} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public BadRequest(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.BAD_REQUEST, statusText, responseBody, responseCharset); + BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.BAD_REQUEST, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.BadRequest} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public BadRequest(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.BAD_REQUEST, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 401 Unauthorized is received. - * + * {@link HttpClientErrorException} for status HTTP 401 Unauthorized. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class Unauthorized extends HttpClientErrorException { - private static final long serialVersionUID = 2770517013134530298L; - - /** - * Construct a new instance of {@code HttpClientErrorException.Unauthorized}. - */ - public Unauthorized() { - super(HttpStatus.UNAUTHORIZED); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Unauthorized} based on status text. - * @param statusText the status text - */ - public Unauthorized(String statusText) { - super(HttpStatus.UNAUTHORIZED, statusText); + Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.UNAUTHORIZED, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.Unauthorized} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Unauthorized(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNAUTHORIZED, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Unauthorized} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Unauthorized(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNAUTHORIZED, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 403 Forbidden is received. - * + * {@link HttpClientErrorException} for status HTTP 403 Forbidden. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class Forbidden extends HttpClientErrorException { - private static final long serialVersionUID = 620402597011417919L; - - /** - * Construct a new instance of {@code HttpClientErrorException.Forbidden}. - */ - public Forbidden() { - super(HttpStatus.FORBIDDEN); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Forbidden} based on status text. - * @param statusText the status text - */ - public Forbidden(String statusText) { - super(HttpStatus.FORBIDDEN, statusText); + Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.FORBIDDEN, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.Forbidden} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Forbidden(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.FORBIDDEN, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Forbidden} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Forbidden(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.FORBIDDEN, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 404 Not Found is received. - * + * {@link HttpClientErrorException} for status HTTP 404 Not Found. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class NotFound extends HttpClientErrorException { - private static final long serialVersionUID = -9150078287238394669L; - - /** - * Construct a new instance of {@code HttpClientErrorException.NotFound}. - */ - public NotFound() { - super(HttpStatus.NOT_FOUND); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotFound} based on status text. - * @param statusText the status text - */ - public NotFound(String statusText) { - super(HttpStatus.NOT_FOUND, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotFound} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotFound(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_FOUND, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotFound} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotFound(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_FOUND, statusText, responseHeaders, responseBody, responseCharset); + NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.NOT_FOUND, statusText, headers, body, charset); } - } /** - * Exception thrown when an HTTP 405 Method Not Allowed is received. - * + * {@link HttpClientErrorException} for status HTTP 405 Method Not Allowed. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class MethodNotAllowed extends HttpClientErrorException { - private static final long serialVersionUID = -1485854208191929937L; - - /** - * Construct a new instance of {@code HttpClientErrorException.MethodNotAllowed}. - */ - public MethodNotAllowed() { - super(HttpStatus.METHOD_NOT_ALLOWED); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.MethodNotAllowed} based on status text. - * @param statusText the status text - */ - public MethodNotAllowed(String statusText) { - super(HttpStatus.METHOD_NOT_ALLOWED, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.MethodNotAllowed} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public MethodNotAllowed(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.METHOD_NOT_ALLOWED, statusText, responseBody, responseCharset); + MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.METHOD_NOT_ALLOWED, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.MethodNotAllowed} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public MethodNotAllowed(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.METHOD_NOT_ALLOWED, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 406 Not Acceptable is received. - * + * {@link HttpClientErrorException} for status HTTP 406 Not Acceptable. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class NotAcceptable extends HttpClientErrorException { - private static final long serialVersionUID = -1762209525396296759L; - - /** - * Construct a new instance of {@code HttpClientErrorException.NotAcceptable}. - */ - public NotAcceptable() { - super(HttpStatus.NOT_ACCEPTABLE); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotAcceptable} based on status text. - * @param statusText the status text - */ - public NotAcceptable(String statusText) { - super(HttpStatus.NOT_ACCEPTABLE, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotAcceptable} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotAcceptable(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_ACCEPTABLE, statusText, responseBody, responseCharset); + NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.NOT_ACCEPTABLE, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.NotAcceptable} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotAcceptable(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_ACCEPTABLE, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 409 Conflict is received. - * + * {@link HttpClientErrorException} for status HTTP 409 Conflict. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class Conflict extends HttpClientErrorException { - private static final long serialVersionUID = -147527825450228693L; - - /** - * Construct a new instance of {@code HttpClientErrorException.Conflict}. - */ - public Conflict() { - super(HttpStatus.CONFLICT); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Conflict} based on status text. - * @param statusText the status text - */ - public Conflict(String statusText) { - super(HttpStatus.CONFLICT, statusText); + Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.CONFLICT, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.Conflict} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Conflict(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.CONFLICT, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Conflict} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Conflict(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.CONFLICT, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 410 Gone is received. - * + * {@link HttpClientErrorException} for status HTTP 410 Gone. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class Gone extends HttpClientErrorException { - private static final long serialVersionUID = -147527825450228693L; - - /** - * Construct a new instance of {@code HttpClientErrorException.Gone}. - */ - public Gone() { - super(HttpStatus.GONE); + Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.GONE, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.Gone} based on status text. - * @param statusText the status text - */ - public Gone(String statusText) { - super(HttpStatus.GONE, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Gone} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Gone(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.GONE, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.Gone} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public Gone(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.GONE, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 415 Unsupported Media Type is received. - * + * {@link HttpClientErrorException} for status HTTP 415 Unsupported Media Type. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class UnsupportedMediaType extends HttpClientErrorException { - private static final long serialVersionUID = -7894170475662610655L; - - /** - * Construct a new instance of {@code HttpClientErrorException.UnsupportedMediaType}. - */ - public UnsupportedMediaType() { - super(HttpStatus.UNSUPPORTED_MEDIA_TYPE); + UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnsupportedMediaType} based on status text. - * @param statusText the status text - */ - public UnsupportedMediaType(String statusText) { - super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnsupportedMediaType} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public UnsupportedMediaType(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnsupportedMediaType} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public UnsupportedMediaType(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 422 Unprocessable Entity is received. - * + * {@link HttpClientErrorException} for status HTTP 422 Unprocessable Entity. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class UnprocessableEntity extends HttpClientErrorException { - private static final long serialVersionUID = 147931406869809016L; - - /** - * Construct a new instance of {@code HttpClientErrorException.UnprocessableEntity}. - */ - public UnprocessableEntity() { - super(HttpStatus.UNPROCESSABLE_ENTITY); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnprocessableEntity} based on status text. - * @param statusText the status text - */ - public UnprocessableEntity(String statusText) { - super(HttpStatus.UNPROCESSABLE_ENTITY, statusText); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnprocessableEntity} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public UnprocessableEntity(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNPROCESSABLE_ENTITY, statusText, responseBody, responseCharset); + UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.UNPROCESSABLE_ENTITY, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.UnprocessableEntity} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public UnprocessableEntity(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.UNPROCESSABLE_ENTITY, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 429 Too Many Requests is received. - * + * {@link HttpClientErrorException} for status HTTP 429 Too Many Requests. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class TooManyRequests extends HttpClientErrorException { - private static final long serialVersionUID = -7180196215964324224L; - - /** - * Construct a new instance of {@code HttpClientErrorException.TooManyRequests}. - */ - public TooManyRequests() { - super(HttpStatus.TOO_MANY_REQUESTS); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.TooManyRequests} based on status text. - * @param statusText the status text - */ - public TooManyRequests(String statusText) { - super(HttpStatus.TOO_MANY_REQUESTS, statusText); + TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.TOO_MANY_REQUESTS, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpClientErrorException.TooManyRequests} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public TooManyRequests(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.TOO_MANY_REQUESTS, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpClientErrorException.TooManyRequests} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public TooManyRequests(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.TOO_MANY_REQUESTS, statusText, responseHeaders, responseBody, responseCharset); - } - } } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java index e627f82a78f..8d0ed9d1e16 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java @@ -35,304 +35,99 @@ public class HttpServerErrorException extends HttpStatusCodeException { /** - * Construct a new instance of {@code HttpServerErrorException} based on - * an {@link HttpStatus}. - * @param statusCode the status code + * Constructor with a status code only. */ public HttpServerErrorException(HttpStatus statusCode) { super(statusCode); } /** - * Construct a new instance of {@code HttpServerErrorException} based on - * an {@link HttpStatus} and status text. - * @param statusCode the status code - * @param statusText the status text + * Constructor with a status code and status text. */ public HttpServerErrorException(HttpStatus statusCode, String statusText) { super(statusCode, statusText); } /** - * Construct a new instance of {@code HttpServerErrorException} based on - * an {@link HttpStatus}, status text, and response body content. - * @param statusCode the status code - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - * @since 3.0.5 + * Constructor with a status code and status text, and content. */ - public HttpServerErrorException(HttpStatus statusCode, String statusText, - @Nullable byte[] responseBody, @Nullable Charset responseCharset) { + public HttpServerErrorException( + HttpStatus statusCode, String statusText, @Nullable byte[] body, @Nullable Charset charset) { - super(statusCode, statusText, responseBody, responseCharset); + super(statusCode, statusText, body, charset); } /** - * Construct a new instance of {@code HttpServerErrorException} based on - * an {@link HttpStatus}, status text, and response body content. - * @param statusCode the status code - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - * @since 3.1.2 + * Constructor with a status code and status text, headers, and content. */ public HttpServerErrorException(HttpStatus statusCode, String statusText, - @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { + @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) { - super(statusCode, statusText, responseHeaders, responseBody, responseCharset); + super(statusCode, statusText, headers, body, charset); } + + // Sub-classes for specific HTTP status codes.. + + /** - * Exception thrown when an HTTP 500 Internal Server Error is received. - * + * {@link HttpServerErrorException} for status HTTP 500 Internal Server Error. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class InternalServerError extends HttpServerErrorException { - private static final long serialVersionUID = -9078091996219553426L; - - /** - * Construct a new instance of {@code HttpServerErrorException.InternalServerError}. - */ - public InternalServerError() { - super(HttpStatus.INTERNAL_SERVER_ERROR); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.InternalServerError} based on status text. - * @param statusText the status text - */ - public InternalServerError(String statusText) { - super(HttpStatus.INTERNAL_SERVER_ERROR, statusText); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.InternalServerError} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public InternalServerError(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.INTERNAL_SERVER_ERROR, statusText, responseBody, responseCharset); + InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.INTERNAL_SERVER_ERROR, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpServerErrorException.InternalServerError} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public InternalServerError(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.INTERNAL_SERVER_ERROR, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 501 Not Implemented is received. - * + * {@link HttpServerErrorException} for status HTTP 501 Not Implemented. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class NotImplemented extends HttpServerErrorException { - private static final long serialVersionUID = -8858888941453536625L; - - /** - * Construct a new instance of {@code HttpServerErrorException.NotImplemented}. - */ - public NotImplemented() { - super(HttpStatus.NOT_IMPLEMENTED); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.NotImplemented} based on status text. - * @param statusText the status text - */ - public NotImplemented(String statusText) { - super(HttpStatus.NOT_IMPLEMENTED, statusText); + NotImplemented(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.NOT_IMPLEMENTED, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpServerErrorException.NotImplemented} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotImplemented(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_IMPLEMENTED, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.NotImplemented} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public NotImplemented(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.NOT_IMPLEMENTED, statusText, responseHeaders, responseBody, responseCharset); - } - } - /** - * Exception thrown when an HTTP 502 Bad Gateway is received. - * + * {@link HttpServerErrorException} for status HTTP HTTP 502 Bad Gateway. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class BadGateway extends HttpServerErrorException { - private static final long serialVersionUID = -8989300848677585487L; - - /** - * Construct a new instance of {@code HttpServerErrorException.BadGateway}. - */ - public BadGateway() { - super(HttpStatus.BAD_GATEWAY); + BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.BAD_GATEWAY, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpServerErrorException.BadGateway} based on status text. - * @param statusText the status text - */ - public BadGateway(String statusText) { - super(HttpStatus.BAD_GATEWAY, statusText); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.BadGateway} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public BadGateway(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.BAD_GATEWAY, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.BadGateway} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public BadGateway(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.BAD_GATEWAY, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 503 Service Unavailable is received. - * + * {@link HttpServerErrorException} for status HTTP 503 Service Unavailable. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class ServiceUnavailable extends HttpServerErrorException { - private static final long serialVersionUID = 8777931838369402139L; - - /** - * Construct a new instance of {@code HttpServerErrorException.ServiceUnavailable}. - */ - public ServiceUnavailable() { - super(HttpStatus.SERVICE_UNAVAILABLE); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.ServiceUnavailable} based on status text. - * @param statusText the status text - */ - public ServiceUnavailable(String statusText) { - super(HttpStatus.SERVICE_UNAVAILABLE, statusText); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.ServiceUnavailable} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public ServiceUnavailable(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.SERVICE_UNAVAILABLE, statusText, responseBody, responseCharset); + ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.SERVICE_UNAVAILABLE, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpServerErrorException.ServiceUnavailable} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public ServiceUnavailable(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.SERVICE_UNAVAILABLE, statusText, responseHeaders, responseBody, responseCharset); - } - } /** - * Exception thrown when an HTTP 504 Gateway Timeout is received. - * + * {@link HttpServerErrorException} for status HTTP 504 Gateway Timeout. * @since 5.1 - * @see DefaultResponseErrorHandler */ + @SuppressWarnings("serial") public static class GatewayTimeout extends HttpServerErrorException { - private static final long serialVersionUID = -7460116254256085095L; - - /** - * Construct a new instance of {@code HttpServerErrorException.GatewayTimeout}. - */ - public GatewayTimeout() { - super(HttpStatus.GATEWAY_TIMEOUT); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.GatewayTimeout} based on status text. - * @param statusText the status text - */ - public GatewayTimeout(String statusText) { - super(HttpStatus.GATEWAY_TIMEOUT, statusText); + GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + super(HttpStatus.GATEWAY_TIMEOUT, statusText, headers, body, charset); } - - /** - * Construct a new instance of {@code HttpServerErrorException.GatewayTimeout} based status text - * and response body content. - * @param statusText the status text - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public GatewayTimeout(String statusText, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.GATEWAY_TIMEOUT, statusText, responseBody, responseCharset); - } - - /** - * Construct a new instance of {@code HttpServerErrorException.GatewayTimeout} based on status text - * and response body content. - * @param statusText the status text - * @param responseHeaders the response headers (may be {@code null}) - * @param responseBody the response body content (may be {@code null}) - * @param responseCharset the response body charset (may be {@code null}) - */ - public GatewayTimeout(String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) { - super(HttpStatus.GATEWAY_TIMEOUT, statusText, responseHeaders, responseBody, responseCharset); - } - } } diff --git a/spring-web/src/test/java/org/springframework/web/client/DefaultReponseHanderSpecificErrorsTests.java b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java similarity index 64% rename from spring-web/src/test/java/org/springframework/web/client/DefaultReponseHanderSpecificErrorsTests.java rename to spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java index 73a006e0743..00ca4a6e6ad 100644 --- a/spring-web/src/test/java/org/springframework/web/client/DefaultReponseHanderSpecificErrorsTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java @@ -1,9 +1,26 @@ +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.web.client; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -14,8 +31,12 @@ import static org.mockito.BDDMockito.*; import static org.mockito.Mockito.mock; import static org.springframework.http.HttpStatus.*; +/** + * Unit tests for {@link DefaultResponseErrorHandler} handling of specific + * HTTP status codes. + */ @RunWith(Parameterized.class) -public class DefaultReponseHanderSpecificErrorsTests { +public class DefaultResponseErrorHandlerHttpStatusTests { @Parameters(name = "error: [{0}], exception: [{1}]") public static Object[][] errorCodes() { @@ -51,27 +72,29 @@ public class DefaultReponseHanderSpecificErrorsTests { private final ClientHttpResponse response = mock(ClientHttpResponse.class); + @Test public void handleErrorIOException() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(httpStatus.value()); - given(response.getHeaders()).willReturn(headers); + given(this.response.getRawStatusCode()).willReturn(this.httpStatus.value()); + given(this.response.getHeaders()).willReturn(headers); try { - handler.handleError(response); - fail("expected " + expectedExceptionClass.getSimpleName()); + this.handler.handleError(this.response); + fail("expected " + this.expectedExceptionClass.getSimpleName()); } catch (HttpStatusCodeException ex) { - assertEquals("Expected " + expectedExceptionClass.getSimpleName(), expectedExceptionClass, ex.getClass()); + assertEquals("Expected " + this.expectedExceptionClass.getSimpleName(), + this.expectedExceptionClass, ex.getClass()); } } @Test public void hasErrorTrue() throws Exception { - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); - assertTrue(handler.hasError(response)); + given(this.response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + assertTrue(handler.hasError(this.response)); } }