diff --git a/spring-core/src/main/java/org/springframework/core/codec/CodecException.java b/spring-core/src/main/java/org/springframework/core/codec/CodecException.java
index 0f431df3e0..64ee902238 100644
--- a/spring-core/src/main/java/org/springframework/core/codec/CodecException.java
+++ b/spring-core/src/main/java/org/springframework/core/codec/CodecException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -19,18 +19,29 @@ package org.springframework.core.codec;
import org.springframework.core.NestedRuntimeException;
/**
- * Codec related exception, usually used as a wrapper for a cause exception.
+ * General error that indicates a problem while encoding and decoding to and
+ * from an Object stream.
*
* @author Sebastien Deleuze
+ * @author Rossen Stoyanchev
* @since 5.0
*/
@SuppressWarnings("serial")
public class CodecException extends NestedRuntimeException {
+ /**
+ * Create a new CodecException.
+ * @param msg the detail message
+ */
public CodecException(String msg) {
super(msg);
}
+ /**
+ * Create a new CodecException.
+ * @param msg the detail message
+ * @param cause root cause for the exception, if any
+ */
public CodecException(String msg, Throwable cause) {
super(msg, cause);
}
diff --git a/spring-core/src/main/java/org/springframework/core/codec/DecodingException.java b/spring-core/src/main/java/org/springframework/core/codec/DecodingException.java
new file mode 100644
index 0000000000..094bad6ba1
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/core/codec/DecodingException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2017 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.core.codec;
+
+/**
+ * Indicates an issue with decoding the input stream with the focus on indicating
+ * a content issue such as a parse failure. As opposed to a more general I/O
+ * errors, illegal state, or a {@link CodecException} such as a configuration
+ * issue that a {@link Decoder} may choose to raise.
+ *
+ *
For example in a web application, a server side {@code DecodingException}
+ * would translate to a response with a 400 (bad input) status while
+ * {@code CodecException} would translate to 500 (server error) status.
+ *
+ * @author Rossen Stoyanchev
+ * @since 5.0
+ * @see Decoder
+ */
+@SuppressWarnings("serial")
+public class DecodingException extends CodecException {
+
+ /**
+ * Create a new DecodingException.
+ * @param msg the detail message
+ */
+ public DecodingException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Create a new DecodingException.
+ * @param msg the detail message
+ * @param cause root cause for the exception, if any
+ */
+ public DecodingException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/spring-core/src/main/java/org/springframework/core/codec/InternalCodecException.java b/spring-core/src/main/java/org/springframework/core/codec/EncodingException.java
similarity index 53%
rename from spring-core/src/main/java/org/springframework/core/codec/InternalCodecException.java
rename to spring-core/src/main/java/org/springframework/core/codec/EncodingException.java
index c554f6030c..e1eab9683b 100644
--- a/spring-core/src/main/java/org/springframework/core/codec/InternalCodecException.java
+++ b/spring-core/src/main/java/org/springframework/core/codec/EncodingException.java
@@ -13,24 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.springframework.core.codec;
/**
- * Codec exception suitable for internal errors, like those not related to invalid data. It can be used to make sure
- * such error will produce a 5xx status code and not a 4xx one when reading HTTP messages for example.
+ * Indicates an issue with encoding the input Object stream with a focus on
+ * indicating the Objects cannot be encoded. As opposed to a more general
+ * {@link CodecException} such as a configuration issue that an {@link Encoder}
+ * may also choose to raise.
*
- * @author Sebastien Deleuze
+ * @author Rossen Stoyanchev
* @since 5.0
+ * @see Encoder
*/
@SuppressWarnings("serial")
-public class InternalCodecException extends CodecException {
+public class EncodingException extends CodecException {
- public InternalCodecException(String msg) {
+ /**
+ * Create a new EncodingException.
+ * @param msg the detail message
+ */
+ public EncodingException(String msg) {
super(msg);
}
- public InternalCodecException(String msg, Throwable cause) {
+ /**
+ * Create a new EncodingException.
+ * @param msg the detail message
+ * @param cause root cause for the exception, if any
+ */
+ public EncodingException(String msg, Throwable cause) {
super(msg, cause);
}
diff --git a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java
index c54e50fcdb..159eb503af 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java
@@ -21,9 +21,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.springframework.core.codec.InternalCodecException;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -88,9 +85,7 @@ public class DecoderHttpMessageReader implements HttpMessageReader {
Map hints) {
MediaType contentType = getContentType(message);
- return this.decoder
- .decode(message.getBody(), elementType, contentType, hints)
- .onErrorMap(this::mapError);
+ return this.decoder.decode(message.getBody(), elementType, contentType, hints);
}
@Override
@@ -98,9 +93,7 @@ public class DecoderHttpMessageReader implements HttpMessageReader {
Map hints) {
MediaType contentType = getContentType(message);
- return this.decoder
- .decodeToMono(message.getBody(), elementType, contentType, hints)
- .onErrorMap(this::mapError);
+ return this.decoder.decodeToMono(message.getBody(), elementType, contentType, hints);
}
private MediaType getContentType(HttpMessage inputMessage) {
@@ -108,16 +101,6 @@ public class DecoderHttpMessageReader implements HttpMessageReader {
return (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
}
- private Throwable mapError(Throwable ex) {
- if (ex instanceof ResponseStatusException) {
- return ex;
- }
- else if (ex instanceof InternalCodecException) {
- return new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to decode HTTP message", ex);
- }
- return new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to decode HTTP message", ex);
- }
-
// Server-side only...
diff --git a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java
index a9b2d9bad7..4a1229e899 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java
@@ -22,14 +22,13 @@ import java.util.List;
import java.util.Map;
import org.reactivestreams.Publisher;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Encoder;
import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -97,10 +96,9 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter {
Map hints) {
MediaType contentType = updateContentType(message, mediaType);
+ DataBufferFactory factory = message.bufferFactory();
- Flux body = this.encoder
- .encode(inputStream, message.bufferFactory(), elementType, contentType, hints)
- .onErrorMap(this::mapError);
+ Flux body = this.encoder.encode(inputStream, factory, elementType, contentType, hints);
return isStreamingMediaType(contentType) ?
message.writeAndFlushWith(body.map(Flux::just)) :
@@ -139,13 +137,6 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter {
.anyMatch(contentType::isCompatibleWith);
}
- private Throwable mapError(Throwable ex) {
- if (ex instanceof ResponseStatusException) {
- return ex;
- }
- return new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to encode HTTP message", ex);
- }
-
// Server side only...
diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java
index ce71d543f5..2e9d30ca5b 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java
@@ -21,6 +21,7 @@ import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
@@ -32,10 +33,10 @@ import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.CodecException;
+import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.codec.HttpMessageDecoder;
-import org.springframework.core.codec.InternalCodecException;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
@@ -116,10 +117,13 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes
return value;
}
catch (InvalidDefinitionException ex) {
- throw new InternalCodecException("Error while reading the data", ex);
+ throw new CodecException("Type definition error: " + ex.getMessage(), ex);
+ }
+ catch (JsonProcessingException ex) {
+ throw new DecodingException("JSON parse error: " + ex.getMessage(), ex);
}
catch (IOException ex) {
- throw new CodecException("Error while reading the data", ex);
+ throw new CodecException("I/O error while reading: " + ex.getMessage(), ex);
}
});
}
diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java
index 03281a7544..8f15890c39 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
@@ -39,6 +40,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.CodecException;
+import org.springframework.core.codec.EncodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
@@ -164,8 +166,11 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMes
try {
writer.writeValue(outputStream, value);
}
+ catch (JsonProcessingException ex) {
+ throw new EncodingException("JSON encoding error: " + ex.getMessage(), ex);
+ }
catch (IOException ex) {
- throw new CodecException("Error while writing the data", ex);
+ throw new CodecException("I/O error while writing: " + ex.getMessage(), ex);
}
return buffer;
diff --git a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java
index d938758494..cf6de65504 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java
@@ -37,7 +37,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.AbstractDecoder;
-import org.springframework.core.codec.CodecException;
+import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeType;
@@ -216,7 +216,7 @@ public class Jaxb2XmlDecoder extends AbstractDecoder