Browse Source

Refactored CodecConfigurer creation for clearer subpackage interdependencies

Includes redeclaration of CodecConfigurer.DefaultCodecs without concrete Jackson decoder/encoder references in order to avoid hard Jackson dependency.

Issue: SPR-16064
pull/1562/head
Juergen Hoeller 9 years ago
parent
commit
682186a20d
  1. 7
      spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java
  2. 11
      spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java
  3. 71
      spring-web/src/main/java/org/springframework/http/codec/CodecConfigurerFactory.java
  4. 5
      spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
  5. 11
      spring-web/src/main/java/org/springframework/http/codec/ServerSentEvent.java
  6. 3
      spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java
  7. 5
      spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java
  8. 2
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java
  9. 3
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java
  10. 8
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java
  11. 5
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2SmileDecoder.java
  12. 6
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2SmileEncoder.java
  13. 82
      spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java
  14. 22
      spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java
  15. 23
      spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java
  16. 11
      spring-web/src/main/java/org/springframework/http/codec/support/package-info.java
  17. 5
      spring-web/src/main/resources/org/springframework/http/codec/CodecConfigurer.properties
  18. 25
      spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java
  19. 50
      spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java
  20. 25
      spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java

7
spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java

@ -35,17 +35,15 @@ import org.springframework.core.codec.Encoder;
*/ */
public interface ClientCodecConfigurer extends CodecConfigurer { public interface ClientCodecConfigurer extends CodecConfigurer {
@Override @Override
ClientDefaultCodecs defaultCodecs(); ClientDefaultCodecs defaultCodecs();
/** /**
* Creates a new instance of the {@code ClientCodecConfigurer}. * Create a new instance of the {@code ClientCodecConfigurer}.
* @return the created instance
*/ */
static ClientCodecConfigurer create() { static ClientCodecConfigurer create() {
return new DefaultClientCodecConfigurer(); return CodecConfigurerFactory.create(ClientCodecConfigurer.class);
} }
@ -71,6 +69,7 @@ public interface ClientCodecConfigurer extends CodecConfigurer {
void serverSentEventDecoder(Decoder<?> decoder); void serverSentEventDecoder(Decoder<?> decoder);
} }
/** /**
* Registry and container for multipart HTTP message writers. * Registry and container for multipart HTTP message writers.
*/ */

11
spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java

@ -20,8 +20,6 @@ import java.util.List;
import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder; import org.springframework.core.codec.Encoder;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
/** /**
* Defines a common interface for configuring either client or server HTTP * Defines a common interface for configuring either client or server HTTP
@ -73,15 +71,16 @@ public interface CodecConfigurer {
/** /**
* Override the default Jackson JSON {@code Decoder}. * Override the default Jackson JSON {@code Decoder}.
* @param decoder the decoder instance to use * @param decoder the decoder instance to use
* @see org.springframework.http.codec.json.Jackson2JsonDecoder
*/ */
void jackson2JsonDecoder(Jackson2JsonDecoder decoder); void jackson2JsonDecoder(Decoder<?> decoder);
/** /**
* Override the default Jackson JSON {@code Encoder}. * Override the default Jackson JSON {@code Encoder}.
* @param encoder the encoder instance to use * @param encoder the encoder instance to use
* @see org.springframework.http.codec.json.Jackson2JsonEncoder
*/ */
void jackson2JsonEncoder(Jackson2JsonEncoder encoder); void jackson2JsonEncoder(Encoder<?> encoder);
} }
@ -119,6 +118,6 @@ public interface CodecConfigurer {
* @param writer the writer to add * @param writer the writer to add
*/ */
void writer(HttpMessageWriter<?> writer); void writer(HttpMessageWriter<?> writer);
} }
} }

71
spring-web/src/main/java/org/springframework/http/codec/CodecConfigurerFactory.java

