diff --git a/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java
new file mode 100644
index 00000000000..5198176ef8c
--- /dev/null
+++ b/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java
@@ -0,0 +1,400 @@
+/*
+ * 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.http.codec;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.core.codec.ByteArrayDecoder;
+import org.springframework.core.codec.ByteArrayEncoder;
+import org.springframework.core.codec.ByteBufferDecoder;
+import org.springframework.core.codec.ByteBufferEncoder;
+import org.springframework.core.codec.CharSequenceEncoder;
+import org.springframework.core.codec.DataBufferDecoder;
+import org.springframework.core.codec.DataBufferEncoder;
+import org.springframework.core.codec.Decoder;
+import org.springframework.core.codec.Encoder;
+import org.springframework.core.codec.ResourceDecoder;
+import org.springframework.core.codec.StringDecoder;
+import org.springframework.http.codec.json.Jackson2JsonDecoder;
+import org.springframework.http.codec.json.Jackson2JsonEncoder;
+import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
+import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+/**
+ * Base class for client or server codec configurers.
+ *
+ * @author Rossen Stoyanchev
+ * @since 5.0
+ */
+public abstract class AbstractCodecConfigurer {
+
+ public static final boolean jackson2Present =
+ ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
+ ServerCodecConfigurer.class.getClassLoader()) &&
+ ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
+ ServerCodecConfigurer.class.getClassLoader());
+
+ public static final boolean jaxb2Present =
+ ClassUtils.isPresent("javax.xml.bind.Binder", ServerCodecConfigurer.class.getClassLoader());
+
+
+ private final DefaultCodecConfigurer defaultCodecs;
+
+ private final CustomCodecConfigurer customCodecs = new CustomCodecConfigurer();
+
+
+ /**
+ * Protected constructor with the configurer for default readers and writers.
+ */
+ protected AbstractCodecConfigurer(DefaultCodecConfigurer defaultCodecConfigurer) {
+ Assert.notNull(defaultCodecConfigurer, "DefaultCodecConfigurer is required.");
+ this.defaultCodecs = defaultCodecConfigurer;
+ }
+
+
+ /**
+ * Provide overrides for built-in HTTP message readers or writers.
+ */
+ public DefaultCodecConfigurer defaultCodec() {
+ return this.defaultCodecs;
+ }
+
+ /**
+ * Whether to make default HTTP message reader and writer registrations.
+ *
By default this is set to {@code "true"}.
+ */
+ public void registerDefaults(boolean registerDefaults) {
+ this.defaultCodec().setSuppressed(!registerDefaults);
+ }
+
+ /**
+ * Register a custom encoder or decoder.
+ */
+ public CustomCodecConfigurer customCodec() {
+ return this.customCodecs;
+ }
+
+
+ /**
+ * Prepare a list of HTTP message readers.
+ */
+ public List> getReaders() {
+
+ List> result = new ArrayList<>();
+
+ addDefaultTypedReaders(result);
+ addCustomTypedReaders(result);
+
+ addDefaultObjectReaders(result);
+ addCustomObjectReaders(result);
+
+ defaultCodec().addStringReaderTo(result);
+
+ return result;
+ }
+
+ /**
+ * Add built-in, concrete, Java type readers.
+ */
+ protected void addDefaultTypedReaders(List> result) {
+ defaultCodec().addReaderTo(result, ByteArrayDecoder.class, ByteArrayDecoder::new);
+ defaultCodec().addReaderTo(result, ByteBufferDecoder.class, ByteBufferDecoder::new);
+ defaultCodec().addReaderTo(result, DataBufferDecoder.class, DataBufferDecoder::new);
+ defaultCodec().addReaderTo(result, ResourceDecoder.class, ResourceDecoder::new);
+ defaultCodec().addStringReaderTextOnlyTo(result);
+ }
+
+ /**
+ * Add custom, concrete, Java type readers.
+ */
+ protected void addCustomTypedReaders(List> result) {
+ customCodec().addTypedReadersTo(result);
+ }
+
+ /**
+ * Add built-in, Object-based readers.
+ */
+ protected void addDefaultObjectReaders(List> result) {
+ if (jaxb2Present) {
+ defaultCodec().addReaderTo(result, Jaxb2XmlDecoder.class, Jaxb2XmlDecoder::new);
+ }
+ if (jackson2Present) {
+ defaultCodec().addReaderTo(result, Jackson2JsonDecoder.class, Jackson2JsonDecoder::new);
+ }
+ }
+
+ /**
+ * Add custom, Object-based readers.
+ */
+ protected void addCustomObjectReaders(List> result) {
+ customCodec().addObjectReadersTo(result);
+ }
+
+
+ /**
+ * Prepare a list of HTTP message writers.
+ */
+ public List> getWriters() {
+
+ List> result = new ArrayList<>();
+
+ addDefaultTypedWriter(result);
+ addCustomTypedWriter(result);
+
+ addDefaultObjectWriters(result);
+ addCustomObjectWriters(result);
+
+ // String + "*/*"
+ defaultCodec().addStringWriterTo(result);
+
+ return result;
+ }
+
+ /**
+ * Add built-in, concrete, Java type readers.
+ */
+ protected void addDefaultTypedWriter(List> result) {
+ defaultCodec().addWriterTo(result, ByteArrayEncoder.class, ByteArrayEncoder::new);
+ defaultCodec().addWriterTo(result, ByteBufferEncoder.class, ByteBufferEncoder::new);
+ defaultCodec().addWriterTo(result, DataBufferEncoder.class, DataBufferEncoder::new);
+ defaultCodec().addWriterTo(result, ResourceHttpMessageWriter::new);
+ defaultCodec().addStringWriterTextPlainOnlyTo(result);
+ }
+
+ /**
+ * Add custom, concrete, Java type readers.
+ */
+ protected void addCustomTypedWriter(List> result) {
+ customCodec().addTypedWritersTo(result);
+ }
+
+ /**
+ * Add built-in, Object-based readers.
+ */
+ protected void addDefaultObjectWriters(List> result) {
+ if (jaxb2Present) {
+ defaultCodec().addWriterTo(result, Jaxb2XmlEncoder.class, Jaxb2XmlEncoder::new);
+ }
+ if (jackson2Present) {
+ defaultCodec().addWriterTo(result, Jackson2JsonEncoder.class, Jackson2JsonEncoder::new);
+ }
+ }
+
+ /**
+ * Add custom, Object-based readers.
+ */
+ protected void addCustomObjectWriters(List> result) {
+ customCodec().addObjectWritersTo(result);
+ }
+
+
+
+ /**
+ * A registry and a factory for built-in HTTP message readers and writers.
+ */
+ public static class DefaultCodecConfigurer {
+
+ private boolean suppressed = false;
+
+ private final Map, HttpMessageReader>> readers = new HashMap<>();
+
+ private final Map, HttpMessageWriter>> writers = new HashMap<>();
+
+
+ /**
+ * Override the default Jackson {@code Decoder}.
+ * @param decoder the decoder to use
+ */
+ public void jackson2Decoder(Jackson2JsonDecoder decoder) {
+ this.readers.put(Jackson2JsonDecoder.class, new DecoderHttpMessageReader<>(decoder));
+ }
+
+ /**
+ * Override the default Jackson {@code Encoder} for JSON.
+ * @param encoder the encoder to use
+ */
+ public void jackson2Encoder(Jackson2JsonEncoder encoder) {
+ this.writers.put(Jackson2JsonEncoder.class, new EncoderHttpMessageWriter<>(encoder));
+ }
+
+
+ // Accessors for internal use...
+
+
+ protected Map, HttpMessageReader>> getReaders() {
+ return this.readers;
+ }
+
+ protected Map, HttpMessageWriter>> getWriters() {
+ return this.writers;
+ }
+
+ private void setSuppressed(boolean suppressed) {
+ this.suppressed = suppressed;
+ }
+
+
+ // Protected methods for building a list of default readers or writers...
+
+
+ protected > void addReaderTo(List> result,
+ Class key, Supplier fallback) {
+
+ addReaderTo(result, () -> findDecoderReader(key, fallback));
+ }
+
+ protected void addReaderTo(List> result,
+ Supplier> reader) {
+
+ if (!this.suppressed) {
+ result.add(reader.get());
+ }
+ }
+
+ protected > DecoderHttpMessageReader> findDecoderReader(
+ Class decoderType, Supplier fallback) {
+
+ DecoderHttpMessageReader> reader = (DecoderHttpMessageReader>) this.readers.get(decoderType);
+ return reader != null ? reader : new DecoderHttpMessageReader<>(fallback.get());
+ }
+
+ @SuppressWarnings("unchecked")
+ protected HttpMessageReader> findReader(Class> key, Supplier> fallback) {
+ return this.readers.containsKey(key) ? this.readers.get(key) : fallback.get();
+ }
+
+
+ protected > void addWriterTo(List> result,
+ Class key, Supplier fallback) {
+
+ addWriterTo(result, () -> findEncoderWriter(key, fallback));
+ }
+
+ protected void addWriterTo(List> result,
+ Supplier> writer) {
+
+ if (!this.suppressed) {
+ result.add(writer.get());
+ }
+ }
+
+ protected > EncoderHttpMessageWriter> findEncoderWriter(
+ Class encoderType, Supplier fallback) {
+
+ EncoderHttpMessageWriter> writer = (EncoderHttpMessageWriter>) this.writers.get(encoderType);
+ return writer != null ? writer : new EncoderHttpMessageWriter<>(fallback.get());
+ }
+
+ @SuppressWarnings("unchecked")
+ protected HttpMessageWriter> findWriter(Class> key, Supplier> fallback) {
+ return this.writers.containsKey(key) ? this.writers.get(key) : fallback.get();
+ }
+
+
+ protected void addStringReaderTextOnlyTo(List> result) {
+ addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly(true)));
+ }
+
+ protected void addStringReaderTo(List> result) {
+ addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true)));
+ }
+
+ protected void addStringWriterTextPlainOnlyTo(List> result) {
+ addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
+ }
+
+ protected void addStringWriterTo(List> result) {
+ addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
+ }
+ }
+
+ /**
+ * Registry and container for custom HTTP message readers and writers.
+ */
+ public static class CustomCodecConfigurer {
+
+ private final List> typedReaders = new ArrayList<>();
+
+ private final List> typedWriters = new ArrayList<>();
+
+ private final List> objectReaders = new ArrayList<>();
+
+ private final List> objectWriters = new ArrayList<>();
+
+
+ /**
+ * Add a custom {@code Decoder} internally wrapped with
+ * {@link DecoderHttpMessageReader}).
+ */
+ public void decoder(Decoder> decoder) {
+ reader(new DecoderHttpMessageReader<>(decoder));
+ }
+
+ /**
+ * Add a custom {@code Encoder}, internally wrapped with
+ * {@link EncoderHttpMessageWriter}.
+ */
+ public void encoder(Encoder> encoder) {
+ writer(new EncoderHttpMessageWriter<>(encoder));
+ }
+
+ /**
+ * Add a custom {@link HttpMessageReader}. For readers of type
+ * {@link DecoderHttpMessageReader} consider using the shortcut
+ * {@link #decoder(Decoder)} instead.
+ */
+ public void reader(HttpMessageReader> reader) {
+ boolean canReadToObject = reader.canRead(ResolvableType.forClass(Object.class), null);
+ (canReadToObject ? this.objectReaders : this.typedReaders).add(reader);
+ }
+
+ /**
+ * Add a custom {@link HttpMessageWriter}. For readers of type
+ * {@link EncoderHttpMessageWriter} consider using the shortcut
+ * {@link #encoder(Encoder)} instead.
+ */
+ public void writer(HttpMessageWriter> writer) {
+ boolean canWriteObject = writer.canWrite(ResolvableType.forClass(Object.class), null);
+ (canWriteObject ? this.objectWriters : this.typedWriters).add(writer);
+ }
+
+
+ // Internal methods for building a list of custom readers or writers...
+
+ protected void addTypedReadersTo(List> result) {
+ result.addAll(this.typedReaders);
+ }
+
+ protected void addObjectReadersTo(List> result) {
+ result.addAll(this.objectReaders);
+ }
+
+ protected void addTypedWritersTo(List> result) {
+ result.addAll(this.typedWriters);
+ }
+
+ protected void addObjectWritersTo(List> result) {
+ result.addAll(this.objectWriters);
+ }
+ }
+}
diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
index 6f5c58563ef..3302cf37f90 100644
--- a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
+++ b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
@@ -15,343 +15,78 @@
*/
package org.springframework.http.codec;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
-import org.springframework.core.ResolvableType;
-import org.springframework.core.codec.ByteArrayDecoder;
-import org.springframework.core.codec.ByteArrayEncoder;
-import org.springframework.core.codec.ByteBufferDecoder;
-import org.springframework.core.codec.ByteBufferEncoder;
-import org.springframework.core.codec.CharSequenceEncoder;
-import org.springframework.core.codec.DataBufferDecoder;
-import org.springframework.core.codec.DataBufferEncoder;
-import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder;
-import org.springframework.core.codec.ResourceDecoder;
-import org.springframework.core.codec.StringDecoder;
-import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
-import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
-import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
-import org.springframework.util.ClassUtils;
/**
* Helps to configure a list of server-side HTTP message readers and writers
* with support for built-in defaults and options to register additional custom
* readers and writers via {@link #customCodec()}.
*
- * The built-in defaults include basic data types such as
- * {@link Byte byte[]}, {@link java.nio.ByteBuffer ByteBuffer},
- * {@link org.springframework.core.io.buffer.DataBuffer DataBuffer},
- * {@link String}, {@link org.springframework.core.io.Resource Resource},
- * in addition to JAXB2 and Jackson 2 based on classpath detection, as well as
- * support for Server-Sent Events. There are options to {@link #defaultCodec()
- * override} some of the defaults or to have them
+ *
The built-in defaults include basic data types such as various byte
+ * representations, resources, strings, forms, but also others like JAXB2 and
+ * Jackson 2 based on classpath detection. There are options to
+ * {@link #defaultCodec() override} some of the defaults or to have them
* {@link #registerDefaults(boolean) turned off} completely.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
-public class ServerCodecConfigurer {
+public class ServerCodecConfigurer extends AbstractCodecConfigurer {
- private static final boolean jackson2Present =
- ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
- ServerCodecConfigurer.class.getClassLoader()) &&
- ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
- ServerCodecConfigurer.class.getClassLoader());
- private static final boolean jaxb2Present =
- ClassUtils.isPresent("javax.xml.bind.Binder", ServerCodecConfigurer.class.getClassLoader());
-
-
- private final DefaultCodecConfigurer defaultCodecs = new DefaultCodecConfigurer();
-
- private final CustomCodecConfigurer customCodecs = new CustomCodecConfigurer();
-
-
- /**
- * Provide overrides for built-in HTTP message readers and writers.
- */
- public DefaultCodecConfigurer defaultCodec() {
- return this.defaultCodecs;
+ public ServerCodecConfigurer() {
+ super(new ServerDefaultCodecConfigurer());
}
- /**
- * Whether to make default HTTP message reader and writer registrations.
- *
By default this is set to {@code "true"}.
- */
- public void registerDefaults(boolean register) {
- this.defaultCodec().setSuppressed(!register);
- }
- /**
- * Register a custom encoder or decoder.
- */
- public CustomCodecConfigurer customCodec() {
- return this.customCodecs;
+ @Override
+ public ServerDefaultCodecConfigurer defaultCodec() {
+ return (ServerDefaultCodecConfigurer) super.defaultCodec();
}
- /**
- * Prepare a list of HTTP message readers.
- */
- public List> getReaders() {
-
- // Built-in, concrete Java type readers
- List> result = new ArrayList<>();
- this.defaultCodecs.addReaderTo(result, ByteArrayDecoder.class, ByteArrayDecoder::new);
- this.defaultCodecs.addReaderTo(result, ByteBufferDecoder.class, ByteBufferDecoder::new);
- this.defaultCodecs.addReaderTo(result, DataBufferDecoder.class, DataBufferDecoder::new);
- this.defaultCodecs.addReaderTo(result, ResourceDecoder.class, ResourceDecoder::new);
- this.defaultCodecs.addStringReaderTextOnlyTo(result);
-
- this.defaultCodecs.addReaderTo(result, FormHttpMessageReader::new);
-
- // Custom, concrete Java type readers
- this.customCodecs.addTypedReadersTo(result);
-
- // Built-in, Object-based readers
- if (jaxb2Present) {
- this.defaultCodecs.addReaderTo(result, Jaxb2XmlDecoder.class, Jaxb2XmlDecoder::new);
- }
- if (jackson2Present) {
- this.defaultCodecs.addReaderTo(result, Jackson2JsonDecoder.class, Jackson2JsonDecoder::new);
- }
-
- // Custom, Object-based readers
- this.customCodecs.addObjectReadersTo(result);
-
- // Potentially overlapping Java types + "*/*"
- this.defaultCodecs.addStringReaderTo(result);
- return result;
+ protected void addDefaultTypedReaders(List> result) {
+ super.addDefaultTypedReaders(result);
+ defaultCodec().addReaderTo(result, FormHttpMessageReader::new);
}
- /**
- * Prepare a list of HTTP message writers.
- */
- public List> getWriters() {
-
- // Built-in, concrete Java type readers
- List> result = new ArrayList<>();
- this.defaultCodecs.addWriterTo(result, ByteArrayEncoder.class, ByteArrayEncoder::new);
- this.defaultCodecs.addWriterTo(result, ByteBufferEncoder.class, ByteBufferEncoder::new);
- this.defaultCodecs.addWriterTo(result, DataBufferEncoder.class, DataBufferEncoder::new);
- this.defaultCodecs.addWriterTo(result, ResourceHttpMessageWriter::new);
- this.defaultCodecs.addStringWriterTextPlainOnlyTo(result);
- // Custom, concrete Java type readers
- this.customCodecs.addTypedWritersTo(result);
-
- // Built-in, Object-based readers
- if (jaxb2Present) {
- this.defaultCodecs.addWriterTo(result, Jaxb2XmlEncoder.class, Jaxb2XmlEncoder::new);
- }
- if (jackson2Present) {
- this.defaultCodecs.addWriterTo(result, Jackson2JsonEncoder.class, Jackson2JsonEncoder::new);
- }
- this.defaultCodecs.addSseWriterTo(result);
-
- // Custom, Object-based readers
- this.customCodecs.addObjectWritersTo(result);
-
- // Potentially overlapping Java types + "*/*"
- this.defaultCodecs.addStringWriterTo(result);
- return result;
+ protected void addDefaultObjectWriters(List> result) {
+ super.addDefaultObjectWriters(result);
+ defaultCodec().addServerSentEventWriterTo(result);
}
/**
- * A registry and a factory for built-in HTTP message readers and writers.
+ * Extension of {@code DefaultCodecConfigurer} with extra server options.
*/
- public static class DefaultCodecConfigurer {
-
- private boolean suppressed = false;
-
- private final Map, HttpMessageReader>> readers = new HashMap<>();
-
- private final Map, HttpMessageWriter>> writers = new HashMap<>();
-
-
- /**
- * Override the default Jackson {@code Decoder}.
- * @param decoder the decoder to use
- */
- public void jackson2Decoder(Jackson2JsonDecoder decoder) {
- this.readers.put(Jackson2JsonDecoder.class, new DecoderHttpMessageReader<>(decoder));
- }
-
- /**
- * Override the default Jackson {@code Encoder} for JSON. Also used for
- * SSE unless further overridden via {@link #sse(Encoder)}.
- * @param encoder the encoder to use
- */
- public void jackson2Encoder(Jackson2JsonEncoder encoder) {
- this.writers.put(Jackson2JsonEncoder.class, new EncoderHttpMessageWriter<>(encoder));
- }
+ public static class ServerDefaultCodecConfigurer extends DefaultCodecConfigurer {
/**
* Configure the {@code Encoder} to use for Server-Sent Events.
* By default the {@link #jackson2Encoder} override is used for SSE.
* @param encoder the encoder to use
*/
- public void sse(Encoder> encoder) {
+ public void serverSentEventEncoder(Encoder> encoder) {
HttpMessageWriter> writer = new ServerSentEventHttpMessageWriter(encoder);
- this.writers.put(ServerSentEventHttpMessageWriter.class, writer);
+ getWriters().put(ServerSentEventHttpMessageWriter.class, writer);
}
// Internal methods for building a list of default readers or writers...
- private void setSuppressed(boolean suppressed) {
- this.suppressed = suppressed;
- }
-
- private > void addReaderTo(List> result,
- Class key, Supplier fallback) {
-
- addReaderTo(result, () -> findReader(key, fallback));
- }
-
- private void addReaderTo(List> result,
- Supplier> reader) {
-
- if (!this.suppressed) {
- result.add(reader.get());
- }
- }
-
- private > DecoderHttpMessageReader> findReader(
- Class key, Supplier fallback) {
-
- DecoderHttpMessageReader> reader = (DecoderHttpMessageReader>) this.readers.get(key);
- return reader != null ? reader : new DecoderHttpMessageReader<>(fallback.get());
- }
-
-
- private > void addWriterTo(List> result,
- Class key, Supplier fallback) {
-
- addWriterTo(result, () -> findWriter(key, fallback));
- }
-
- private void addWriterTo(List> result,
- Supplier> writer) {
-
- if (!this.suppressed) {
- result.add(writer.get());
- }
- }
-
- private > EncoderHttpMessageWriter> findWriter(
- Class key, Supplier fallback) {
-
- EncoderHttpMessageWriter> writer = (EncoderHttpMessageWriter>) this.writers.get(key);
- return writer != null ? writer : new EncoderHttpMessageWriter<>(fallback.get());
- }
-
-
- private void addStringReaderTextOnlyTo(List> result) {
- addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly(true)));
- }
-
- private void addStringReaderTo(List> result) {
- addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true)));
- }
-
- private void addStringWriterTextPlainOnlyTo(List> result) {
- addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
- }
-
- private void addStringWriterTo(List> result) {
- addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
- }
-
- private void addSseWriterTo(List> result) {
- addWriterTo(result, () -> {
- HttpMessageWriter> writer = this.writers.get(ServerSentEventHttpMessageWriter.class);
- if (writer != null) {
- return writer;
- }
+ private void addServerSentEventWriterTo(List> result) {
+ addWriterTo(result, () -> findWriter(ServerSentEventHttpMessageWriter.class, () -> {
+ Encoder> encoder = null;
if (jackson2Present) {
- return new ServerSentEventHttpMessageWriter(
- findWriter(Jackson2JsonEncoder.class, Jackson2JsonEncoder::new).getEncoder());
+ encoder = findEncoderWriter(
+ Jackson2JsonEncoder.class, Jackson2JsonEncoder::new).getEncoder();
}
- return new ServerSentEventHttpMessageWriter();
- });
- }
- }
-
- /**
- * Registry and container for custom HTTP message readers and writers.
- */
- public static class CustomCodecConfigurer {
-
- private final List> typedReaders = new ArrayList<>();
-
- private final List> typedWriters = new ArrayList<>();
-
- private final List> objectReaders = new ArrayList<>();
-
- private final List> objectWriters = new ArrayList<>();
-
-
- /**
- * Add a custom {@code Decoder} internally wrapped with
- * {@link DecoderHttpMessageReader}).
- */
- public void decoder(Decoder> decoder) {
- reader(new DecoderHttpMessageReader<>(decoder));
- }
-
- /**
- * Add a custom {@code Encoder}, internally wrapped with
- * {@link EncoderHttpMessageWriter}.
- */
- public void encoder(Encoder> encoder) {
- writer(new EncoderHttpMessageWriter<>(encoder));
- }
-
- /**
- * Add a custom {@link HttpMessageReader}. For readers of type
- * {@link DecoderHttpMessageReader} consider using the shortcut
- * {@link #decoder(Decoder)} instead.
- */
- public void reader(HttpMessageReader> reader) {
- boolean canReadToObject = reader.canRead(ResolvableType.forClass(Object.class), null);
- (canReadToObject ? this.objectReaders : this.typedReaders).add(reader);
- }
-
- /**
- * Add a custom {@link HttpMessageWriter}. For readers of type
- * {@link EncoderHttpMessageWriter} consider using the shortcut
- * {@link #encoder(Encoder)} instead.
- */
- public void writer(HttpMessageWriter> writer) {
- boolean canWriteObject = writer.canWrite(ResolvableType.forClass(Object.class), null);
- (canWriteObject ? this.objectWriters : this.typedWriters).add(writer);
- }
-
-
- // Internal methods for building a list of custom readers or writers...
-
- private void addTypedReadersTo(List> result) {
- result.addAll(this.typedReaders);
- }
-
- private void addObjectReadersTo(List> result) {
- result.addAll(this.objectReaders);
- }
-
- private void addTypedWritersTo(List> result) {
- result.addAll(this.typedWriters);
- }
-
- private void addObjectWritersTo(List> result) {
- result.addAll(this.objectWriters);
+ return new ServerSentEventHttpMessageWriter(encoder);
+ }));
}
}
diff --git a/spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java
new file mode 100644
index 00000000000..8c57c69f2f2
--- /dev/null
+++ b/spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java
@@ -0,0 +1,289 @@
+/*
+ * 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.http.codec;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.core.codec.ByteArrayDecoder;
+import org.springframework.core.codec.ByteArrayEncoder;
+import org.springframework.core.codec.ByteBufferDecoder;
+import org.springframework.core.codec.ByteBufferEncoder;
+import org.springframework.core.codec.CharSequenceEncoder;
+import org.springframework.core.codec.DataBufferDecoder;
+import org.springframework.core.codec.DataBufferEncoder;
+import org.springframework.core.codec.Decoder;
+import org.springframework.core.codec.Encoder;
+import org.springframework.core.codec.ResourceDecoder;
+import org.springframework.core.codec.StringDecoder;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.json.Jackson2JsonDecoder;
+import org.springframework.http.codec.json.Jackson2JsonEncoder;
+import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
+import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
+import org.springframework.util.MimeTypeUtils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.springframework.core.ResolvableType.forClass;
+
+/**
+ * Unit tests for {@link ServerCodecConfigurer}.
+ * @author Rossen Stoyanchev
+ */
+public class CodecConfigurerTests {
+
+ private final TestCodecConfigurer configurer = new TestCodecConfigurer();
+
+ private final AtomicInteger index = new AtomicInteger(0);
+
+
+ @Test
+ public void defaultReaders() throws Exception {
+ List> readers = this.configurer.getReaders();
+ assertEquals(8, readers.size());
+ assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
+ assertStringDecoder(getNextDecoder(readers), true);
+ assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
+ assertStringDecoder(getNextDecoder(readers), false);
+ }
+
+ @Test
+ public void defaultWriters() throws Exception {
+ List> writers = this.configurer.getWriters();
+ assertEquals(8, writers.size());
+ assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
+ assertStringEncoder(getNextEncoder(writers), true);
+ assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
+ assertStringEncoder(getNextEncoder(writers), false);
+ }
+
+ @Test
+ public void defaultAndCustomReaders() throws Exception {
+
+ Decoder> customDecoder1 = mock(Decoder.class);
+ Decoder> customDecoder2 = mock(Decoder.class);
+
+ when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ HttpMessageReader> customReader1 = mock(HttpMessageReader.class);
+ HttpMessageReader> customReader2 = mock(HttpMessageReader.class);
+
+ when(customReader1.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customReader2.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ this.configurer.customCodec().decoder(customDecoder1);
+ this.configurer.customCodec().decoder(customDecoder2);
+
+ this.configurer.customCodec().reader(customReader1);
+ this.configurer.customCodec().reader(customReader2);
+
+ List> readers = this.configurer.getReaders();
+
+ assertEquals(12, readers.size());
+ assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
+ assertSame(customDecoder1, getNextDecoder(readers));
+ assertSame(customReader1, readers.get(this.index.getAndIncrement()));
+ assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
+ assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
+ assertSame(customDecoder2, getNextDecoder(readers));
+ assertSame(customReader2, readers.get(this.index.getAndIncrement()));
+ assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
+ }
+
+ @Test
+ public void defaultAndCustomWriters() throws Exception {
+
+ Encoder> customEncoder1 = mock(Encoder.class);
+ Encoder> customEncoder2 = mock(Encoder.class);
+
+ when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ HttpMessageWriter> customWriter1 = mock(HttpMessageWriter.class);
+ HttpMessageWriter> customWriter2 = mock(HttpMessageWriter.class);
+
+ when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ this.configurer.customCodec().encoder(customEncoder1);
+ this.configurer.customCodec().encoder(customEncoder2);
+
+ this.configurer.customCodec().writer(customWriter1);
+ this.configurer.customCodec().writer(customWriter2);
+
+ List> writers = this.configurer.getWriters();
+
+ assertEquals(12, writers.size());
+ assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
+ assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
+ assertSame(customEncoder1, getNextEncoder(writers));
+ assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
+ assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
+ assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
+ assertSame(customEncoder2, getNextEncoder(writers));
+ assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
+ assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
+ }
+
+ @Test
+ public void defaultsOffCustomReaders() throws Exception {
+
+ Decoder> customDecoder1 = mock(Decoder.class);
+ Decoder> customDecoder2 = mock(Decoder.class);
+
+ when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ HttpMessageReader> customReader1 = mock(HttpMessageReader.class);
+ HttpMessageReader> customReader2 = mock(HttpMessageReader.class);
+
+ when(customReader1.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customReader2.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ this.configurer.customCodec().decoder(customDecoder1);
+ this.configurer.customCodec().decoder(customDecoder2);
+
+ this.configurer.customCodec().reader(customReader1);
+ this.configurer.customCodec().reader(customReader2);
+
+ this.configurer.registerDefaults(false);
+
+ List> readers = this.configurer.getReaders();
+
+ assertEquals(4, readers.size());
+ assertSame(customDecoder1, getNextDecoder(readers));
+ assertSame(customReader1, readers.get(this.index.getAndIncrement()));
+ assertSame(customDecoder2, getNextDecoder(readers));
+ assertSame(customReader2, readers.get(this.index.getAndIncrement()));
+ }
+
+ @Test
+ public void defaultsOffWithCustomWriters() throws Exception {
+
+ Encoder> customEncoder1 = mock(Encoder.class);
+ Encoder> customEncoder2 = mock(Encoder.class);
+
+ when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ HttpMessageWriter> customWriter1 = mock(HttpMessageWriter.class);
+ HttpMessageWriter> customWriter2 = mock(HttpMessageWriter.class);
+
+ when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
+ when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
+
+ this.configurer.customCodec().encoder(customEncoder1);
+ this.configurer.customCodec().encoder(customEncoder2);
+
+ this.configurer.customCodec().writer(customWriter1);
+ this.configurer.customCodec().writer(customWriter2);
+
+ this.configurer.registerDefaults(false);
+
+ List> writers = this.configurer.getWriters();
+
+ assertEquals(4, writers.size());
+ assertSame(customEncoder1, getNextEncoder(writers));
+ assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
+ assertSame(customEncoder2, getNextEncoder(writers));
+ assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
+ }
+
+ @Test
+ public void jackson2DecoderOverride() throws Exception {
+
+ Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
+ this.configurer.defaultCodec().jackson2Decoder(decoder);
+
+ assertSame(decoder, this.configurer.getReaders().stream()
+ .filter(writer -> writer instanceof DecoderHttpMessageReader)
+ .map(writer -> ((DecoderHttpMessageReader>) writer).getDecoder())
+ .filter(e -> Jackson2JsonDecoder.class.equals(e.getClass()))
+ .findFirst()
+ .filter(e -> e == decoder).orElse(null));
+ }
+
+ @Test
+ public void jackson2EncoderOverride() throws Exception {
+
+ Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
+ this.configurer.defaultCodec().jackson2Encoder(encoder);
+
+ assertSame(encoder, this.configurer.getWriters().stream()
+ .filter(writer -> writer instanceof EncoderHttpMessageWriter)
+ .map(writer -> ((EncoderHttpMessageWriter>) writer).getEncoder())
+ .filter(e -> Jackson2JsonEncoder.class.equals(e.getClass()))
+ .findFirst()
+ .filter(e -> e == encoder).orElse(null));
+ }
+
+
+ private Decoder> getNextDecoder(List> readers) {
+ HttpMessageReader> reader = readers.get(this.index.getAndIncrement());
+ assertEquals(DecoderHttpMessageReader.class, reader.getClass());
+ return ((DecoderHttpMessageReader) reader).getDecoder();
+ }
+
+ private Encoder> getNextEncoder(List> writers) {
+ HttpMessageWriter> writer = writers.get(this.index.getAndIncrement());
+ assertEquals(EncoderHttpMessageWriter.class, writer.getClass());
+ return ((EncoderHttpMessageWriter) writer).getEncoder();
+ }
+
+ private void assertStringDecoder(Decoder> decoder, boolean textOnly) {
+ assertEquals(StringDecoder.class, decoder.getClass());
+ assertTrue(decoder.canDecode(forClass(String.class), MimeTypeUtils.TEXT_PLAIN));
+ assertEquals(!textOnly, decoder.canDecode(forClass(String.class), MediaType.TEXT_EVENT_STREAM));
+ }
+
+ private void assertStringEncoder(Encoder> encoder, boolean textOnly) {
+ assertEquals(CharSequenceEncoder.class, encoder.getClass());
+ assertTrue(encoder.canEncode(forClass(String.class), MimeTypeUtils.TEXT_PLAIN));
+ assertEquals(!textOnly, encoder.canEncode(forClass(String.class), MediaType.TEXT_EVENT_STREAM));
+ }
+
+
+ private static class TestCodecConfigurer extends AbstractCodecConfigurer {
+
+ private TestCodecConfigurer() {
+ super(new DefaultCodecConfigurer());
+ }
+ }
+
+}
diff --git a/spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java
index d33087b7230..d98853b2159 100644
--- a/spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java
+++ b/spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java
@@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
-import org.springframework.core.ResolvableType;
import org.springframework.core.codec.ByteArrayDecoder;
import org.springframework.core.codec.ByteArrayEncoder;
import org.springframework.core.codec.ByteBufferDecoder;
@@ -43,8 +42,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.springframework.core.ResolvableType.forClass;
/**
@@ -88,175 +85,12 @@ public class ServerCodecConfigurerTests {
assertStringEncoder(getNextEncoder(writers), false);
}
- @Test
- public void defaultAndCustomReaders() throws Exception {
-
- Decoder> customDecoder1 = mock(Decoder.class);
- Decoder> customDecoder2 = mock(Decoder.class);
-
- when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- HttpMessageReader> customReader1 = mock(HttpMessageReader.class);
- HttpMessageReader> customReader2 = mock(HttpMessageReader.class);
-
- when(customReader1.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customReader2.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- this.configurer.customCodec().decoder(customDecoder1);
- this.configurer.customCodec().decoder(customDecoder2);
-
- this.configurer.customCodec().reader(customReader1);
- this.configurer.customCodec().reader(customReader2);
-
- List> readers = this.configurer.getReaders();
-
- assertEquals(13, readers.size());
- assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
- assertSame(customDecoder1, getNextDecoder(readers));
- assertSame(customReader1, readers.get(this.index.getAndIncrement()));
- assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
- assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
- assertSame(customDecoder2, getNextDecoder(readers));
- assertSame(customReader2, readers.get(this.index.getAndIncrement()));
- assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
- }
-
- @Test
- public void defaultAndCustomWriters() throws Exception {
-
- Encoder> customEncoder1 = mock(Encoder.class);
- Encoder> customEncoder2 = mock(Encoder.class);
-
- when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- HttpMessageWriter> customWriter1 = mock(HttpMessageWriter.class);
- HttpMessageWriter> customWriter2 = mock(HttpMessageWriter.class);
-
- when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- this.configurer.customCodec().encoder(customEncoder1);
- this.configurer.customCodec().encoder(customEncoder2);
-
- this.configurer.customCodec().writer(customWriter1);
- this.configurer.customCodec().writer(customWriter2);
-
- List> writers = this.configurer.getWriters();
-
- assertEquals(13, writers.size());
- assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
- assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
- assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
- assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
- assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
- assertSame(customEncoder1, getNextEncoder(writers));
- assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
- assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
- assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
- assertEquals(ServerSentEventHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
- assertSame(customEncoder2, getNextEncoder(writers));
- assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
- assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
- }
-
- @Test
- public void defaultsOffCustomReaders() throws Exception {
-
- Decoder> customDecoder1 = mock(Decoder.class);
- Decoder> customDecoder2 = mock(Decoder.class);
-
- when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- HttpMessageReader> customReader1 = mock(HttpMessageReader.class);
- HttpMessageReader> customReader2 = mock(HttpMessageReader.class);
-
- when(customReader1.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customReader2.canRead(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- this.configurer.customCodec().decoder(customDecoder1);
- this.configurer.customCodec().decoder(customDecoder2);
-
- this.configurer.customCodec().reader(customReader1);
- this.configurer.customCodec().reader(customReader2);
-
- this.configurer.registerDefaults(false);
-
- List> readers = this.configurer.getReaders();
-
- assertEquals(4, readers.size());
- assertSame(customDecoder1, getNextDecoder(readers));
- assertSame(customReader1, readers.get(this.index.getAndIncrement()));
- assertSame(customDecoder2, getNextDecoder(readers));
- assertSame(customReader2, readers.get(this.index.getAndIncrement()));
- }
-
- @Test
- public void defaultsOffWithCustomWriters() throws Exception {
-
- Encoder> customEncoder1 = mock(Encoder.class);
- Encoder> customEncoder2 = mock(Encoder.class);
-
- when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- HttpMessageWriter> customWriter1 = mock(HttpMessageWriter.class);
- HttpMessageWriter> customWriter2 = mock(HttpMessageWriter.class);
-
- when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
- when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
-
- this.configurer.customCodec().encoder(customEncoder1);
- this.configurer.customCodec().encoder(customEncoder2);
-
- this.configurer.customCodec().writer(customWriter1);
- this.configurer.customCodec().writer(customWriter2);
-
- this.configurer.registerDefaults(false);
-
- List> writers = this.configurer.getWriters();
-
- assertEquals(4, writers.size());
- assertSame(customEncoder1, getNextEncoder(writers));
- assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
- assertSame(customEncoder2, getNextEncoder(writers));
- assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
- }
-
- @Test
- public void jackson2DecoderOverride() throws Exception {
-
- Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
- this.configurer.defaultCodec().jackson2Decoder(decoder);
-
- assertSame(decoder, this.configurer.getReaders().stream()
- .filter(writer -> writer instanceof DecoderHttpMessageReader)
- .map(writer -> ((DecoderHttpMessageReader>) writer).getDecoder())
- .filter(e -> Jackson2JsonDecoder.class.equals(e.getClass()))
- .findFirst()
- .filter(e -> e == decoder).orElse(null));
- }
-
@Test
public void jackson2EncoderOverride() throws Exception {
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
this.configurer.defaultCodec().jackson2Encoder(encoder);
- assertSame(encoder, this.configurer.getWriters().stream()
- .filter(writer -> writer instanceof EncoderHttpMessageWriter)
- .map(writer -> ((EncoderHttpMessageWriter>) writer).getEncoder())
- .filter(e -> Jackson2JsonEncoder.class.equals(e.getClass()))
- .findFirst()
- .filter(e -> e == encoder).orElse(null));
-
assertSame(encoder, this.configurer.getWriters().stream()
.filter(writer -> ServerSentEventHttpMessageWriter.class.equals(writer.getClass()))
.map(writer -> (ServerSentEventHttpMessageWriter) writer)
diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
index c8f6ed9a7c2..cee40b2c91a 100644
--- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
+++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
@@ -71,16 +71,6 @@ import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
*/
public class WebFluxConfigurationSupport implements ApplicationContextAware {
- private static final boolean jackson2Present =
- ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
- WebFluxConfigurationSupport.class.getClassLoader()) &&
- ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
- WebFluxConfigurationSupport.class.getClassLoader());
-
- private static final boolean jaxb2Present =
- ClassUtils.isPresent("javax.xml.bind.Binder", WebFluxConfigurationSupport.class.getClassLoader());
-
-
private Map corsConfigurations;
private PathMatchConfigurer pathMatchConfigurer;
@@ -159,7 +149,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
*/
protected Map getDefaultMediaTypeMappings() {
Map map = new HashMap<>();
- if (jackson2Present) {
+ if (ServerCodecConfigurer.jackson2Present) {
map.put("json", MediaType.APPLICATION_JSON);
}
return map;