From 4a7218f54fa881b6e3ca372c0f0eeb67b721059a Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 23 Mar 2017 22:57:59 -0400 Subject: [PATCH 1/3] Introduce ServerCodecConfigurer Issue: SPR-15247 --- .../server/DefaultControllerSpec.java | 27 +- .../web/reactive/server/WebTestClient.java | 15 +- .../http/codec/ServerCodecConfigurer.java | 356 ++++++++++++++++++ .../codec/ServerCodecConfigurerTests.java | 299 +++++++++++++++ .../DelegatingWebFluxConfiguration.java | 22 +- .../config/WebFluxConfigurationSupport.java | 153 +------- .../reactive/config/WebFluxConfigurer.java | 40 +- .../config/WebFluxConfigurerComposite.java | 36 +- .../DefaultHandlerStrategiesBuilder.java | 62 +-- .../RequestMappingHandlerAdapter.java | 12 +- .../DelegatingWebFluxConfigurationTests.java | 12 +- .../WebFluxConfigurationSupportTests.java | 28 +- .../DispatcherHandlerIntegrationTests.java | 7 +- 13 files changed, 731 insertions(+), 338 deletions(-) create mode 100644 spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java create mode 100644 spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java index 512826045b..0d878c8339 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java @@ -25,8 +25,8 @@ import java.util.function.Consumer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.validation.Validator; @@ -85,14 +85,8 @@ class DefaultControllerSpec extends AbstractMockServerSpec>> consumer) { - this.configurer.readersConsumer = consumer; - return this; - } - - @Override - public DefaultControllerSpec messageWriters(Consumer>> consumer) { - this.configurer.writersConsumer = consumer; + public DefaultControllerSpec httpMessageCodecs(Consumer consumer) { + this.configurer.messageCodecsConsumer = consumer; return this; } @@ -145,7 +139,7 @@ class DefaultControllerSpec extends AbstractMockServerSpec pathMatchConsumer; - private Consumer>> readersConsumer; + private Consumer messageCodecsConsumer; private Consumer>> writersConsumer; @@ -178,16 +172,9 @@ class DefaultControllerSpec extends AbstractMockServerSpec> readers) { - if (this.readersConsumer != null) { - this.readersConsumer.accept(readers); - } - } - - @Override - public void extendMessageWriters(List> writers) { - if (this.writersConsumer != null) { - this.writersConsumer.accept(writers); + public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { + if (this.messageCodecsConsumer != null) { + this.messageCodecsConsumer.accept(configurer); } } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index 73869bac55..8b1750ecc1 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -34,8 +34,7 @@ import org.springframework.format.FormatterRegistry; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ClientHttpRequest; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.MultiValueMap; import org.springframework.validation.Validator; import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; @@ -244,16 +243,10 @@ public interface WebTestClient { ControllerSpec pathMatching(Consumer consumer); /** - * Modify or extend the list of built-in message readers. - * @see WebFluxConfigurer#configureMessageReaders + * Modify or extend the list of built-in message readers and writers. + * @see WebFluxConfigurer#configureHttpMessageCodecs */ - ControllerSpec messageReaders(Consumer>> readers); - - /** - * Modify or extend the list of built-in message writers. - * @see WebFluxConfigurer#configureMessageWriters - */ - ControllerSpec messageWriters(Consumer>> writers); + ControllerSpec httpMessageCodecs(Consumer configurer); /** * Register formatters and converters to use for type conversion. 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 new file mode 100644 index 0000000000..c9feafb92c --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java @@ -0,0 +1,356 @@ +/* + * 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.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 + * {@link #registerDefaults(boolean) turned off} completely. + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +public class ServerCodecConfigurer { + + 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; + } + + /** + * 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; + } + + + /** + * 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); + + // 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; + } + + /** + * 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; + } + + + /** + * A registry and a factory for built-in HTTP message readers and writers. + */ + public static class DefaultCodecConfigurer { + + private boolean suppressed = false; + + private final Map, ServerHttpMessageReader> readers = new HashMap<>(); + + private final Map, ServerHttpMessageWriter> 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)); + } + + /** + * 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) { + ServerHttpMessageWriter writer = new ServerSentEventHttpMessageWriter(encoder); + this.writers.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, () -> { + ServerHttpMessageWriter writer = this.writers.get(ServerSentEventHttpMessageWriter.class); + if (writer != null) { + return writer; + } + if (jackson2Present) { + return new ServerSentEventHttpMessageWriter( + findWriter(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 ServerHttpMessageReader}. For readers of type + * {@link DecoderHttpMessageReader} consider using the shortcut + * {@link #decoder(Decoder)} instead. + */ + public void reader(ServerHttpMessageReader reader) { + boolean canReadToObject = reader.canRead(ResolvableType.forClass(Object.class), null); + (canReadToObject ? this.objectReaders : this.typedReaders).add(reader); + } + + /** + * Add a custom {@link ServerHttpMessageWriter}. For readers of type + * {@link EncoderHttpMessageWriter} consider using the shortcut + * {@link #encoder(Encoder)} instead. + */ + public void writer(ServerHttpMessageWriter 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); + } + } + +} 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 new file mode 100644 index 0000000000..09a008c9e6 --- /dev/null +++ b/spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java @@ -0,0 +1,299 @@ +/* + * 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.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; + +/** + * Unit tests for {@link ServerCodecConfigurer}. + * @author Rossen Stoyanchev + */ +public class ServerCodecConfigurerTests { + + private final ServerCodecConfigurer configurer = new ServerCodecConfigurer(); + + 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(9, 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()); + assertSseWriter(writers); + 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); + + ServerHttpMessageReader customReader1 = mock(ServerHttpMessageReader.class); + ServerHttpMessageReader customReader2 = mock(ServerHttpMessageReader.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); + + ServerHttpMessageWriter customWriter1 = mock(ServerHttpMessageWriter.class); + ServerHttpMessageWriter customWriter2 = mock(ServerHttpMessageWriter.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); + + ServerHttpMessageReader customReader1 = mock(ServerHttpMessageReader.class); + ServerHttpMessageReader customReader2 = mock(ServerHttpMessageReader.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); + + ServerHttpMessageWriter customWriter1 = mock(ServerHttpMessageWriter.class); + ServerHttpMessageWriter customWriter2 = mock(ServerHttpMessageWriter.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) + .findFirst() + .map(ServerSentEventHttpMessageWriter::getEncoder) + .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 void assertSseWriter(List> writers) { + ServerHttpMessageWriter writer = writers.get(this.index.getAndIncrement()); + assertEquals(ServerSentEventHttpMessageWriter.class, writer.getClass()); + Encoder encoder = ((ServerSentEventHttpMessageWriter) writer).getEncoder(); + assertNotNull(encoder); + assertEquals(Jackson2JsonEncoder.class, encoder.getClass()); + } + +} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java index 18cb061f3e..a986150401 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java @@ -21,8 +21,7 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.CollectionUtils; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; @@ -76,13 +75,8 @@ public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport } @Override - protected void configureMessageReaders(List> messageReaders) { - this.configurers.configureMessageReaders(messageReaders); - } - - @Override - protected void extendMessageReaders(List> messageReaders) { - this.configurers.extendMessageReaders(messageReaders); + protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { + this.configurers.configureHttpMessageCodecs(configurer); } @Override @@ -100,16 +94,6 @@ public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport return this.configurers.getMessageCodesResolver().orElse(super.getMessageCodesResolver()); } - @Override - protected void configureMessageWriters(List> messageWriters) { - this.configurers.configureMessageWriters(messageWriters); - } - - @Override - protected void extendMessageWriters(List> messageWriters) { - this.configurers.extendMessageWriters(messageWriters); - } - @Override protected void configureViewResolvers(ViewResolverRegistry registry) { this.configurers.configureViewResolvers(registry); 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 fc657dfa12..c8f6ed9a7c 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 @@ -30,32 +30,13 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.annotation.Order; -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.Encoder; -import org.springframework.core.codec.ResourceDecoder; -import org.springframework.core.codec.StringDecoder; import org.springframework.core.convert.converter.Converter; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.FormattingConversionService; import org.springframework.http.MediaType; -import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.EncoderHttpMessageWriter; -import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; -import org.springframework.http.codec.ServerSentEventHttpMessageWriter; -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.http.codec.ServerCodecConfigurer; import org.springframework.util.ClassUtils; import org.springframework.validation.Errors; import org.springframework.validation.MessageCodesResolver; @@ -104,9 +85,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { private PathMatchConfigurer pathMatchConfigurer; - private List> messageReaders; - - private List> messageWriters; + private ServerCodecConfigurer messageCodecsConfigurer; private ApplicationContext applicationContext; @@ -267,7 +246,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); - adapter.setMessageReaders(getMessageReaders()); + adapter.setMessageReaders(getMessageCodecsConfigurer().getReaders()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry()); @@ -294,58 +273,22 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { } /** - * Main method to access message readers to use for decoding - * controller method arguments with. - *

Use {@link #configureMessageReaders} to configure the list or - * {@link #extendMessageReaders} to add in addition to the default ones. + * Main method to access the configurer for HTTP message readers and writers. + *

Use {@link #configureHttpMessageCodecs(ServerCodecConfigurer)} to + * configure the readers and writers. */ - protected final List> getMessageReaders() { - if (this.messageReaders == null) { - this.messageReaders = new ArrayList<>(); - configureMessageReaders(this.messageReaders); - if (this.messageReaders.isEmpty()) { - addDefaultHttpMessageReaders(this.messageReaders); - } - extendMessageReaders(this.messageReaders); + protected final ServerCodecConfigurer getMessageCodecsConfigurer() { + if (this.messageCodecsConfigurer == null) { + this.messageCodecsConfigurer = new ServerCodecConfigurer(); + configureHttpMessageCodecs(this.getMessageCodecsConfigurer()); } - return this.messageReaders; + return this.messageCodecsConfigurer; } /** - * Override to configure the message readers to use for decoding - * controller method arguments. - *

If no message readres are specified, default will be added via - * {@link #addDefaultHttpMessageReaders}. - * @param messageReaders a list to add message readers to, initially an empty + * Override to configure the HTTP message readers and writers to use. */ - protected void configureMessageReaders(List> messageReaders) { - } - - /** - * Adds default converters that sub-classes can call from - * {@link #configureMessageReaders(List)} for {@code byte[]}, - * {@code ByteBuffer}, {@code String}, {@code Resource}, JAXB2, and Jackson - * (if present on the classpath). - */ - protected final void addDefaultHttpMessageReaders(List> readers) { - readers.add(new DecoderHttpMessageReader<>(new ByteArrayDecoder())); - readers.add(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); - readers.add(new DecoderHttpMessageReader<>(new DataBufferDecoder())); - readers.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); - readers.add(new DecoderHttpMessageReader<>(new ResourceDecoder())); - if (jaxb2Present) { - readers.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); - } - if (jackson2Present) { - readers.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())); - } - } - - /** - * Override this to modify the list of message readers after it has been - * configured, for example to add some in addition to the default ones. - */ - protected void extendMessageReaders(List> messageReaders) { + protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { } /** @@ -435,76 +378,14 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { @Bean public ResponseEntityResultHandler responseEntityResultHandler() { - return new ResponseEntityResultHandler( - getMessageWriters(), webFluxContentTypeResolver(), webFluxAdapterRegistry()); + return new ResponseEntityResultHandler(getMessageCodecsConfigurer().getWriters(), + webFluxContentTypeResolver(), webFluxAdapterRegistry()); } @Bean public ResponseBodyResultHandler responseBodyResultHandler() { - return new ResponseBodyResultHandler( - getMessageWriters(), webFluxContentTypeResolver(), webFluxAdapterRegistry()); - } - - /** - * Main method to access message writers to use for encoding return values. - *

Use {@link #configureMessageWriters(List)} to configure the list or - * {@link #extendMessageWriters(List)} to add in addition to the default ones. - */ - protected final List> getMessageWriters() { - if (this.messageWriters == null) { - this.messageWriters = new ArrayList<>(); - configureMessageWriters(this.messageWriters); - if (this.messageWriters.isEmpty()) { - addDefaultHttpMessageWriters(this.messageWriters); - } - extendMessageWriters(this.messageWriters); - } - return this.messageWriters; - } - /** - * Override to configure the message writers to use for encoding - * return values. - *

If no message readers are specified, default will be added via - * {@link #addDefaultHttpMessageWriters}. - * @param messageWriters a list to add message writers to, initially an empty - */ - protected void configureMessageWriters(List> messageWriters) { - } - - /** - * Adds default converters that sub-classes can call from - * {@link #configureMessageWriters(List)}. - */ - protected final void addDefaultHttpMessageWriters(List> writers) { - writers.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder())); - writers.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); - writers.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder())); - writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); - writers.add(new ResourceHttpMessageWriter()); - if (jaxb2Present) { - writers.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); - } - if (jackson2Present) { - writers.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder())); - } - writers.add(new ServerSentEventHttpMessageWriter(getSseEncoder())); - writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); - } - - private Encoder getSseEncoder() { - if (jackson2Present) { - return new Jackson2JsonEncoder(); - } - else { - return null; - } - } - - /** - * Override this to modify the list of message writers after it has been - * configured, for example to add some in addition to the default ones. - */ - protected void extendMessageWriters(List> messageWriters) { + return new ResponseBodyResultHandler(getMessageCodecsConfigurer().getWriters(), + webFluxContentTypeResolver(), webFluxAdapterRegistry()); } @Bean diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java index fdf29d8f54..1f51f69901 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java @@ -22,8 +22,7 @@ import java.util.Optional; import org.springframework.core.convert.converter.Converter; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.reactive.accept.CompositeContentTypeResolver; @@ -89,22 +88,10 @@ public interface WebFluxConfigurer { } /** - * Configure the message readers to use for decoding the request body where - * {@code @RequestBody} and {@code HttpEntity} controller method arguments - * are used. If none are specified, default ones are added based on - * {@link WebFluxConfigurationSupport#addDefaultHttpMessageReaders}. - *

See {@link #extendMessageReaders(List)} for adding readers - * in addition to the default ones. - * @param readers an empty list to add message readers to + * Configure custom HTTP message readers and writers or override built-in ones. + * @param configurer the configurer to use */ - default void configureMessageReaders(List> readers) { - } - - /** - * An alternative to {@link #configureMessageReaders(List)} that allows - * modifying the message readers to use after default ones have been added. - */ - default void extendMessageReaders(List> readers) { + default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { } /** @@ -132,25 +119,6 @@ public interface WebFluxConfigurer { return Optional.empty(); } - /** - * Configure the message writers to use to encode the response body based on - * the return values of {@code @ResponseBody}, and {@code ResponseEntity} - * controller methods. If none are specified, default ones are added based on - * {@link WebFluxConfigurationSupport#addDefaultHttpMessageWriters(List)}. - *

See {@link #extendMessageWriters(List)} for adding writers - * in addition to the default ones. - * @param writers a empty list to add message writers to - */ - default void configureMessageWriters(List> writers) { - } - - /** - * An alternative to {@link #configureMessageWriters(List)} that allows - * modifying the message writers to use after default ones have been added. - */ - default void extendMessageWriters(List> writers) { - } - /** * Configure view resolution for processing the return values of controller * methods that rely on resolving a diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurerComposite.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurerComposite.java index 51070f12c0..bfb92ff1bb 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurerComposite.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurerComposite.java @@ -23,8 +23,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.CollectionUtils; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; @@ -52,42 +51,37 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer { @Override public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { - this.delegates.stream().forEach(delegate -> delegate.configureContentTypeResolver(builder)); + this.delegates.forEach(delegate -> delegate.configureContentTypeResolver(builder)); } @Override public void addCorsMappings(CorsRegistry registry) { - this.delegates.stream().forEach(delegate -> delegate.addCorsMappings(registry)); + this.delegates.forEach(delegate -> delegate.addCorsMappings(registry)); } @Override public void configurePathMatching(PathMatchConfigurer configurer) { - this.delegates.stream().forEach(delegate -> delegate.configurePathMatching(configurer)); + this.delegates.forEach(delegate -> delegate.configurePathMatching(configurer)); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - this.delegates.stream().forEach(delegate -> delegate.addResourceHandlers(registry)); + this.delegates.forEach(delegate -> delegate.addResourceHandlers(registry)); } @Override public void addArgumentResolvers(List resolvers) { - this.delegates.stream().forEach(delegate -> delegate.addArgumentResolvers(resolvers)); + this.delegates.forEach(delegate -> delegate.addArgumentResolvers(resolvers)); } @Override - public void configureMessageReaders(List> readers) { - this.delegates.stream().forEach(delegate -> delegate.configureMessageReaders(readers)); - } - - @Override - public void extendMessageReaders(List> readers) { - this.delegates.stream().forEach(delegate -> delegate.extendMessageReaders(readers)); + public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { + this.delegates.forEach(delegate -> delegate.configureHttpMessageCodecs(configurer)); } @Override public void addFormatters(FormatterRegistry registry) { - this.delegates.stream().forEach(delegate -> delegate.addFormatters(registry)); + this.delegates.forEach(delegate -> delegate.addFormatters(registry)); } @Override @@ -100,19 +94,9 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer { return createSingleBean(WebFluxConfigurer::getMessageCodesResolver, MessageCodesResolver.class); } - @Override - public void configureMessageWriters(List> writers) { - this.delegates.stream().forEach(delegate -> delegate.configureMessageWriters(writers)); - } - - @Override - public void extendMessageWriters(List> writers) { - this.delegates.stream().forEach(delegate -> delegate.extendMessageWriters(writers)); - } - @Override public void configureViewResolvers(ViewResolverRegistry registry) { - this.delegates.stream().forEach(delegate -> delegate.configureViewResolvers(registry)); + this.delegates.forEach(delegate -> delegate.configureViewResolvers(registry)); } private Optional createSingleBean(Function> factory, diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java index 218b8df555..2d2d334149 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java @@ -26,26 +26,10 @@ import java.util.function.Supplier; import java.util.stream.Stream; import org.springframework.context.ApplicationContext; -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.Encoder; -import org.springframework.core.codec.StringDecoder; -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.ServerSentEventHttpMessageWriter; -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.http.codec.ServerCodecConfigurer; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.web.reactive.result.view.ViewResolver; /** @@ -61,16 +45,6 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { .map(Locale.LanguageRange::getRange) .map(Locale::forLanguageTag).findFirst(); - private static final boolean jackson2Present = - ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", - DefaultHandlerStrategiesBuilder.class.getClassLoader()) && - ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", - DefaultHandlerStrategiesBuilder.class.getClassLoader()); - - private static final boolean jaxb2Present = - ClassUtils.isPresent("javax.xml.bind.Binder", - DefaultHandlerStrategiesBuilder.class.getClassLoader()); - private final List> messageReaders = new ArrayList<>(); @@ -82,40 +56,12 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { public void defaultConfiguration() { - messageReader(new DecoderHttpMessageReader<>(new ByteArrayDecoder())); - messageReader(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); - messageReader(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); - messageReader(new FormHttpMessageReader()); - - messageWriter(new EncoderHttpMessageWriter<>(new ByteArrayEncoder())); - messageWriter(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); - messageWriter(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); - messageWriter(new ResourceHttpMessageWriter()); - - if (jaxb2Present) { - messageReader(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); - messageWriter(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); - } - if (jackson2Present) { - messageReader(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())); - messageWriter(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder())); - } - - messageWriter(new ServerSentEventHttpMessageWriter(getSseEncoder())); - messageWriter(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); - + ServerCodecConfigurer configurer = new ServerCodecConfigurer(); + configurer.getReaders().forEach(this::messageReader); + configurer.getWriters().forEach(this::messageWriter); localeResolver(DEFAULT_LOCALE_RESOLVER); } - private Encoder getSseEncoder() { - if (jackson2Present) { - return new Jackson2JsonEncoder(); - } - else { - return null; - } - } - public void applicationContext(ApplicationContext applicationContext) { applicationContext.getBeansOfType(HttpMessageReader.class).values().forEach(this::messageReader); applicationContext.getBeansOfType(HttpMessageWriter.class).values().forEach(this::messageWriter); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java index dbed19a45c..9a062d5e46 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java @@ -42,8 +42,10 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.codec.ByteArrayDecoder; import org.springframework.core.codec.ByteBufferDecoder; import org.springframework.core.codec.DataBufferDecoder; +import org.springframework.core.codec.ResourceDecoder; import org.springframework.core.codec.StringDecoder; import org.springframework.http.codec.DecoderHttpMessageReader; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.ServerHttpMessageReader; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -114,16 +116,20 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application public RequestMappingHandlerAdapter() { - // TODO: improve with better (shared) defaults this.messageReaders.add(new DecoderHttpMessageReader<>(new ByteArrayDecoder())); this.messageReaders.add(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); this.messageReaders.add(new DecoderHttpMessageReader<>(new DataBufferDecoder())); + this.messageReaders.add(new DecoderHttpMessageReader<>(new ResourceDecoder())); this.messageReaders.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); } /** - * Configure message readers to de-serialize the request body with. + * Configure HTTP message readers to de-serialize the request body with. + *

By default only basic data types such as bytes and text are registered. + * Consider using {@link ServerCodecConfigurer} to configure a richer list + * including JSON encoding . + * @see ServerCodecConfigurer */ public void setMessageReaders(List> messageReaders) { this.messageReaders.clear(); @@ -131,7 +137,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application } /** - * Return the configured message readers. + * Return the configured HTTP message readers. */ public List> getMessageReaders() { return this.messageReaders; diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java index dc1fbc1494..8a373ab0f8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java @@ -30,8 +30,8 @@ import org.mockito.MockitoAnnotations; import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.convert.ConversionService; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; @@ -58,7 +58,7 @@ public class DelegatingWebFluxConfigurationTests { private WebFluxConfigurer webFluxConfigurer; @Captor - private ArgumentCaptor>> readers; + private ArgumentCaptor codecsConfigurer; @Captor private ArgumentCaptor>> writers; @@ -96,15 +96,14 @@ public class DelegatingWebFluxConfigurationTests { ConversionService initializerConversionService = initializer.getConversionService(); assertTrue(initializer.getValidator() instanceof LocalValidatorFactoryBean); - verify(webFluxConfigurer).configureMessageReaders(readers.capture()); - verify(webFluxConfigurer).extendMessageReaders(readers.capture()); + verify(webFluxConfigurer).configureHttpMessageCodecs(codecsConfigurer.capture()); verify(webFluxConfigurer).getValidator(); verify(webFluxConfigurer).getMessageCodesResolver(); verify(webFluxConfigurer).addFormatters(formatterRegistry.capture()); verify(webFluxConfigurer).addArgumentResolvers(any()); assertSame(formatterRegistry.getValue(), initializerConversionService); - assertEquals(7, readers.getValue().size()); + assertEquals(8, codecsConfigurer.getValue().getReaders().size()); } @Test @@ -126,8 +125,7 @@ public class DelegatingWebFluxConfigurationTests { delegatingConfig.setConfigurers(Collections.singletonList(webFluxConfigurer)); delegatingConfig.responseBodyResultHandler(); - verify(webFluxConfigurer).configureMessageWriters(writers.capture()); - verify(webFluxConfigurer).extendMessageWriters(writers.capture()); + verify(webFluxConfigurer).configureHttpMessageCodecs(codecsConfigurer.capture()); verify(webFluxConfigurer).configureContentTypeResolver(any(RequestedContentTypeResolverBuilder.class)); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java index 99919d89e3..db3efd0ac1 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java @@ -34,10 +34,9 @@ import org.springframework.core.codec.StringDecoder; import org.springframework.core.convert.ConversionService; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; -import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.ServerHttpMessageReader; import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlDecoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; @@ -128,7 +127,7 @@ public class WebFluxConfigurationSupportTests { assertNotNull(adapter); List> readers = adapter.getMessageReaders(); - assertEquals(7, readers.size()); + assertEquals(8, readers.size()); assertHasMessageReader(readers, byte[].class, APPLICATION_OCTET_STREAM); assertHasMessageReader(readers, ByteBuffer.class, APPLICATION_OCTET_STREAM); @@ -297,23 +296,12 @@ public class WebFluxConfigurationSupportTests { static class CustomMessageConverterConfig extends WebFluxConfigurationSupport { @Override - protected void configureMessageReaders(List> messageReaders) { - messageReaders.add(new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly(true))); - } - - @Override - protected void configureMessageWriters(List> messageWriters) { - messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); - } - - @Override - protected void extendMessageReaders(List> messageReaders) { - messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); - } - - @Override - protected void extendMessageWriters(List> messageWriters) { - messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); + protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { + configurer.registerDefaults(false); + configurer.customCodec().decoder(StringDecoder.textPlainOnly(true)); + configurer.customCodec().decoder(new Jaxb2XmlDecoder()); + configurer.customCodec().encoder(CharSequenceEncoder.textPlainOnly()); + configurer.customCodec().encoder(new Jaxb2XmlEncoder()); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DispatcherHandlerIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DispatcherHandlerIntegrationTests.java index 911436c0ec..7563397ad8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DispatcherHandlerIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DispatcherHandlerIntegrationTests.java @@ -120,16 +120,19 @@ public class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegr @Bean public HandlerMapping handlerMapping(RouterFunction routerFunction, ApplicationContext applicationContext) { + return RouterFunctions.toHandlerMapping(routerFunction, new HandlerStrategies() { @Override public Supplier>> messageReaders() { - return () -> getMessageReaders().stream().map(reader -> (HttpMessageReader) reader); + return () -> getMessageCodecsConfigurer().getReaders().stream() + .map(reader -> (HttpMessageReader) reader); } @Override public Supplier>> messageWriters() { - return () -> getMessageWriters().stream().map(writer -> (HttpMessageWriter) writer); + return () -> getMessageCodecsConfigurer().getWriters().stream() + .map(writer -> (HttpMessageWriter) writer); } @Override From 5414cd0cf8228d4cd1a3873ae18b4fcb91b6e556 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 24 Mar 2017 17:36:28 -0400 Subject: [PATCH 2/3] Collape ServerHttpMessage[Reader|Writer] This commit folds ServerHttpMessage[Reader|Writer] into its parent HttpMessage[Reader|Writer] with the server methods pre-implemented by default to be simple pass-through delegates. --- .../server/DefaultControllerSpec.java | 4 +- .../http/codec/DecoderHttpMessageReader.java | 6 +- .../http/codec/EncoderHttpMessageWriter.java | 6 +- .../http/codec/HttpMessageReader.java | 42 +++++++++++ .../http/codec/HttpMessageWriter.java | 25 +++++++ .../http/codec/ResourceHttpMessageWriter.java | 8 +-- .../http/codec/ServerCodecConfigurer.java | 62 ++++++++--------- .../http/codec/ServerHttpMessageReader.java | 69 ------------------- .../http/codec/ServerHttpMessageWriter.java | 57 --------------- .../ServerSentEventHttpMessageWriter.java | 4 +- .../codec/ServerCodecConfigurerTests.java | 36 +++++----- ...AbstractMessageReaderArgumentResolver.java | 16 ++--- .../AbstractMessageWriterResultHandler.java | 16 ++--- .../HttpEntityArgumentResolver.java | 4 +- .../RequestBodyArgumentResolver.java | 4 +- .../RequestMappingHandlerAdapter.java | 8 +-- .../annotation/ResponseBodyResultHandler.java | 8 +-- .../ResponseEntityResultHandler.java | 6 +- .../DelegatingWebFluxConfigurationTests.java | 4 +- .../WebFluxConfigurationSupportTests.java | 16 ++--- .../HttpEntityArgumentResolverTests.java | 4 +- .../MessageReaderArgumentResolverTests.java | 4 +- .../MessageWriterResultHandlerTests.java | 8 +-- .../RequestBodyArgumentResolverTests.java | 4 +- .../ResponseBodyResultHandlerTests.java | 4 +- .../ResponseEntityResultHandlerTests.java | 6 +- 26 files changed, 186 insertions(+), 245 deletions(-) delete mode 100644 spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageReader.java delete mode 100644 spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageWriter.java diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java index 0d878c8339..ad2577b2af 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultControllerSpec.java @@ -25,7 +25,7 @@ import java.util.function.Consumer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -141,7 +141,7 @@ class DefaultControllerSpec extends AbstractMockServerSpec messageCodecsConsumer; - private Consumer>> writersConsumer; + private Consumer>> writersConsumer; private Consumer formattersConsumer; diff --git a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java index 266a6dd46d..b57b9ad66a 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java @@ -36,7 +36,7 @@ import org.springframework.util.Assert; /** * {@code HttpMessageReader} that wraps and delegates to a {@link Decoder}. * - *

Also a {@code ServerHttpMessageReader} that pre-resolves decoding hints + *

Also a {@code HttpMessageReader} that pre-resolves decoding hints * from the extra information available on the server side such as the request * or controller method parameter annotations. * @@ -45,7 +45,7 @@ import org.springframework.util.Assert; * @author Rossen Stoyanchev * @since 5.0 */ -public class DecoderHttpMessageReader implements ServerHttpMessageReader { +public class DecoderHttpMessageReader implements HttpMessageReader { private final Decoder decoder; @@ -102,7 +102,7 @@ public class DecoderHttpMessageReader implements ServerHttpMessageReader { } - // ServerHttpMessageReader... + // Server-side only... @Override public Flux read(ResolvableType actualType, ResolvableType elementType, diff --git a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java index c7397c475b..e3209b0c9c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java @@ -37,7 +37,7 @@ import org.springframework.util.Assert; /** * {@code HttpMessageWriter} that wraps and delegates to a {@link Encoder}. * - *

Also a {@code ServerHttpMessageWriter} that pre-resolves encoding hints + *

Also a {@code HttpMessageWriter} that pre-resolves encoding hints * from the extra information available on the server side such as the request * or controller method annotations. * @@ -46,7 +46,7 @@ import org.springframework.util.Assert; * @author Rossen Stoyanchev * @since 5.0 */ -public class EncoderHttpMessageWriter implements ServerHttpMessageWriter { +public class EncoderHttpMessageWriter implements HttpMessageWriter { private final Encoder encoder; @@ -136,7 +136,7 @@ public class EncoderHttpMessageWriter implements ServerHttpMessageWriter { } - // ServerHttpMessageWriter... + // Server side only... @Override public Mono write(Publisher inputStream, ResolvableType actualType, diff --git a/spring-web/src/main/java/org/springframework/http/codec/HttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageReader.java index 009de9b0d8..0fbc036deb 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/HttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageReader.java @@ -22,9 +22,12 @@ import java.util.Map; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.http.MediaType; import org.springframework.http.ReactiveHttpInputMessage; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; /** * Strategy for reading from a {@link ReactiveHttpInputMessage} and decoding @@ -74,5 +77,44 @@ public interface HttpMessageReader { */ Mono readMono(ResolvableType elementType, ReactiveHttpInputMessage message, Map hints); + /** + * Server-side only alternative to + * {@link #read(ResolvableType, ReactiveHttpInputMessage, Map)} with + * additional context available. + * + * @param actualType the actual type of the target method parameter; for + * annotated controllers, the {@link MethodParameter} can be accessed via + * {@link ResolvableType#getSource()}. + * @param elementType the type of Objects in the output stream + * @param request the current request + * @param response the current response + * @param hints additional information about how to read the body + * @return the decoded stream of elements + */ + default Flux read(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request, + ServerHttpResponse response, Map hints) { + + return read(elementType, request, hints); + } + + /** + * Server-side only alternative to + * {@link #readMono(ResolvableType, ReactiveHttpInputMessage, Map)} with + * additional, context available. + * + * @param actualType the actual type of the target method parameter; for + * annotated controllers, the {@link MethodParameter} can be accessed via + * {@link ResolvableType#getSource()}. + * @param elementType the type of Objects in the output stream + * @param request the current request + * @param response the current response + * @param hints additional information about how to read the body + * @return the decoded stream of elements + */ + default Mono readMono(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request, + ServerHttpResponse response, Map hints) { + + return readMono(elementType, request, hints); + } } diff --git a/spring-web/src/main/java/org/springframework/http/codec/HttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageWriter.java index 6083f905fa..848341cd3a 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/HttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageWriter.java @@ -22,9 +22,12 @@ import java.util.Map; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; +import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.http.MediaType; import org.springframework.http.ReactiveHttpOutputMessage; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; /** * Strategy for encoding a stream of objects of type {@code } and writing @@ -67,4 +70,26 @@ public interface HttpMessageWriter { MediaType mediaType, ReactiveHttpOutputMessage message, Map hints); + /** + * Server-side only alternative to + * {@link #write(Publisher, ResolvableType, MediaType, ReactiveHttpOutputMessage, Map)} + * with additional context available. + * + * @param actualType the actual return type of the method that returned the + * value; for annotated controllers, the {@link MethodParameter} can be + * accessed via {@link ResolvableType#getSource()}. + * @param elementType the type of Objects in the input stream + * @param mediaType the content type to use, possibly {@code null} indicating + * the default content type of the writer should be used. + * @param request the current request + * @param response the current response + * @return a {@link Mono} that indicates completion of writing or error + */ + default Mono write(Publisher inputStream, ResolvableType actualType, + ResolvableType elementType, MediaType mediaType, ServerHttpRequest request, + ServerHttpResponse response, Map hints) { + + return write(inputStream, elementType, mediaType, response, hints); + } + } diff --git a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java index d074e9d234..a5da877917 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java @@ -53,7 +53,7 @@ import static java.util.Collections.emptyMap; /** * {@code HttpMessageWriter} that can write a {@link Resource}. * - *

Also an implementation of {@code ServerHttpMessageWriter} with support + *

Also an implementation of {@code HttpMessageWriter} with support * for writing one or more {@link ResourceRegion}'s based on the HTTP ranges * specified in the request. * @@ -68,7 +68,7 @@ import static java.util.Collections.emptyMap; * @see ResourceRegionEncoder * @see HttpRange */ -public class ResourceHttpMessageWriter implements ServerHttpMessageWriter { +public class ResourceHttpMessageWriter implements HttpMessageWriter { private static final ResolvableType REGION_TYPE = ResolvableType.forClass(ResourceRegion.class); @@ -102,7 +102,7 @@ public class ResourceHttpMessageWriter implements ServerHttpMessageWriter write(Publisher inputStream, ResolvableType elementType, @@ -171,7 +171,7 @@ public class ResourceHttpMessageWriter implements ServerHttpMessageWriter> getReaders() { + public List> getReaders() { // Built-in, concrete Java type readers - List> result = new ArrayList<>(); + 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); @@ -131,10 +131,10 @@ public class ServerCodecConfigurer { /** * Prepare a list of HTTP message writers. */ - public List> getWriters() { + public List> getWriters() { // Built-in, concrete Java type readers - List> result = new ArrayList<>(); + 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); @@ -169,9 +169,9 @@ public class ServerCodecConfigurer { private boolean suppressed = false; - private final Map, ServerHttpMessageReader> readers = new HashMap<>(); + private final Map, HttpMessageReader> readers = new HashMap<>(); - private final Map, ServerHttpMessageWriter> writers = new HashMap<>(); + private final Map, HttpMessageWriter> writers = new HashMap<>(); /** @@ -197,7 +197,7 @@ public class ServerCodecConfigurer { * @param encoder the encoder to use */ public void sse(Encoder encoder) { - ServerHttpMessageWriter writer = new ServerSentEventHttpMessageWriter(encoder); + HttpMessageWriter writer = new ServerSentEventHttpMessageWriter(encoder); this.writers.put(ServerSentEventHttpMessageWriter.class, writer); } @@ -208,14 +208,14 @@ public class ServerCodecConfigurer { this.suppressed = suppressed; } - private > void addReaderTo(List> result, + private > void addReaderTo(List> result, Class key, Supplier fallback) { addReaderTo(result, () -> findReader(key, fallback)); } - private void addReaderTo(List> result, - Supplier> reader) { + private void addReaderTo(List> result, + Supplier> reader) { if (!this.suppressed) { result.add(reader.get()); @@ -230,14 +230,14 @@ public class ServerCodecConfigurer { } - private > void addWriterTo(List> result, + private > void addWriterTo(List> result, Class key, Supplier fallback) { addWriterTo(result, () -> findWriter(key, fallback)); } - private void addWriterTo(List> result, - Supplier> writer) { + private void addWriterTo(List> result, + Supplier> writer) { if (!this.suppressed) { result.add(writer.get()); @@ -252,25 +252,25 @@ public class ServerCodecConfigurer { } - private void addStringReaderTextOnlyTo(List> result) { + private void addStringReaderTextOnlyTo(List> result) { addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly(true))); } - private void addStringReaderTo(List> result) { + private void addStringReaderTo(List> result) { addReaderTo(result, () -> new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); } - private void addStringWriterTextPlainOnlyTo(List> result) { + private void addStringWriterTextPlainOnlyTo(List> result) { addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); } - private void addStringWriterTo(List> result) { + private void addStringWriterTo(List> result) { addWriterTo(result, () -> new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); } - private void addSseWriterTo(List> result) { + private void addSseWriterTo(List> result) { addWriterTo(result, () -> { - ServerHttpMessageWriter writer = this.writers.get(ServerSentEventHttpMessageWriter.class); + HttpMessageWriter writer = this.writers.get(ServerSentEventHttpMessageWriter.class); if (writer != null) { return writer; } @@ -288,13 +288,13 @@ public class ServerCodecConfigurer { */ public static class CustomCodecConfigurer { - private final List> typedReaders = new ArrayList<>(); + private final List> typedReaders = new ArrayList<>(); - private final List> typedWriters = new ArrayList<>(); + private final List> typedWriters = new ArrayList<>(); - private final List> objectReaders = new ArrayList<>(); + private final List> objectReaders = new ArrayList<>(); - private final List> objectWriters = new ArrayList<>(); + private final List> objectWriters = new ArrayList<>(); /** @@ -314,21 +314,21 @@ public class ServerCodecConfigurer { } /** - * Add a custom {@link ServerHttpMessageReader}. For readers of type + * Add a custom {@link HttpMessageReader}. For readers of type * {@link DecoderHttpMessageReader} consider using the shortcut * {@link #decoder(Decoder)} instead. */ - public void reader(ServerHttpMessageReader reader) { + 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 ServerHttpMessageWriter}. For readers of type + * Add a custom {@link HttpMessageWriter}. For readers of type * {@link EncoderHttpMessageWriter} consider using the shortcut * {@link #encoder(Encoder)} instead. */ - public void writer(ServerHttpMessageWriter writer) { + public void writer(HttpMessageWriter writer) { boolean canWriteObject = writer.canWrite(ResolvableType.forClass(Object.class), null); (canWriteObject ? this.objectWriters : this.typedWriters).add(writer); } @@ -336,19 +336,19 @@ public class ServerCodecConfigurer { // Internal methods for building a list of custom readers or writers... - private void addTypedReadersTo(List> result) { + private void addTypedReadersTo(List> result) { result.addAll(this.typedReaders); } - private void addObjectReadersTo(List> result) { + private void addObjectReadersTo(List> result) { result.addAll(this.objectReaders); } - private void addTypedWritersTo(List> result) { + private void addTypedWritersTo(List> result) { result.addAll(this.typedWriters); } - private void addObjectWritersTo(List> result) { + private void addObjectWritersTo(List> result) { result.addAll(this.objectWriters); } } diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageReader.java deleted file mode 100644 index 1509b42ddd..0000000000 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageReader.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.Map; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.core.MethodParameter; -import org.springframework.core.ResolvableType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; - -/** - * An extension of {@code HttpMessageReader} for decoding and reading the - * request body with extra information available on the server side. - * - * @author Sebastien Deleuze - * @author Rossen Stoyanchev - * @since 5.0 - */ -public interface ServerHttpMessageReader extends HttpMessageReader { - - /** - * Decode and read the request body to an object stream. - * - * @param actualType the actual type of the target method parameter; for - * annotated controllers, the {@link MethodParameter} can be accessed via - * {@link ResolvableType#getSource()}. - * @param elementType the type of Objects in the output stream - * @param request the current request - * @param response the current response - * @param hints additional information about how to read the body - * @return the decoded stream of elements - */ - Flux read(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request, - ServerHttpResponse response, Map hints); - - /** - * Decode and read the request body to a single object. - * - * @param actualType the actual type of the target method parameter; for - * annotated controllers, the {@link MethodParameter} can be accessed via - * {@link ResolvableType#getSource()}. - * @param elementType the type of Objects in the output stream - * @param request the current request - * @param response the current response - * @param hints additional information about how to read the body - * @return the decoded stream of elements - */ - Mono readMono(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request, - ServerHttpResponse response, Map hints); - -} diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageWriter.java deleted file mode 100644 index 5758d728c5..0000000000 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerHttpMessageWriter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.Map; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Mono; - -import org.springframework.core.MethodParameter; -import org.springframework.core.ResolvableType; -import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; - -/** - * An extension of {@code HttpMessageWriter} for encoding and writing the - * response body with extra information available on the server side. - * - * @author Sebastien Deleuze - * @author Rossen Stoyanchev - * @since 5.0 - */ -public interface ServerHttpMessageWriter extends HttpMessageWriter { - - /** - * Encode and write the given object stream to the response. - * - * @param actualType the actual return type of the method that returned the - * value; for annotated controllers, the {@link MethodParameter} can be - * accessed via {@link ResolvableType#getSource()}. - * @param elementType the type of Objects in the input stream - * @param mediaType the content type to use, possibly {@code null} indicating - * the default content type of the writer should be used. - * @param request the current request - * @param response the current response - * @return a {@link Mono} that indicates completion of writing or error - */ - Mono write(Publisher inputStream, ResolvableType actualType, - ResolvableType elementType, MediaType mediaType, ServerHttpRequest request, - ServerHttpResponse response, Map hints); - -} diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java index bfe2c42bcb..c280cb70f0 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java @@ -37,14 +37,14 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; /** - * {@code ServerHttpMessageWriter} for {@code "text/event-stream"} responses. + * {@code HttpMessageWriter} for {@code "text/event-stream"} responses. * * @author Sebastien Deleuze * @author Arjen Poutsma * @author Rossen Stoyanchev * @since 5.0 */ -public class ServerSentEventHttpMessageWriter implements ServerHttpMessageWriter { +public class ServerSentEventHttpMessageWriter implements HttpMessageWriter { private static final List WRITABLE_MEDIA_TYPES = Collections.singletonList(MediaType.TEXT_EVENT_STREAM); 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 09a008c9e6..b9ed7694d3 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 @@ -60,7 +60,7 @@ public class ServerCodecConfigurerTests { @Test public void defaultReaders() throws Exception { - List> readers = this.configurer.getReaders(); + List> readers = this.configurer.getReaders(); assertEquals(8, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass()); @@ -74,7 +74,7 @@ public class ServerCodecConfigurerTests { @Test public void defaultWriters() throws Exception { - List> writers = this.configurer.getWriters(); + List> writers = this.configurer.getWriters(); assertEquals(9, writers.size()); assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass()); assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass()); @@ -96,8 +96,8 @@ public class ServerCodecConfigurerTests { when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false); when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true); - ServerHttpMessageReader customReader1 = mock(ServerHttpMessageReader.class); - ServerHttpMessageReader customReader2 = mock(ServerHttpMessageReader.class); + 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); @@ -108,7 +108,7 @@ public class ServerCodecConfigurerTests { this.configurer.customCodec().reader(customReader1); this.configurer.customCodec().reader(customReader2); - List> readers = this.configurer.getReaders(); + List> readers = this.configurer.getReaders(); assertEquals(12, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); @@ -134,8 +134,8 @@ public class ServerCodecConfigurerTests { when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false); when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true); - ServerHttpMessageWriter customWriter1 = mock(ServerHttpMessageWriter.class); - ServerHttpMessageWriter customWriter2 = mock(ServerHttpMessageWriter.class); + 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); @@ -146,7 +146,7 @@ public class ServerCodecConfigurerTests { this.configurer.customCodec().writer(customWriter1); this.configurer.customCodec().writer(customWriter2); - List> writers = this.configurer.getWriters(); + List> writers = this.configurer.getWriters(); assertEquals(13, writers.size()); assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass()); @@ -173,8 +173,8 @@ public class ServerCodecConfigurerTests { when(customDecoder1.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(false); when(customDecoder2.canDecode(ResolvableType.forClass(Object.class), null)).thenReturn(true); - ServerHttpMessageReader customReader1 = mock(ServerHttpMessageReader.class); - ServerHttpMessageReader customReader2 = mock(ServerHttpMessageReader.class); + 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); @@ -187,7 +187,7 @@ public class ServerCodecConfigurerTests { this.configurer.registerDefaults(false); - List> readers = this.configurer.getReaders(); + List> readers = this.configurer.getReaders(); assertEquals(4, readers.size()); assertSame(customDecoder1, getNextDecoder(readers)); @@ -205,8 +205,8 @@ public class ServerCodecConfigurerTests { when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false); when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true); - ServerHttpMessageWriter customWriter1 = mock(ServerHttpMessageWriter.class); - ServerHttpMessageWriter customWriter2 = mock(ServerHttpMessageWriter.class); + 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); @@ -219,7 +219,7 @@ public class ServerCodecConfigurerTests { this.configurer.registerDefaults(false); - List> writers = this.configurer.getWriters(); + List> writers = this.configurer.getWriters(); assertEquals(4, writers.size()); assertSame(customEncoder1, getNextEncoder(writers)); @@ -264,13 +264,13 @@ public class ServerCodecConfigurerTests { } - private Decoder getNextDecoder(List> readers) { + 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) { + private Encoder getNextEncoder(List> writers) { HttpMessageWriter writer = writers.get(this.index.getAndIncrement()); assertEquals(EncoderHttpMessageWriter.class, writer.getClass()); return ((EncoderHttpMessageWriter) writer).getEncoder(); @@ -288,8 +288,8 @@ public class ServerCodecConfigurerTests { assertEquals(!textOnly, encoder.canEncode(forClass(String.class), MediaType.TEXT_EVENT_STREAM)); } - private void assertSseWriter(List> writers) { - ServerHttpMessageWriter writer = writers.get(this.index.getAndIncrement()); + private void assertSseWriter(List> writers) { + HttpMessageWriter writer = writers.get(this.index.getAndIncrement()); assertEquals(ServerSentEventHttpMessageWriter.class, writer.getClass()); Encoder encoder = ((ServerSentEventHttpMessageWriter) writer).getEncoder(); assertNotNull(encoder); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageReaderArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageReaderArgumentResolver.java index a833004b5b..b450bf727a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageReaderArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageReaderArgumentResolver.java @@ -32,7 +32,7 @@ import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.MediaType; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; @@ -48,7 +48,7 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException; /** * Abstract base class for argument resolvers that resolve method arguments - * by reading the request body with an {@link ServerHttpMessageReader}. + * by reading the request body with an {@link HttpMessageReader}. * *

Applies validation if the method argument is annotated with * {@code @javax.validation.Valid} or @@ -60,16 +60,16 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException; */ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMethodArgumentResolverSupport { - private final List> messageReaders; + private final List> messageReaders; private final List supportedMediaTypes; /** - * Constructor with {@link ServerHttpMessageReader}'s and a {@link Validator}. + * Constructor with {@link HttpMessageReader}'s and a {@link Validator}. * @param readers readers to convert from the request body */ - protected AbstractMessageReaderArgumentResolver(List> readers) { + protected AbstractMessageReaderArgumentResolver(List> readers) { this(readers, new ReactiveAdapterRegistry()); } @@ -78,7 +78,7 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho * @param messageReaders readers to convert from the request body * @param adapterRegistry for adapting to other reactive types from Flux and Mono */ - protected AbstractMessageReaderArgumentResolver(List> messageReaders, + protected AbstractMessageReaderArgumentResolver(List> messageReaders, ReactiveAdapterRegistry adapterRegistry) { super(adapterRegistry); @@ -94,7 +94,7 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho /** * Return the configured message converters. */ - public List> getMessageReaders() { + public List> getMessageReaders() { return this.messageReaders; } @@ -113,7 +113,7 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho mediaType = MediaType.APPLICATION_OCTET_STREAM; } - for (ServerHttpMessageReader reader : getMessageReaders()) { + for (HttpMessageReader reader : getMessageReaders()) { if (reader.canRead(elementType, mediaType)) { Map readHints = Collections.emptyMap(); if (adapter != null && adapter.isMultiValue()) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java index ba3a7ee588..dd332aeb6f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java @@ -27,7 +27,7 @@ import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.ResolvableType; import org.springframework.http.MediaType; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; @@ -38,24 +38,24 @@ import org.springframework.web.server.ServerWebExchange; /** * Abstract base class for result handlers that handle return values by writing - * to the response with {@link ServerHttpMessageWriter}. + * to the response with {@link HttpMessageWriter}. * * @author Rossen Stoyanchev * @since 5.0 */ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHandlerSupport { - private final List> messageWriters; + private final List> messageWriters; /** - * Constructor with {@link ServerHttpMessageWriter}s and a + * Constructor with {@link HttpMessageWriter}s and a * {@code RequestedContentTypeResolver}. * * @param messageWriters for serializing Objects to the response body stream * @param contentTypeResolver for resolving the requested content type */ - protected AbstractMessageWriterResultHandler(List> messageWriters, + protected AbstractMessageWriterResultHandler(List> messageWriters, RequestedContentTypeResolver contentTypeResolver) { super(contentTypeResolver); @@ -71,7 +71,7 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa * @param adapterRegistry for adapting other reactive types (e.g. rx.Observable, * rx.Single, etc.) to Flux or Mono */ - protected AbstractMessageWriterResultHandler(List> messageWriters, + protected AbstractMessageWriterResultHandler(List> messageWriters, RequestedContentTypeResolver contentTypeResolver, ReactiveAdapterRegistry adapterRegistry) { @@ -84,7 +84,7 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa /** * Return the configured message converters. */ - public List> getMessageWriters() { + public List> getMessageWriters() { return this.messageWriters; } @@ -115,7 +115,7 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa ServerHttpResponse response = exchange.getResponse(); MediaType bestMediaType = selectMediaType(exchange, () -> getProducibleMediaTypes(elementType)); if (bestMediaType != null) { - for (ServerHttpMessageWriter writer : getMessageWriters()) { + for (HttpMessageWriter writer : getMessageWriters()) { if (writer.canWrite(elementType, bestMediaType)) { return writer.write((Publisher) publisher, bodyType, elementType, bestMediaType, request, response, Collections.emptyMap()); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java index 7fd0576083..d4e36e8c29 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java @@ -24,7 +24,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.http.HttpEntity; import org.springframework.http.RequestEntity; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; @@ -40,7 +40,7 @@ import org.springframework.web.server.ServerWebExchange; */ public class HttpEntityArgumentResolver extends AbstractMessageReaderArgumentResolver { - public HttpEntityArgumentResolver(List> readers, + public HttpEntityArgumentResolver(List> readers, ReactiveAdapterRegistry registry) { super(readers, registry); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java index 56ce5977d6..90b4c77010 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java @@ -22,7 +22,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; @@ -45,7 +45,7 @@ import org.springframework.web.server.ServerWebInputException; */ public class RequestBodyArgumentResolver extends AbstractMessageReaderArgumentResolver { - public RequestBodyArgumentResolver(List> readers, + public RequestBodyArgumentResolver(List> readers, ReactiveAdapterRegistry registry) { super(readers, registry); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java index 9a062d5e46..bed81fff75 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java @@ -46,7 +46,7 @@ import org.springframework.core.codec.ResourceDecoder; import org.springframework.core.codec.StringDecoder; import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.InitBinder; @@ -78,7 +78,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application private static final Log logger = LogFactory.getLog(RequestMappingHandlerAdapter.class); - private final List> messageReaders = new ArrayList<>(10); + private final List> messageReaders = new ArrayList<>(10); private WebBindingInitializer webBindingInitializer; @@ -131,7 +131,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application * including JSON encoding . * @see ServerCodecConfigurer */ - public void setMessageReaders(List> messageReaders) { + public void setMessageReaders(List> messageReaders) { this.messageReaders.clear(); this.messageReaders.addAll(messageReaders); } @@ -139,7 +139,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application /** * Return the configured HTTP message readers. */ - public List> getMessageReaders() { + public List> getMessageReaders() { return this.messageReaders; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java index cc9a6d5c65..d0ccd3c65b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java @@ -23,7 +23,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.HandlerResultHandler; @@ -34,7 +34,7 @@ import org.springframework.web.server.ServerWebExchange; /** * {@code HandlerResultHandler} that handles return values from methods annotated * with {@code @ResponseBody} writing to the body of the request or response with - * an {@link ServerHttpMessageWriter}. + * an {@link HttpMessageWriter}. * *

By default the order for this result handler is set to 100. As it detects * the presence of {@code @ResponseBody} it should be ordered after result @@ -56,7 +56,7 @@ public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandle * @param writers writers for serializing to the response body * @param resolver to determine the requested content type */ - public ResponseBodyResultHandler(List> writers, + public ResponseBodyResultHandler(List> writers, RequestedContentTypeResolver resolver) { this(writers, resolver, new ReactiveAdapterRegistry()); @@ -68,7 +68,7 @@ public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandle * @param resolver to determine the requested content type * @param registry for adaptation to reactive types */ - public ResponseBodyResultHandler(List> writers, + public ResponseBodyResultHandler(List> writers, RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) { super(writers, resolver, registry); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java index 30bef89cc4..6470f5d1d6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java @@ -30,7 +30,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.util.Assert; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.HandlerResultHandler; @@ -57,7 +57,7 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand * @param writers writers for serializing to the response body * @param resolver to determine the requested content type */ - public ResponseEntityResultHandler(List> writers, + public ResponseEntityResultHandler(List> writers, RequestedContentTypeResolver resolver) { this(writers, resolver, new ReactiveAdapterRegistry()); @@ -69,7 +69,7 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand * @param resolver to determine the requested content type * @param registry for adaptation to reactive types */ - public ResponseEntityResultHandler(List> writers, + public ResponseEntityResultHandler(List> writers, RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) { super(writers, resolver, registry); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java index 8a373ab0f8..403ffd2c15 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java @@ -30,7 +30,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.convert.ConversionService; import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -61,7 +61,7 @@ public class DelegatingWebFluxConfigurationTests { private ArgumentCaptor codecsConfigurer; @Captor - private ArgumentCaptor>> writers; + private ArgumentCaptor>> writers; @Captor private ArgumentCaptor formatterRegistry; diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java index db3efd0ac1..715f569720 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java @@ -34,8 +34,8 @@ import org.springframework.core.codec.StringDecoder; import org.springframework.core.convert.ConversionService; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; -import org.springframework.http.codec.ServerHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlDecoder; @@ -126,7 +126,7 @@ public class WebFluxConfigurationSupportTests { RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class); assertNotNull(adapter); - List> readers = adapter.getMessageReaders(); + List> readers = adapter.getMessageReaders(); assertEquals(8, readers.size()); assertHasMessageReader(readers, byte[].class, APPLICATION_OCTET_STREAM); @@ -159,7 +159,7 @@ public class WebFluxConfigurationSupportTests { RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class); assertNotNull(adapter); - List> messageReaders = adapter.getMessageReaders(); + List> messageReaders = adapter.getMessageReaders(); assertEquals(2, messageReaders.size()); assertHasMessageReader(messageReaders, String.class, TEXT_PLAIN); @@ -176,7 +176,7 @@ public class WebFluxConfigurationSupportTests { assertEquals(0, handler.getOrder()); - List> writers = handler.getMessageWriters(); + List> writers = handler.getMessageWriters(); assertEquals(9, writers.size()); assertHasMessageWriter(writers, byte[].class, APPLICATION_OCTET_STREAM); @@ -202,7 +202,7 @@ public class WebFluxConfigurationSupportTests { assertEquals(100, handler.getOrder()); - List> writers = handler.getMessageWriters(); + List> writers = handler.getMessageWriters(); assertEquals(9, writers.size()); assertHasMessageWriter(writers, byte[].class, APPLICATION_OCTET_STREAM); @@ -258,12 +258,12 @@ public class WebFluxConfigurationSupportTests { } - private void assertHasMessageReader(List> readers, Class clazz, MediaType mediaType) { + private void assertHasMessageReader(List> readers, Class clazz, MediaType mediaType) { ResolvableType type = ResolvableType.forClass(clazz); assertTrue(readers.stream().anyMatch(c -> mediaType == null || c.canRead(type, mediaType))); } - private void assertHasMessageWriter(List> writers, Class clazz, MediaType mediaType) { + private void assertHasMessageWriter(List> writers, Class clazz, MediaType mediaType) { ResolvableType type = ResolvableType.forClass(clazz); assertTrue(writers.stream().anyMatch(c -> mediaType == null || c.canWrite(type, mediaType))); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java index 05bcc3d4c1..8b687439ae 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java @@ -39,7 +39,7 @@ import org.springframework.core.codec.StringDecoder; import org.springframework.http.HttpEntity; import org.springframework.http.RequestEntity; import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerWebExchange; import org.springframework.util.ObjectUtils; import org.springframework.web.method.ResolvableMethod; @@ -73,7 +73,7 @@ public class HttpEntityArgumentResolverTests { private HttpEntityArgumentResolver createResolver() { - List> readers = new ArrayList<>(); + List> readers = new ArrayList<>(); readers.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); return new HttpEntityArgumentResolver(readers, new ReactiveAdapterRegistry()); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java index 7cc280bcc4..46e451e9b4 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java @@ -43,7 +43,7 @@ import org.springframework.core.ResolvableType; import org.springframework.core.codec.Decoder; import org.springframework.http.MediaType; import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.validation.Errors; import org.springframework.validation.Validator; @@ -302,7 +302,7 @@ public class MessageReaderArgumentResolverTests { @SuppressWarnings("Convert2MethodRef") private AbstractMessageReaderArgumentResolver resolver(Decoder... decoders) { - List> readers = new ArrayList<>(); + List> readers = new ArrayList<>(); Arrays.asList(decoders).forEach(decoder -> readers.add(new DecoderHttpMessageReader<>(decoder))); return new AbstractMessageReaderArgumentResolver(readers) { @Override diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java index 5856be3f36..2b89311ae9 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java @@ -43,7 +43,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; @@ -71,8 +71,8 @@ public class MessageWriterResultHandlerTests { private final MockServerWebExchange exchange = MockServerHttpRequest.get("/path").toExchange(); - private AbstractMessageWriterResultHandler initResultHandler(ServerHttpMessageWriter... writers) { - List> writerList; + private AbstractMessageWriterResultHandler initResultHandler(HttpMessageWriter... writers) { + List> writerList; if (ObjectUtils.isEmpty(writers)) { writerList = new ArrayList<>(); writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); @@ -141,7 +141,7 @@ public class MessageWriterResultHandlerTests { ByteArrayOutputStream body = new ByteArrayOutputStream(); MethodParameter type = on(TestController.class).resolveReturnType(OutputStream.class); - ServerHttpMessageWriter writer = new EncoderHttpMessageWriter<>(new ByteBufferEncoder()); + HttpMessageWriter writer = new EncoderHttpMessageWriter<>(new ByteBufferEncoder()); Mono mono = initResultHandler(writer).writeBody(body, type, this.exchange); StepVerifier.create(mono).expectError(IllegalStateException.class).verify(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java index 880e64f8e5..f9e993bac4 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java @@ -35,7 +35,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.codec.StringDecoder; import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.ServerHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.method.ResolvableMethod; @@ -66,7 +66,7 @@ public class RequestBodyArgumentResolverTests { @Before public void setup() { - List> readers = new ArrayList<>(); + List> readers = new ArrayList<>(); readers.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); this.resolver = new RequestBodyArgumentResolver(readers, new ReactiveAdapterRegistry()); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandlerTests.java index 8af0ce73aa..c8bb97cba8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandlerTests.java @@ -30,7 +30,7 @@ import org.springframework.core.codec.ByteBufferEncoder; import org.springframework.core.codec.CharSequenceEncoder; import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.stereotype.Controller; @@ -64,7 +64,7 @@ public class ResponseBodyResultHandlerTests { @Before public void setup() throws Exception { - List> writerList = new ArrayList<>(5); + List> writerList = new ArrayList<>(5); writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); writerList.add(new ResourceHttpMessageWriter()); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java index dcb4cecb20..b133379379 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java @@ -44,7 +44,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.ServerHttpMessageWriter; +import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.mock.http.server.reactive.test.MockServerWebExchange; @@ -83,8 +83,8 @@ public class ResponseEntityResultHandlerTests { this.resultHandler = createHandler(); } - private ResponseEntityResultHandler createHandler(ServerHttpMessageWriter... writers) { - List> writerList; + private ResponseEntityResultHandler createHandler(HttpMessageWriter... writers) { + List> writerList; if (ObjectUtils.isEmpty(writers)) { writerList = new ArrayList<>(); writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); From ec5b5c8578f7ae0754068f400f9a3db6adfffcee Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 24 Mar 2017 17:42:37 -0400 Subject: [PATCH 3/3] Rename Http[Encoder|Decoder] to HttpMessage[Encoder|Decoder] --- .../http/codec/DecoderHttpMessageReader.java | 6 +++--- .../http/codec/EncoderHttpMessageWriter.java | 10 +++++----- .../{HttpDecoder.java => HttpMessageDecoder.java} | 4 ++-- .../{HttpEncoder.java => HttpMessageEncoder.java} | 4 ++-- .../http/codec/ServerSentEventHttpMessageWriter.java | 4 ++-- .../http/codec/json/Jackson2JsonDecoder.java | 6 +++--- .../http/codec/json/Jackson2JsonEncoder.java | 8 ++++---- 7 files changed, 21 insertions(+), 21 deletions(-) rename spring-web/src/main/java/org/springframework/http/codec/{HttpDecoder.java => HttpMessageDecoder.java} (94%) rename spring-web/src/main/java/org/springframework/http/codec/{HttpEncoder.java => HttpMessageEncoder.java} (95%) diff --git a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java index b57b9ad66a..159eb503af 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/DecoderHttpMessageReader.java @@ -129,13 +129,13 @@ public class DecoderHttpMessageReader implements HttpMessageReader { /** * Get additional hints for decoding for example based on the server request * or annotations from controller method parameters. By default, delegate to - * the decoder if it is an instance of {@link HttpDecoder}. + * the decoder if it is an instance of {@link HttpMessageDecoder}. */ protected Map getReadHints(ResolvableType streamType, ResolvableType elementType, ServerHttpRequest request, ServerHttpResponse response) { - if (this.decoder instanceof HttpDecoder) { - HttpDecoder httpDecoder = (HttpDecoder) this.decoder; + if (this.decoder instanceof HttpMessageDecoder) { + HttpMessageDecoder httpDecoder = (HttpMessageDecoder) this.decoder; return httpDecoder.getDecodeHints(streamType, elementType, request, response); } return Collections.emptyMap(); diff --git a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java index e3209b0c9c..52258f4b1c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java @@ -130,8 +130,8 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter { } private boolean isStreamingMediaType(MediaType contentType) { - return this.encoder instanceof HttpEncoder && - ((HttpEncoder) this.encoder).getStreamingMediaTypes().stream() + return this.encoder instanceof HttpMessageEncoder && + ((HttpMessageEncoder) this.encoder).getStreamingMediaTypes().stream() .anyMatch(contentType::isCompatibleWith); } @@ -153,13 +153,13 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter { /** * Get additional hints for encoding for example based on the server request * or annotations from controller method parameters. By default, delegate to - * the encoder if it is an instance of {@link HttpEncoder}. + * the encoder if it is an instance of {@link HttpMessageEncoder}. */ protected Map getWriteHints(ResolvableType streamType, ResolvableType elementType, MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) { - if (this.encoder instanceof HttpEncoder) { - HttpEncoder httpEncoder = (HttpEncoder) this.encoder; + if (this.encoder instanceof HttpMessageEncoder) { + HttpMessageEncoder httpEncoder = (HttpMessageEncoder) this.encoder; return httpEncoder.getEncodeHints(streamType, elementType, mediaType, request, response); } return Collections.emptyMap(); diff --git a/spring-web/src/main/java/org/springframework/http/codec/HttpDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageDecoder.java similarity index 94% rename from spring-web/src/main/java/org/springframework/http/codec/HttpDecoder.java rename to spring-web/src/main/java/org/springframework/http/codec/HttpMessageDecoder.java index 146bd9ce94..43542af563 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/HttpDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageDecoder.java @@ -25,12 +25,12 @@ import org.springframework.http.server.reactive.ServerHttpResponse; /** * Extension of {@code Decoder} exposing extra methods relevant in the context - * of HTTP applications. + * of HTTP request or response body decoding. * * @author Rossen Stoyanchev * @since 5.0 */ -public interface HttpDecoder extends Decoder { +public interface HttpMessageDecoder extends Decoder { /** * Get decoding hints based on the server request or annotations on the diff --git a/spring-web/src/main/java/org/springframework/http/codec/HttpEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageEncoder.java similarity index 95% rename from spring-web/src/main/java/org/springframework/http/codec/HttpEncoder.java rename to spring-web/src/main/java/org/springframework/http/codec/HttpMessageEncoder.java index 98b3f94357..bb292acda4 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/HttpEncoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/HttpMessageEncoder.java @@ -29,12 +29,12 @@ import org.springframework.http.server.reactive.ServerHttpResponse; /** * Extension of {@code Encoder} exposing extra methods relevant in the context - * of HTTP applications. + * of HTTP request or response body encoding. * * @author Rossen Stoyanchev * @since 5.0 */ -public interface HttpEncoder extends Encoder { +public interface HttpMessageEncoder extends Encoder { /** * Return "streaming" media types for which flushing should be performed diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java index c280cb70f0..1fad05f0a3 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java @@ -172,8 +172,8 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter getEncodeHints(ResolvableType actualType, ResolvableType elementType, MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) { - if (this.encoder instanceof HttpEncoder) { - HttpEncoder httpEncoder = (HttpEncoder) this.encoder; + if (this.encoder instanceof HttpMessageEncoder) { + HttpMessageEncoder httpEncoder = (HttpMessageEncoder) this.encoder; return httpEncoder.getEncodeHints(actualType, elementType, mediaType, request, response); } return Collections.emptyMap(); diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java index d3d2b94051..9beda0e8a7 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java @@ -33,7 +33,7 @@ import org.springframework.core.ResolvableType; import org.springframework.core.codec.CodecException; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.http.codec.HttpDecoder; +import org.springframework.http.codec.HttpMessageDecoder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; @@ -48,7 +48,7 @@ import org.springframework.util.MimeType; * @since 5.0 * @see Jackson2JsonEncoder */ -public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpDecoder { +public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMessageDecoder { private final JsonObjectDecoder fluxDecoder = new JsonObjectDecoder(true); @@ -120,7 +120,7 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpDec } - // HttpDecoder... + // HttpMessageDecoder... @Override public Map getDecodeHints(ResolvableType actualType, ResolvableType elementType, diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java index 26a712afc0..0675ca09e2 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java @@ -42,7 +42,7 @@ import org.springframework.core.codec.CodecException; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.http.MediaType; -import org.springframework.http.codec.HttpEncoder; +import org.springframework.http.codec.HttpMessageEncoder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; @@ -59,7 +59,7 @@ import org.springframework.util.MimeType; * @since 5.0 * @see Jackson2JsonDecoder */ -public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpEncoder { +public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMessageEncoder { private final List streamingMediaTypes = new ArrayList<>(1); @@ -89,7 +89,7 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpEnc * automatically vs at the end of the stream. *

By default this is set to {@link MediaType#APPLICATION_STREAM_JSON}. * @param mediaTypes one or more media types to add to the list - * @see HttpEncoder#getStreamingMediaTypes() + * @see HttpMessageEncoder#getStreamingMediaTypes() */ public void setStreamingMediaTypes(List mediaTypes) { this.streamingMediaTypes.clear(); @@ -169,7 +169,7 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpEnc } - // HttpEncoder... + // HttpMessageEncoder... @Override public List getStreamingMediaTypes() {