@ -0,0 +1,71 @@
/*
* 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.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;
/**
* Internal delegate for loading the default codec configurer class names.
* Models a loose relationship with the default implementations in the support
* package, literally only needing to know the default class name to use.
*
* @author Juergen Hoeller
* @since 5.0.1
* @see ClientCodecConfigurer#create()
* @see ServerCodecConfigurer#create()
*/
class CodecConfigurerFactory {
private static final String DEFAULT_CONFIGURERS_PATH = "CodecConfigurer.properties";
private static final Map<Class<?>, Class<?>> defaultCodecConfigurers = new HashMap<>(4);
static {
try {
Properties props = PropertiesLoaderUtils.loadProperties(
new ClassPathResource(DEFAULT_CONFIGURERS_PATH, CodecConfigurerFactory.class));
for (String ifcName : props.stringPropertyNames()) {
String implName = props.getProperty(ifcName);
Class<?> ifc = ClassUtils.forName(ifcName, CodecConfigurerFactory.class.getClassLoader());
Class<?> impl = ClassUtils.forName(implName, CodecConfigurerFactory.class.getClassLoader());
defaultCodecConfigurers.put(ifc, impl);
}
}
catch (IOException | ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}
}
@SuppressWarnings("unchecked")
public static <T extends CodecConfigurer> T create(Class<T> ifc) {
Class<?> impl = defaultCodecConfigurers.get(ifc);
if (impl == null) {
throw new IllegalStateException("No default codec configurer found for " + ifc);
}
return (T) BeanUtils.instantiateClass(impl);
}
}

5
spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java

@ -39,11 +39,10 @@ public interface ServerCodecConfigurer extends CodecConfigurer {
/** /**
* Creates a new instance of the {@code ServerCodecConfigurer}. * Create a new instance of the {@code ServerCodecConfigurer}.
* @return the created instance
*/ */
static ServerCodecConfigurer create() { static ServerCodecConfigurer create() {
return new DefaultServerCodecConfigurer(); return CodecConfigurerFactory.create(ServerCodecConfigurer.class);
} }

11
spring-web/src/main/java/org/springframework/http/codec/ServerSentEvent.java

@ -18,7 +18,6 @@ package org.springframework.http.codec;
import java.time.Duration; import java.time.Duration;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
@ -167,10 +166,10 @@ public class ServerSentEvent<T> {
Builder<T> comment(String comment); Builder<T> comment(String comment);
/** /**
* Set the value of the {@code data} field. If the {@code data} argument is a * Set the value of the {@code data} field. If the {@code data} argument is a multi-line
* multi-line {@code String}, it will be turned into multiple {@code data} field lines * {@code String}, it will be turned into multiple {@code data} field lines as defined
* as defined in the Server-Sent Events W3C recommendation. If {@code data} is not a * in the Server-Sent Events W3C recommendation. If {@code data} is not a String, it will
* String, it will be {@linkplain Jackson2JsonEncoder encoded} into JSON. * be {@linkplain org.springframework.http.codec.json.Jackson2JsonEncoder encoded} into JSON.
* @param data the value of the data field * @param data the value of the data field
* @return {@code this} builder * @return {@code this} builder
*/ */
@ -181,9 +180,9 @@ public class ServerSentEvent<T> {
* @return the built event * @return the built event
*/ */
ServerSentEvent<T> build(); ServerSentEvent<T> build();
} }
private static class BuilderImpl<T> implements Builder<T> { private static class BuilderImpl<T> implements Builder<T> {
@Nullable @Nullable

3
spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec.json; package org.springframework.http.codec.json;
import java.io.IOException; import java.io.IOException;
@ -54,7 +55,6 @@ import org.springframework.util.MimeType;
*/ */
public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport implements HttpMessageDecoder<Object> { public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport implements HttpMessageDecoder<Object> {
/** /**
* Constructor with a Jackson {@link ObjectMapper} to use. * Constructor with a Jackson {@link ObjectMapper} to use.
*/ */
@ -144,4 +144,5 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
protected <A extends Annotation> A getAnnotation(MethodParameter parameter, Class<A> annotType) { protected <A extends Annotation> A getAnnotation(MethodParameter parameter, Class<A> annotType) {
return parameter.getParameterAnnotation(annotType); return parameter.getParameterAnnotation(annotType);
} }
} }

5
spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec.json; package org.springframework.http.codec.json;
import java.io.IOException; import java.io.IOException;
@ -57,6 +58,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
protected final List<MediaType> streamingMediaTypes = new ArrayList<>(1); protected final List<MediaType> streamingMediaTypes = new ArrayList<>(1);
/** /**
* Constructor with a Jackson {@link ObjectMapper} to use. * Constructor with a Jackson {@link ObjectMapper} to use.
*/ */
@ -64,6 +66,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
super(mapper, mimeTypes); super(mapper, mimeTypes);
} }
/** /**
* Configure "streaming" media types for which flushing should be performed * Configure "streaming" media types for which flushing should be performed
* automatically vs at the end of the stream. * automatically vs at the end of the stream.
@ -76,6 +79,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
this.streamingMediaTypes.addAll(mediaTypes); this.streamingMediaTypes.addAll(mediaTypes);
} }
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.resolve(Object.class);
@ -143,6 +147,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
protected ObjectWriter customizeWriter(ObjectWriter writer, @Nullable MimeType mimeType, protected ObjectWriter customizeWriter(ObjectWriter writer, @Nullable MimeType mimeType,
ResolvableType elementType, @Nullable Map<String, Object> hints) { ResolvableType elementType, @Nullable Map<String, Object> hints) {
return writer; return writer;
} }

2
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java

@ -83,7 +83,7 @@ public abstract class Jackson2CodecSupport {
} }
/** /**
* Sub-classes should expose this as "decodable" or "encodable" mime types. * Subclasses should expose this as "decodable" or "encodable" mime types.
*/ */
protected List<MimeType> getMimeTypes() { protected List<MimeType> getMimeTypes() {
return this.mimeTypes; return this.mimeTypes;

3
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java

@ -19,6 +19,7 @@ package org.springframework.http.codec.json;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
@ -40,8 +41,10 @@ public class Jackson2JsonDecoder extends AbstractJackson2Decoder {
super(mapper, mimeTypes); super(mapper, mimeTypes);
} }
@Override @Override
public List<MimeType> getDecodableMimeTypes() { public List<MimeType> getDecodableMimeTypes() {
return getMimeTypes(); return getMimeTypes();
} }
} }

