From 2ff43726be693f32b7bf2a6d237ab65f8ce84ba6 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Mon, 14 May 2012 14:47:11 +0300 Subject: [PATCH] Restore serializability of HttpStatusCodeException SPR-7591 introduced a java.nio.charset.Charset field within HttpStatusCodeException. The former is non-serializable, thus by extension the latter also became non-serializable. Because the Charset field is only used for outputting the charset name in HttpStatusCodeException#getResponseBodyAsString, it is reasonable to store the value returned by Charset#name() instead of the actual Charset object itself. This commit refactors HttpStatusCodeException's responseCharset field to be of type String instead of Charset and adds tests to prove that HttpStatusCodeException objects are once again serializable as expected. Issue: SPR-9273, SPR-7591 --- .../web/client/HttpClientErrorException.java | 4 +- .../web/client/HttpServerErrorException.java | 4 +- .../web/client/HttpStatusCodeException.java | 13 +++-- .../client/HttpStatusCodeExceptionTests.java | 57 +++++++++++++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 spring-web/src/test/java/org/springframework/web/client/HttpStatusCodeExceptionTests.java 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 11f583de3b..99de72b160 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-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -29,6 +29,8 @@ import org.springframework.http.HttpStatus; */ public class HttpClientErrorException extends HttpStatusCodeException { + private static final long serialVersionUID = 6777393766937023392L; + /** * Construct a new instance of {@code HttpClientErrorException} based on a {@link HttpStatus}. * @param statusCode the status code 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 3828b036d8..9549dcbd0e 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -29,6 +29,8 @@ import org.springframework.http.HttpStatus; */ public class HttpServerErrorException extends HttpStatusCodeException { + private static final long serialVersionUID = -2565832100451369997L; + /** * Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus}. * diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java index 3a9355a06a..e2396e0683 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -25,11 +25,14 @@ import org.springframework.http.HttpStatus; * Abstract base class for exceptions based on an {@link HttpStatus}. * * @author Arjen Poutsma + * @author Chris Beams * @since 3.0 */ public abstract class HttpStatusCodeException extends RestClientException { - private static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); + private static final long serialVersionUID = 1549626836533638803L; + + private static final String DEFAULT_CHARSET = "ISO-8859-1"; private final HttpStatus statusCode; @@ -37,7 +40,7 @@ public abstract class HttpStatusCodeException extends RestClientException { private final byte[] responseBody; - private final Charset responseCharset; + private final String responseCharset; /** * Construct a new instance of {@code HttpStatusCodeException} based on a {@link HttpStatus}. @@ -76,7 +79,7 @@ public abstract class HttpStatusCodeException extends RestClientException { this.statusCode = statusCode; this.statusText = statusText; this.responseBody = responseBody != null ? responseBody : new byte[0]; - this.responseCharset = responseCharset != null ? responseCharset : DEFAULT_CHARSET; + this.responseCharset = responseCharset != null ? responseCharset.name() : DEFAULT_CHARSET; } /** @@ -109,7 +112,7 @@ public abstract class HttpStatusCodeException extends RestClientException { */ public String getResponseBodyAsString() { try { - return new String(responseBody, responseCharset.name()); + return new String(responseBody, responseCharset); } catch (UnsupportedEncodingException ex) { // should not occur diff --git a/spring-web/src/test/java/org/springframework/web/client/HttpStatusCodeExceptionTests.java b/spring-web/src/test/java/org/springframework/web/client/HttpStatusCodeExceptionTests.java new file mode 100644 index 0000000000..6614227c24 --- /dev/null +++ b/spring-web/src/test/java/org/springframework/web/client/HttpStatusCodeExceptionTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2012 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 java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.charset.Charset; + +import org.junit.Test; +import org.springframework.http.HttpStatus; + +import static org.hamcrest.CoreMatchers.*; + +import static org.junit.Assert.*; + +/** + * Unit tests for {@link HttpStatusCodeException} and subclasses. + * + * @author Chris Beams + */ +public class HttpStatusCodeExceptionTests { + + /** + * Corners bug SPR-9273, which reported the fact that following the changes made in + * SPR-7591, {@link HttpStatusCodeException} and subtypes became no longer + * serializable due to the addition of a non-serializable {@link Charset} field. + */ + @Test + public void testSerializability() throws IOException, ClassNotFoundException { + HttpStatusCodeException ex1 = new HttpClientErrorException( + HttpStatus.BAD_REQUEST, null, null, Charset.forName("US-ASCII")); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new ObjectOutputStream(out).writeObject(ex1); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + HttpStatusCodeException ex2 = + (HttpStatusCodeException) new ObjectInputStream(in).readObject(); + assertThat(ex2.getResponseBodyAsString(), equalTo(ex1.getResponseBodyAsString())); + } + +} -- GitLab