8
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java

@ -63,16 +63,20 @@ public class Jackson2JsonEncoder extends AbstractJackson2Encoder {
return printer; return printer;
} }
@Override @Override
protected ObjectWriter customizeWriter(ObjectWriter writer, @Nullable MimeType mimeType, protected ObjectWriter customizeWriter(ObjectWriter writer, @Nullable MimeType mimeType,
ResolvableType elementType, @Nullable Map<String, Object> hints) { ResolvableType elementType, @Nullable Map<String, Object> hints) {
return (this.ssePrettyPrinter != null && MediaType.TEXT_EVENT_STREAM.isCompatibleWith(mimeType) && return (this.ssePrettyPrinter != null &&
writer.getConfig().isEnabled(SerializationFeature.INDENT_OUTPUT) ? writer.with(this.ssePrettyPrinter) : writer); MediaType.TEXT_EVENT_STREAM.isCompatibleWith(mimeType) &&
writer.getConfig().isEnabled(SerializationFeature.INDENT_OUTPUT) ?
writer.with(this.ssePrettyPrinter) : writer);
} }
@Override @Override
public List<MimeType> getEncodableMimeTypes() { public List<MimeType> getEncodableMimeTypes() {
return getMimeTypes(); return getMimeTypes();
} }
} }

5
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2SmileDecoder.java

@ -16,7 +16,7 @@
package org.springframework.http.codec.json; package org.springframework.http.codec.json;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -51,6 +51,7 @@ public class Jackson2SmileDecoder extends AbstractJackson2Decoder {
@Override @Override
public List<MimeType> getDecodableMimeTypes() { public List<MimeType> getDecodableMimeTypes() {
return Arrays.asList(SMILE_MIME_TYPE); return Collections.singletonList(SMILE_MIME_TYPE);
} }
} }

6
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2SmileEncoder.java

@ -16,7 +16,7 @@
package org.springframework.http.codec.json; package org.springframework.http.codec.json;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -49,8 +49,10 @@ public class Jackson2SmileEncoder extends AbstractJackson2Encoder {
this.streamingMediaTypes.add(new MediaType("application", "stream+x-jackson-smile")); this.streamingMediaTypes.add(new MediaType("application", "stream+x-jackson-smile"));
} }
@Override @Override
public List<MimeType> getEncodableMimeTypes() { public List<MimeType> getEncodableMimeTypes() {
return Arrays.asList(SMILE_MIME_TYPE); return Collections.singletonList(SMILE_MIME_TYPE);
} }
} }

82
spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java → spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec; package org.springframework.http.codec.support;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -32,6 +32,12 @@ import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder; import org.springframework.core.codec.Encoder;
import org.springframework.core.codec.ResourceDecoder; import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.StringDecoder; import org.springframework.core.codec.StringDecoder;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder; import org.springframework.http.codec.json.Jackson2SmileDecoder;
@ -50,7 +56,7 @@ import org.springframework.util.ClassUtils;
*/ */
abstract class AbstractCodecConfigurer implements CodecConfigurer { abstract class AbstractCodecConfigurer implements CodecConfigurer {
protected static final boolean jackson2Present = static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
AbstractCodecConfigurer.class.getClassLoader()) && AbstractCodecConfigurer.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
@ -60,8 +66,8 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory",
AbstractCodecConfigurer.class.getClassLoader()); AbstractCodecConfigurer.class.getClassLoader());
protected static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", private static final boolean jaxb2Present =
AbstractCodecConfigurer.class.getClassLoader()); ClassUtils.isPresent("javax.xml.bind.Binder", AbstractCodecConfigurer.class.getClassLoader());
private final AbstractDefaultCodecs defaultCodecs; private final AbstractDefaultCodecs defaultCodecs;
@ -69,7 +75,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
private final DefaultCustomCodecs customCodecs = new DefaultCustomCodecs(); private final DefaultCustomCodecs customCodecs = new DefaultCustomCodecs();
protected AbstractCodecConfigurer(AbstractDefaultCodecs defaultCodecs) { AbstractCodecConfigurer(AbstractDefaultCodecs defaultCodecs) {
Assert.notNull(defaultCodecs, "'defaultCodecs' is required"); Assert.notNull(defaultCodecs, "'defaultCodecs' is required");
this.defaultCodecs = defaultCodecs; this.defaultCodecs = defaultCodecs;
this.defaultCodecs.setCustomCodecs(this.customCodecs); this.defaultCodecs.setCustomCodecs(this.customCodecs);
@ -83,7 +89,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
@Override @Override
public void registerDefaults(boolean shouldRegister) { public void registerDefaults(boolean shouldRegister) {
this.defaultCodecs.setRegisterDefaults(shouldRegister); this.defaultCodecs.registerDefaults(shouldRegister);
} }
@Override @Override
@ -120,60 +126,60 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
} }
abstract protected static class AbstractDefaultCodecs implements DefaultCodecs { abstract static class AbstractDefaultCodecs implements DefaultCodecs {
private boolean registerDefaults = true; private boolean registerDefaults = true;
@Nullable @Nullable
private Jackson2JsonDecoder jackson2JsonDecoder; private Decoder<?> jackson2JsonDecoder;
@Nullable @Nullable
private Jackson2JsonEncoder jackson2JsonEncoder; private Encoder<?> jackson2JsonEncoder;
@Nullable @Nullable
private DefaultCustomCodecs customCodecs; private DefaultCustomCodecs customCodecs;
public void setRegisterDefaults(boolean registerDefaults) { void registerDefaults(boolean registerDefaults) {
this.registerDefaults = registerDefaults; this.registerDefaults = registerDefaults;
} }
public boolean shouldRegisterDefaults() { boolean shouldRegisterDefaults() {
return this.registerDefaults; return this.registerDefaults;
} }
/** /**
* Access to custom codecs for sub-classes, e.g. for multipart writers. * Access to custom codecs for subclasses, e.g. for multipart writers.
*/ */
public void setCustomCodecs(@Nullable DefaultCustomCodecs customCodecs) { void setCustomCodecs(@Nullable DefaultCustomCodecs customCodecs) {
this.customCodecs = customCodecs; this.customCodecs = customCodecs;
} }
@Nullable @Nullable
public DefaultCustomCodecs getCustomCodecs() { DefaultCustomCodecs getCustomCodecs() {
return this.customCodecs; return this.customCodecs;
} }
@Override @Override
public void jackson2JsonDecoder(Jackson2JsonDecoder decoder) { public void jackson2JsonDecoder(Decoder<?> decoder) {
this.jackson2JsonDecoder = decoder; this.jackson2JsonDecoder = decoder;
} }
protected Jackson2JsonDecoder jackson2JsonDecoder() { Decoder<?> getJackson2JsonDecoder() {
return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder()); return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder());
} }
@Override @Override
public void jackson2JsonEncoder(Jackson2JsonEncoder encoder) { public void jackson2JsonEncoder(Encoder<?> encoder) {
this.jackson2JsonEncoder = encoder; this.jackson2JsonEncoder = encoder;
} }
protected Jackson2JsonEncoder jackson2JsonEncoder() { Encoder<?> getJackson2JsonEncoder() {
return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder()); return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder());
} }
// Readers... // Readers...
public List<HttpMessageReader<?>> getTypedReaders() { List<HttpMessageReader<?>> getTypedReaders() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -186,26 +192,26 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
return result; return result;
} }
protected abstract boolean splitTextOnNewLine(); abstract boolean splitTextOnNewLine();
public List<HttpMessageReader<?>> getObjectReaders() { List<HttpMessageReader<?>> getObjectReaders() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<HttpMessageReader<?>> result = new ArrayList<>(); List<HttpMessageReader<?>> result = new ArrayList<>();
if (jaxb2Present) {
result.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
}
if (jackson2Present) { if (jackson2Present) {
result.add(new DecoderHttpMessageReader<>(jackson2JsonDecoder())); result.add(new DecoderHttpMessageReader<>(getJackson2JsonDecoder()));
} }
if (jackson2SmilePresent) { if (jackson2SmilePresent) {
result.add(new DecoderHttpMessageReader<>(new Jackson2SmileDecoder())); result.add(new DecoderHttpMessageReader<>(new Jackson2SmileDecoder()));
} }
if (jaxb2Present) {
result.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
}
return result; return result;
} }
public List<HttpMessageReader<?>> getCatchAllReaders() { List<HttpMessageReader<?>> getCatchAllReaders() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -216,7 +222,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
// Writers... // Writers...
public List<HttpMessageWriter<?>> getTypedWriters() { List<HttpMessageWriter<?>> getTypedWriters() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -229,24 +235,24 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
return result; return result;
} }
public List<HttpMessageWriter<?>> getObjectWriters() { List<HttpMessageWriter<?>> getObjectWriters() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<HttpMessageWriter<?>> result = new ArrayList<>(); List<HttpMessageWriter<?>> result = new ArrayList<>();
if (jaxb2Present) {
result.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
}
if (jackson2Present) { if (jackson2Present) {
result.add(new EncoderHttpMessageWriter<>(jackson2JsonEncoder())); result.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
} }
if (jackson2SmilePresent) { if (jackson2SmilePresent) {
result.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder())); result.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder()));
} }
if (jaxb2Present) {
result.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
}
return result; return result;
} }
public List<HttpMessageWriter<?>> getCatchAllWriters() { List<HttpMessageWriter<?>> getCatchAllWriters() {
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -257,7 +263,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
} }
protected static class DefaultCustomCodecs implements CustomCodecs { static class DefaultCustomCodecs implements CustomCodecs {
private final List<HttpMessageReader<?>> typedReaders = new ArrayList<>(); private final List<HttpMessageReader<?>> typedReaders = new ArrayList<>();
@ -289,19 +295,19 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer {
(canWriteObject ? this.objectWriters : this.typedWriters).add(writer); (canWriteObject ? this.objectWriters : this.typedWriters).add(writer);
} }
public List<HttpMessageReader<?>> getTypedReaders() { List<HttpMessageReader<?>> getTypedReaders() {
return this.typedReaders; return this.typedReaders;
} }
public List<HttpMessageWriter<?>> getTypedWriters() { List<HttpMessageWriter<?>> getTypedWriters() {
return this.typedWriters; return this.typedWriters;
} }
public List<HttpMessageReader<?>> getObjectReaders() { List<HttpMessageReader<?>> getObjectReaders() {
return this.objectReaders; return this.objectReaders;
} }
public List<HttpMessageWriter<?>> getObjectWriters() { List<HttpMessageWriter<?>> getObjectWriters() {
return this.objectWriters; return this.objectWriters;
} }
} }

22
spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java → spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec; package org.springframework.http.codec.support;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -22,6 +22,12 @@ import java.util.List;
import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder; import org.springframework.core.codec.Encoder;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; import org.springframework.http.codec.multipart.MultipartHttpMessageWriter;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -31,7 +37,7 @@ import org.springframework.lang.Nullable;
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 5.0 * @since 5.0
*/ */
class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements ClientCodecConfigurer { public class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements ClientCodecConfigurer {
public DefaultClientCodecConfigurer() { public DefaultClientCodecConfigurer() {
super(new ClientDefaultCodecsImpl()); super(new ClientDefaultCodecsImpl());
@ -65,12 +71,12 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl
} }
@Override @Override
protected boolean splitTextOnNewLine() { boolean splitTextOnNewLine() {
return false; return false;
} }
@Override @Override
public List<HttpMessageReader<?>> getObjectReaders() { List<HttpMessageReader<?>> getObjectReaders() {
if (!shouldRegisterDefaults()) { if (!shouldRegisterDefaults()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -84,12 +90,12 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl
if (this.sseDecoder != null) { if (this.sseDecoder != null) {
return this.sseDecoder; return this.sseDecoder;
} }
return (jackson2Present ? jackson2JsonDecoder() : null); return (jackson2Present ? getJackson2JsonDecoder() : null);
} }
@Override @Override
public List<HttpMessageWriter<?>> getTypedWriters() { List<HttpMessageWriter<?>> getTypedWriters() {
if (!this.shouldRegisterDefaults()) { if (!shouldRegisterDefaults()) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<HttpMessageWriter<?>> result = super.getTypedWriters(); List<HttpMessageWriter<?>> result = super.getTypedWriters();
@ -137,7 +143,7 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl
return this; return this;
} }
public List<HttpMessageWriter<?>> getWriters() { List<HttpMessageWriter<?>> getWriters() {
return this.writers; return this.writers;
} }
} }

23
spring-web/src/main/java/org/springframework/http/codec/DefaultServerCodecConfigurer.java → spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java

@ -14,12 +14,17 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec; package org.springframework.http.codec.support;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.springframework.core.codec.Encoder; import org.springframework.core.codec.Encoder;
import org.springframework.http.codec.FormHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.multipart.MultipartHttpMessageReader; import org.springframework.http.codec.multipart.MultipartHttpMessageReader;
import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader; import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -31,11 +36,11 @@ import org.springframework.util.ClassUtils;
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 5.0 * @since 5.0
*/ */
class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements ServerCodecConfigurer { public class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements ServerCodecConfigurer {
static final boolean synchronossMultipartPresent = ClassUtils.isPresent( static final boolean synchronossMultipartPresent =
"org.synchronoss.cloud.nio.multipart.NioMultipartParser", ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParser",
DefaultServerCodecConfigurer.class.getClassLoader()); DefaultServerCodecConfigurer.class.getClassLoader());
public DefaultServerCodecConfigurer() { public DefaultServerCodecConfigurer() {
@ -62,12 +67,12 @@ class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements Se
} }
@Override @Override
protected boolean splitTextOnNewLine() { boolean splitTextOnNewLine() {
return true; return true;
} }
@Override @Override
public List<HttpMessageReader<?>> getTypedReaders() { List<HttpMessageReader<?>> getTypedReaders() {
if (!shouldRegisterDefaults()) { if (!shouldRegisterDefaults()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -82,7 +87,7 @@ class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements Se
} }
@Override @Override
public List<HttpMessageWriter<?>> getObjectWriters() { List<HttpMessageWriter<?>> getObjectWriters() {
if (!shouldRegisterDefaults()) { if (!shouldRegisterDefaults()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -96,7 +101,7 @@ class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements Se
if (this.sseEncoder != null) { if (this.sseEncoder != null) {
return this.sseEncoder; return this.sseEncoder;
} }
return jackson2Present ? jackson2JsonEncoder() : null; return jackson2Present ? getJackson2JsonEncoder() : null;
} }
} }

11
spring-web/src/main/java/org/springframework/http/codec/support/package-info.java

@ -0,0 +1,11 @@
/**
* Provides implementations of {@link org.springframework.http.codec.ClientCodecConfigurer}
* and {@link org.springframework.http.codec.ServerCodecConfigurer} based on the converter
* implementations from {@code org.springframework.http.codec.json} and co.
*/
@NonNullApi
@NonNullFields
package org.springframework.http.codec.support;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

5
spring-web/src/main/resources/org/springframework/http/codec/CodecConfigurer.properties

@ -0,0 +1,5 @@
# Default CodecConfigurer implementation classes for static Client/ServerCodecConfigurer.create() calls.
# Not meant to be customized by application developers; simply instantiate custom impl classes instead.
org.springframework.http.codec.ClientCodecConfigurer=org.springframework.http.codec.support.DefaultClientCodecConfigurer
org.springframework.http.codec.ServerCodecConfigurer=org.springframework.http.codec.support.DefaultServerCodecConfigurer

25
spring-web/src/test/java/org/springframework/http/codec/ClientCodecConfigurerTests.java → spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec;
package org.springframework.http.codec.support;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Duration; import java.time.Duration;
@ -38,6 +39,14 @@ import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.StringDecoder; import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder; import org.springframework.http.codec.json.Jackson2SmileDecoder;
@ -48,10 +57,11 @@ import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.forClass; import static org.springframework.core.ResolvableType.*;
/** /**
* Unit tests for {@link ClientCodecConfigurer}. * Unit tests for {@link ClientCodecConfigurer}.
*
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class ClientCodecConfigurerTests { public class ClientCodecConfigurerTests {
@ -62,7 +72,7 @@ public class ClientCodecConfigurerTests {
@Test @Test
public void defaultReaders() throws Exception { public void defaultReaders() {
List<HttpMessageReader<?>> readers = this.configurer.getReaders(); List<HttpMessageReader<?>> readers = this.configurer.getReaders();
assertEquals(10, readers.size()); assertEquals(10, readers.size());
assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
@ -70,15 +80,15 @@ public class ClientCodecConfigurerTests {
assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
assertStringDecoder(getNextDecoder(readers), true); assertStringDecoder(getNextDecoder(readers), true);
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertSseReader(readers); assertSseReader(readers);
assertStringDecoder(getNextDecoder(readers), false); assertStringDecoder(getNextDecoder(readers), false);
} }
@Test @Test
public void defaultWriters() throws Exception { public void defaultWriters() {
List<HttpMessageWriter<?>> writers = this.configurer.getWriters(); List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(11, writers.size()); assertEquals(11, writers.size());
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass()); assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
@ -88,15 +98,14 @@ public class ClientCodecConfigurerTests {
assertStringEncoder(getNextEncoder(writers), true); assertStringEncoder(getNextEncoder(writers), true);
assertEquals(FormHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass()); assertEquals(FormHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
assertEquals(MultipartHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass()); assertEquals(MultipartHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertStringEncoder(getNextEncoder(writers), false); assertStringEncoder(getNextEncoder(writers), false);
} }
@Test @Test
public void jackson2EncoderOverride() throws Exception { public void jackson2EncoderOverride() {
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(); Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
this.configurer.defaultCodecs().jackson2JsonDecoder(decoder); this.configurer.defaultCodecs().jackson2JsonDecoder(decoder);

50
spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java → spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec;
package org.springframework.http.codec.support;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -33,6 +34,12 @@ import org.springframework.core.codec.Encoder;
import org.springframework.core.codec.ResourceDecoder; import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.StringDecoder; import org.springframework.core.codec.StringDecoder;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder; import org.springframework.http.codec.json.Jackson2SmileDecoder;
@ -41,12 +48,9 @@ import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertSame; import static org.mockito.Mockito.*;
import static org.junit.Assert.assertTrue; import static org.springframework.core.ResolvableType.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.core.ResolvableType.forClass;
/** /**
* Unit tests for {@link AbstractCodecConfigurer.AbstractDefaultCodecs}. * Unit tests for {@link AbstractCodecConfigurer.AbstractDefaultCodecs}.
@ -60,7 +64,7 @@ public class CodecConfigurerTests {
@Test @Test
public void defaultReaders() throws Exception { public void defaultReaders() {
List<HttpMessageReader<?>> readers = this.configurer.getReaders(); List<HttpMessageReader<?>> readers = this.configurer.getReaders();
assertEquals(9, readers.size()); assertEquals(9, readers.size());
assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
@ -68,14 +72,14 @@ public class CodecConfigurerTests {
assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
assertStringDecoder(getNextDecoder(readers), true); assertStringDecoder(getNextDecoder(readers), true);
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertStringDecoder(getNextDecoder(readers), false); assertStringDecoder(getNextDecoder(readers), false);
} }
@Test @Test
public void defaultWriters() throws Exception { public void defaultWriters() {
List<HttpMessageWriter<?>> writers = this.configurer.getWriters(); List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(9, writers.size()); assertEquals(9, writers.size());
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass()); assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
@ -83,15 +87,14 @@ public class CodecConfigurerTests {
assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass()); assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass()); assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertStringEncoder(getNextEncoder(writers), true); assertStringEncoder(getNextEncoder(writers), true);
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertStringEncoder(getNextEncoder(writers), false); assertStringEncoder(getNextEncoder(writers), false);
} }
@Test @Test
public void defaultAndCustomReaders() throws Exception { public void defaultAndCustomReaders() {
Decoder<?> customDecoder1 = mock(Decoder.class); Decoder<?> customDecoder1 = mock(Decoder.class);
Decoder<?> customDecoder2 = mock(Decoder.class); Decoder<?> customDecoder2 = mock(Decoder.class);
@ -120,17 +123,16 @@ public class CodecConfigurerTests {
assertEquals(StringDecoder.class, getNextDecoder(readers).getClass()); assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
assertSame(customDecoder1, getNextDecoder(readers)); assertSame(customDecoder1, getNextDecoder(readers));
assertSame(customReader1, readers.get(this.index.getAndIncrement())); assertSame(customReader1, readers.get(this.index.getAndIncrement()));
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertSame(customDecoder2, getNextDecoder(readers)); assertSame(customDecoder2, getNextDecoder(readers));
assertSame(customReader2, readers.get(this.index.getAndIncrement())); assertSame(customReader2, readers.get(this.index.getAndIncrement()));
assertEquals(StringDecoder.class, getNextDecoder(readers).getClass()); assertEquals(StringDecoder.class, getNextDecoder(readers).getClass());
} }
@Test @Test
public void defaultAndCustomWriters() throws Exception { public void defaultAndCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class); Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class); Encoder<?> customEncoder2 = mock(Encoder.class);
@ -159,17 +161,16 @@ public class CodecConfigurerTests {
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass()); assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
assertSame(customEncoder1, getNextEncoder(writers)); assertSame(customEncoder1, getNextEncoder(writers));
assertSame(customWriter1, writers.get(this.index.getAndIncrement())); assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertSame(customEncoder2, getNextEncoder(writers)); assertSame(customEncoder2, getNextEncoder(writers));
assertSame(customWriter2, writers.get(this.index.getAndIncrement())); assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass()); assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
} }
@Test @Test
public void defaultsOffCustomReaders() throws Exception { public void defaultsOffCustomReaders() {
Decoder<?> customDecoder1 = mock(Decoder.class); Decoder<?> customDecoder1 = mock(Decoder.class);
Decoder<?> customDecoder2 = mock(Decoder.class); Decoder<?> customDecoder2 = mock(Decoder.class);
@ -200,8 +201,7 @@ public class CodecConfigurerTests {
} }
@Test @Test
public void defaultsOffWithCustomWriters() throws Exception { public void defaultsOffWithCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class); Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class); Encoder<?> customEncoder2 = mock(Encoder.class);
@ -232,8 +232,7 @@ public class CodecConfigurerTests {
} }
@Test @Test
public void jackson2DecoderOverride() throws Exception { public void jackson2DecoderOverride() {
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(); Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
this.configurer.defaultCodecs().jackson2JsonDecoder(decoder); this.configurer.defaultCodecs().jackson2JsonDecoder(decoder);
@ -246,8 +245,7 @@ public class CodecConfigurerTests {
} }
@Test @Test
public void jackson2EncoderOverride() throws Exception { public void jackson2EncoderOverride() {
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(); Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
this.configurer.defaultCodecs().jackson2JsonEncoder(encoder); this.configurer.defaultCodecs().jackson2JsonEncoder(encoder);
@ -295,7 +293,7 @@ public class CodecConfigurerTests {
private static class TestDefaultCodecs extends AbstractDefaultCodecs { private static class TestDefaultCodecs extends AbstractDefaultCodecs {
@Override @Override
protected boolean splitTextOnNewLine() { boolean splitTextOnNewLine() {
return true; return true;
} }
} }

25
spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java → spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.http.codec;
package org.springframework.http.codec.support;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Duration; import java.time.Duration;
@ -39,6 +40,14 @@ import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.StringDecoder; import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder; import org.springframework.http.codec.json.Jackson2SmileDecoder;
@ -50,10 +59,11 @@ import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.forClass; import static org.springframework.core.ResolvableType.*;
/** /**
* Unit tests for {@link ServerCodecConfigurer}. * Unit tests for {@link ServerCodecConfigurer}.
*
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class ServerCodecConfigurerTests { public class ServerCodecConfigurerTests {
@ -64,7 +74,7 @@ public class ServerCodecConfigurerTests {
@Test @Test
public void defaultReaders() throws Exception { public void defaultReaders() {
List<HttpMessageReader<?>> readers = this.configurer.getReaders(); List<HttpMessageReader<?>> readers = this.configurer.getReaders();
assertEquals(12, readers.size()); assertEquals(12, readers.size());
assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
@ -75,14 +85,14 @@ public class ServerCodecConfigurerTests {
assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
assertEquals(SynchronossPartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(SynchronossPartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
assertEquals(MultipartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(MultipartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass());
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
assertStringDecoder(getNextDecoder(readers), false); assertStringDecoder(getNextDecoder(readers), false);
} }
@Test @Test
public void defaultWriters() throws Exception { public void defaultWriters() {
List<HttpMessageWriter<?>> writers = this.configurer.getWriters(); List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(10, writers.size()); assertEquals(10, writers.size());
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass()); assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
@ -90,16 +100,15 @@ public class ServerCodecConfigurerTests {
assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass()); assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass()); assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertStringEncoder(getNextEncoder(writers), true); assertStringEncoder(getNextEncoder(writers), true);
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass()); assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertSseWriter(writers); assertSseWriter(writers);
assertStringEncoder(getNextEncoder(writers), false); assertStringEncoder(getNextEncoder(writers), false);
} }
@Test @Test
public void jackson2EncoderOverride() throws Exception { public void jackson2EncoderOverride() {
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(); Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
this.configurer.defaultCodecs().jackson2JsonEncoder(encoder); this.configurer.defaultCodecs().jackson2JsonEncoder(encoder);
Loading…
Cancel
Save