diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java index c42d92a5639..c21cd301899 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java @@ -33,9 +33,9 @@ public interface BodyExtractor { /** * Extract from the given request. * @param request the request to extract from - * @param configuration the configuration to use + * @param strategies the strategies to use * @return the extracted data */ - T extract(ServerHttpRequest request, Configuration configuration); + T extract(ServerHttpRequest request, StrategiesSupplier strategies); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java index 1c2ebfec163..11e5e0a10e2 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java @@ -61,7 +61,7 @@ public abstract class BodyExtractors { */ public static BodyExtractor> toMono(ResolvableType elementType) { Assert.notNull(elementType, "'elementType' must not be null"); - return (request, configuration) -> readWithMessageReaders(request, configuration, + return (request, strategies) -> readWithMessageReaders(request, strategies, elementType, reader -> reader.readMono(elementType, request, Collections.emptyMap()), Mono::error); @@ -86,7 +86,7 @@ public abstract class BodyExtractors { */ public static BodyExtractor> toFlux(ResolvableType elementType) { Assert.notNull(elementType, "'elementType' must not be null"); - return (request, configuration) -> readWithMessageReaders(request, configuration, + return (request, strategies) -> readWithMessageReaders(request, strategies, elementType, reader -> reader.read(elementType, request, Collections.emptyMap()), Flux::error); @@ -94,14 +94,13 @@ public abstract class BodyExtractors { private static > S readWithMessageReaders( ServerHttpRequest request, - Configuration configuration, + StrategiesSupplier strategies, ResolvableType elementType, Function, S> readerFunction, Function unsupportedError) { MediaType contentType = contentType(request); - Supplier>> messageReaders = - configuration.messageReaders(); + Supplier>> messageReaders = strategies.messageReaders(); return messageReaders.get() .filter(r -> r.canRead(elementType, contentType, Collections.emptyMap())) .findFirst() diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java index b85eee0ba22..116166f8e4d 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java @@ -39,10 +39,10 @@ public interface BodyInserter { /** * Insert into the given response. * @param response the response to insert into - * @param configuration the configuration to use + * @param strategies the strategies to use * @return a {@code Mono} that indicates completion or error */ - Mono insert(ServerHttpResponse response, Configuration configuration); + Mono insert(ServerHttpResponse response, StrategiesSupplier strategies); /** * Return the type contained in the body. @@ -58,7 +58,7 @@ public interface BodyInserter { * @param the type supplied and written by the inserter * @return the new {@code BodyInserter} */ - static BodyInserter of(BiFunction> writer, + static BodyInserter of(BiFunction> writer, Supplier supplier) { Assert.notNull(writer, "'writer' must not be null"); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java index 9cd9eb709ee..bdc3d3c9d33 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java @@ -64,7 +64,7 @@ public abstract class BodyInserters { public static BodyInserter fromObject(T body) { Assert.notNull(body, "'body' must not be null"); return BodyInserter.of( - (response, configuration) -> writeWithMessageWriters(response, configuration, + (response, strategies) -> writeWithMessageWriters(response, strategies, Mono.just(body), ResolvableType.forInstance(body)), () -> body); } @@ -99,7 +99,7 @@ public abstract class BodyInserters { Assert.notNull(publisher, "'publisher' must not be null"); Assert.notNull(elementType, "'elementType' must not be null"); return BodyInserter.of( - (response, configuration) -> writeWithMessageWriters(response, configuration, + (response, strategies) -> writeWithMessageWriters(response, strategies, publisher, elementType), () -> publisher ); @@ -117,7 +117,7 @@ public abstract class BodyInserters { public static BodyInserter fromResource(T resource) { Assert.notNull(resource, "'resource' must not be null"); return BodyInserter.of( - (response, configuration) -> { + (response, strategies) -> { ResourceHttpMessageWriter messageWriter = new ResourceHttpMessageWriter(); MediaType contentType = response.getHeaders().getContentType(); return messageWriter.write(Mono.just(resource), RESOURCE_TYPE, contentType, @@ -139,7 +139,7 @@ public abstract class BodyInserters { Assert.notNull(eventsPublisher, "'eventsPublisher' must not be null"); return BodyInserter.of( - (response, configuration) -> { + (response, strategies) -> { ServerSentEventHttpMessageWriter messageWriter = sseMessageWriter(); MediaType contentType = response.getHeaders().getContentType(); return messageWriter.write(eventsPublisher, SERVER_SIDE_EVENT_TYPE, @@ -183,7 +183,7 @@ public abstract class BodyInserters { Assert.notNull(eventsPublisher, "'eventsPublisher' must not be null"); Assert.notNull(eventType, "'eventType' must not be null"); return BodyInserter.of( - (response, configuration) -> { + (response, strategies) -> { ServerSentEventHttpMessageWriter messageWriter = sseMessageWriter(); MediaType contentType = response.getHeaders().getContentType(); return messageWriter.write(eventsPublisher, eventType, contentType, response, @@ -201,13 +201,13 @@ public abstract class BodyInserters { } private static Mono writeWithMessageWriters(ServerHttpResponse response, - Configuration configuration, + StrategiesSupplier strategies, Publisher body, ResolvableType bodyType) { // TODO: use ContentNegotiatingResultHandlerSupport MediaType contentType = response.getHeaders().getContentType(); - return configuration.messageWriters().get() + return strategies.messageWriters().get() .filter(messageWriter -> messageWriter.canWrite(bodyType, contentType, Collections .emptyMap())) .findFirst() @@ -228,20 +228,20 @@ public abstract class BodyInserters { static class DefaultBodyInserter implements BodyInserter { - private final BiFunction> writer; + private final BiFunction> writer; private final Supplier supplier; public DefaultBodyInserter( - BiFunction> writer, + BiFunction> writer, Supplier supplier) { this.writer = writer; this.supplier = supplier; } @Override - public Mono insert(ServerHttpResponse response, Configuration configuration) { - return this.writer.apply(response, configuration); + public Mono insert(ServerHttpResponse response, StrategiesSupplier strategies) { + return this.writer.apply(response, strategies); } @Override diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java index 92b8b66f475..3b1b0161094 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java @@ -42,11 +42,11 @@ class DefaultRequest implements Request { private final Headers headers; - private final Configuration configuration; + private final StrategiesSupplier strategies; - DefaultRequest(ServerWebExchange exchange, Configuration configuration) { + DefaultRequest(ServerWebExchange exchange, StrategiesSupplier strategies) { this.exchange = exchange; - this.configuration = configuration; + this.strategies = strategies; this.headers = new DefaultHeaders(); } @@ -67,7 +67,7 @@ class DefaultRequest implements Request { @Override public T body(BodyExtractor extractor) { - return extractor.extract(request(), this.configuration); + return extractor.extract(request(), this.strategies); } @Override diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java index 902ffebde89..5d4d8f1b37c 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java @@ -142,7 +142,7 @@ class DefaultResponseBuilder implements Response.BodyBuilder { @Override public Response build() { return body(BodyInserter.of( - (response, configuration) -> response.setComplete(), + (response, strategies) -> response.setComplete(), () -> null)); } @@ -150,12 +150,12 @@ class DefaultResponseBuilder implements Response.BodyBuilder { public > Response build(T voidPublisher) { Assert.notNull(voidPublisher, "'voidPublisher' must not be null"); return body(BodyInserter.of( - (response, configuration) -> Flux.from(voidPublisher).then(response.setComplete()), + (response, strategies) -> Flux.from(voidPublisher).then(response.setComplete()), () -> null)); } @Override - public Response body(BiFunction> writer, + public Response body(BiFunction> writer, Supplier supplier) { return body(BodyInserter.of(writer, supplier)); } @@ -250,10 +250,10 @@ class DefaultResponseBuilder implements Response.BodyBuilder { } @Override - public Mono writeTo(ServerWebExchange exchange, Configuration configuration) { + public Mono writeTo(ServerWebExchange exchange, StrategiesSupplier strategies) { ServerHttpResponse response = exchange.getResponse(); writeStatusAndHeaders(response); - return this.inserter.insert(response, configuration); + return this.inserter.insert(response, strategies); } } @@ -281,12 +281,12 @@ class DefaultResponseBuilder implements Response.BodyBuilder { } @Override - public Mono writeTo(ServerWebExchange exchange, Configuration configuration) { + public Mono writeTo(ServerWebExchange exchange, StrategiesSupplier strategies) { ServerHttpResponse response = exchange.getResponse(); writeStatusAndHeaders(response); MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Locale locale = Locale.ENGLISH; // TODO: resolve locale - Stream viewResolverStream = configuration.viewResolvers().get(); + Stream viewResolverStream = strategies.viewResolvers().get(); return Flux.fromStream(viewResolverStream) .concatMap(viewResolver -> viewResolver.resolveViewName(this.name, locale)) .next() diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfigurationBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultStrategiesSupplierBuilder.java similarity index 85% rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfigurationBuilder.java rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultStrategiesSupplierBuilder.java index 7491429ee1c..4d1d4b1d3a5 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfigurationBuilder.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultStrategiesSupplierBuilder.java @@ -17,7 +17,6 @@ package org.springframework.web.reactive.function; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.function.Supplier; @@ -41,20 +40,22 @@ import org.springframework.util.ClassUtils; import org.springframework.web.reactive.result.view.ViewResolver; /** + * Default implementation of {@link StrategiesSupplier.Builder}. + * * @author Arjen Poutsma * @since 5.0 */ -class DefaultConfigurationBuilder implements Configuration.Builder { +class DefaultStrategiesSupplierBuilder implements StrategiesSupplier.Builder { private static final boolean jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", - DefaultConfigurationBuilder.class.getClassLoader()) && + DefaultStrategiesSupplierBuilder.class.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", - DefaultConfigurationBuilder.class.getClassLoader()); + DefaultStrategiesSupplierBuilder.class.getClassLoader()); private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", - DefaultConfigurationBuilder.class.getClassLoader()); + DefaultStrategiesSupplierBuilder.class.getClassLoader()); private final List> messageReaders = new ArrayList<>(); @@ -85,33 +86,33 @@ class DefaultConfigurationBuilder implements Configuration.Builder { } @Override - public Configuration.Builder messageReader(HttpMessageReader messageReader) { + public StrategiesSupplier.Builder messageReader(HttpMessageReader messageReader) { Assert.notNull(messageReader, "'messageReader' must not be null"); this.messageReaders.add(messageReader); return this; } @Override - public Configuration.Builder messageWriter(HttpMessageWriter messageWriter) { + public StrategiesSupplier.Builder messageWriter(HttpMessageWriter messageWriter) { Assert.notNull(messageWriter, "'messageWriter' must not be null"); this.messageWriters.add(messageWriter); return this; } @Override - public Configuration.Builder viewResolver(ViewResolver viewResolver) { + public StrategiesSupplier.Builder viewResolver(ViewResolver viewResolver) { Assert.notNull(viewResolver, "'viewResolver' must not be null"); this.viewResolvers.add(viewResolver); return this; } @Override - public Configuration build() { - return new DefaultConfiguration(this.messageReaders, this.messageWriters, + public StrategiesSupplier build() { + return new DefaultStrategiesSupplier(this.messageReaders, this.messageWriters, this.viewResolvers); } - private static class DefaultConfiguration implements Configuration { + private static class DefaultStrategiesSupplier implements StrategiesSupplier { private final List> messageReaders; @@ -119,7 +120,7 @@ class DefaultConfigurationBuilder implements Configuration.Builder { private final List viewResolvers; - public DefaultConfiguration( + public DefaultStrategiesSupplier( List> messageReaders, List> messageWriters, List viewResolvers) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java index 2c1fd093955..25b5e0206ac 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java @@ -67,9 +67,10 @@ public interface Response { * Writes this response to the given web exchange. * * @param exchange the web exchange to write to + * @param strategies the strategies to use when writing * @return {@code Mono} to indicate when request handling is complete */ - Mono writeTo(ServerWebExchange exchange, Configuration configuration); + Mono writeTo(ServerWebExchange exchange, StrategiesSupplier strategies); // Static builder methods @@ -315,7 +316,7 @@ public interface Response { * @param the type contained in the body * @return the built response */ - Response body(BiFunction> writer, + Response body(BiFunction> writer, Supplier supplier); /** diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java index 0d62d54655e..68c4705be82 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java @@ -38,7 +38,7 @@ import org.springframework.web.server.adapter.HttpWebHandlerAdapter; *

Additionally, this class can {@linkplain #toHttpHandler(RouterFunction) transform} a * {@code RouterFunction} into an {@code HttpHandler}, which can be run in Servlet 3.1+, * Reactor, RxNetty, or Undertow. - * And it can {@linkplain #toHandlerMapping(RouterFunction, Configuration) transform} a + * And it can {@linkplain #toHandlerMapping(RouterFunction, StrategiesSupplier) transform} a * {@code RouterFunction} into an {@code HandlerMapping}, which can be run in a * {@code DispatcherHandler}. * @@ -103,7 +103,7 @@ public abstract class RouterFunctions { /** * Converts the given {@linkplain RouterFunction routing function} into a {@link HttpHandler}. - * This conversion uses the {@linkplain Configuration#builder() default configuration}. + * This conversion uses {@linkplain StrategiesSupplier#builder() default strategies}. * *

The returned {@code HttpHandler} can be adapted to run in *

    @@ -121,12 +121,12 @@ public abstract class RouterFunctions { * @return an http handler that handles HTTP request using the given routing function */ public static HttpHandler toHttpHandler(RouterFunction routerFunction) { - return toHttpHandler(routerFunction, defaultConfiguration()); + return toHttpHandler(routerFunction, defaultStrategies()); } /** * Converts the given {@linkplain RouterFunction routing function} into a {@link HttpHandler}, - * using the given configuration. + * using the given strategies. * *

    The returned {@code HttpHandler} can be adapted to run in *

      @@ -141,26 +141,26 @@ public abstract class RouterFunctions { *
    * * @param routerFunction the routing function to convert - * @param configuration the configuration to use + * @param strategies the strategies to use * @return an http handler that handles HTTP request using the given routing function */ - public static HttpHandler toHttpHandler(RouterFunction routerFunction, Configuration configuration) { + public static HttpHandler toHttpHandler(RouterFunction routerFunction, StrategiesSupplier strategies) { Assert.notNull(routerFunction, "'routerFunction' must not be null"); - Assert.notNull(configuration, "'configuration' must not be null"); + Assert.notNull(strategies, "'strategies' must not be null"); return new HttpWebHandlerAdapter(exchange -> { - Request request = new DefaultRequest(exchange, configuration); + Request request = new DefaultRequest(exchange, strategies); addAttributes(exchange, request); HandlerFunction handlerFunction = routerFunction.route(request).orElse(notFound()); Response response = handlerFunction.handle(request); - return response.writeTo(exchange, configuration); + return response.writeTo(exchange, strategies); }); } /** * Converts the given {@code RouterFunction} into a {@code HandlerMapping}. - * This conversion uses the {@linkplain Configuration#builder() default configuration}. + * This conversion uses {@linkplain StrategiesSupplier#builder() default strategies}. * *

    The returned {@code HandlerMapping} can be run in a * {@link org.springframework.web.reactive.DispatcherHandler}. @@ -171,27 +171,28 @@ public abstract class RouterFunctions { * @see org.springframework.web.reactive.function.support.ResponseResultHandler */ public static HandlerMapping toHandlerMapping(RouterFunction routerFunction) { - return toHandlerMapping(routerFunction, defaultConfiguration()); + return toHandlerMapping(routerFunction, defaultStrategies()); } /** - * Converts the given {@linkplain RouterFunction routing function} into a {@link HandlerMapping} - * using the given configuration. + * Converts the given {@linkplain RouterFunction routing function} into a {@link HandlerMapping}, + * using the given strategies. * *

    The returned {@code HandlerMapping} can be run in a * {@link org.springframework.web.reactive.DispatcherHandler}. * * @param routerFunction the routing function to convert + * @param strategies the strategies to use * @return an handler mapping that maps HTTP request to a handler using the given routing function * @see org.springframework.web.reactive.function.support.HandlerFunctionAdapter * @see org.springframework.web.reactive.function.support.ResponseResultHandler */ - public static HandlerMapping toHandlerMapping(RouterFunction routerFunction, Configuration configuration) { + public static HandlerMapping toHandlerMapping(RouterFunction routerFunction, StrategiesSupplier strategies) { Assert.notNull(routerFunction, "'routerFunction' must not be null"); - Assert.notNull(configuration, "'configuration' must not be null"); + Assert.notNull(strategies, "'strategies' must not be null"); return exchange -> { - Request request = new DefaultRequest(exchange, configuration); + Request request = new DefaultRequest(exchange, strategies); addAttributes(exchange, request); Optional> route = routerFunction.route(request); @@ -199,8 +200,8 @@ public abstract class RouterFunctions { }; } - private static Configuration defaultConfiguration() { - return Configuration.builder().build(); + private static StrategiesSupplier defaultStrategies() { + return StrategiesSupplier.builder().build(); } private static void addAttributes(ServerWebExchange exchange, Request request) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Configuration.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/StrategiesSupplier.java similarity index 57% rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Configuration.java rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/StrategiesSupplier.java index 07f1798ddab..4ac12d3649b 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Configuration.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/StrategiesSupplier.java @@ -26,15 +26,18 @@ import org.springframework.util.Assert; import org.springframework.web.reactive.result.view.ViewResolver; /** - * Defines the configuration to be used for processing {@link HandlerFunction}s. An instance of + * Defines the strategies to be used for processing {@link HandlerFunction}s. An instance of * this class is immutable; instances are typically created through the mutable {@link Builder}: - * either through {@link #builder()} to create a default configuration, {@link #empty()} to create - * an empty configuration. + * either through {@link #builder()} to set up default strategies, or {@link #empty()} to start from + * scratch. Alternatively, {@code StrategiesSupplier} instances can be created through + * {@link #of(Supplier, Supplier, Supplier)}. * * @author Arjen Poutsma * @since 5.0 + * @see RouterFunctions#toHttpHandler(RouterFunction, StrategiesSupplier) + * @see RouterFunctions#toHandlerMapping(RouterFunction, StrategiesSupplier) */ -public interface Configuration { +public interface StrategiesSupplier { // Instance methods @@ -62,19 +65,55 @@ public interface Configuration { // Static methods /** - * Return a mutable, empty builder for a {@code Configuration}. + * Return a new {@code StrategiesSupplier} described by the given supplier functions. All + * provided supplier function parameters can be {@code null} to indicate an empty stream is to + * be returned. + * @param messageReaders the supplier function for {@link HttpMessageReader} instances (can be {@code null}) + * @param messageWriters the supplier function for {@link HttpMessageWriter} instances (can be {@code null}) + * @param viewResolvers the supplier function for {@link ViewResolver} instances (can be {@code null}) + * @return the new {@code StrategiesSupplier} + */ + static StrategiesSupplier of(Supplier>> messageReaders, + Supplier>> messageWriters, + Supplier> viewResolvers) { + + return new StrategiesSupplier() { + @Override + public Supplier>> messageReaders() { + return checkForNull(messageReaders); + } + + @Override + public Supplier>> messageWriters() { + return checkForNull(messageWriters); + } + + @Override + public Supplier> viewResolvers() { + return checkForNull(viewResolvers); + } + + private Supplier> checkForNull(Supplier> supplier) { + return supplier != null ? supplier : Stream::empty; + } + }; + } + + + /** + * Return a mutable, empty builder for a {@code StrategiesSupplier}. * @return the builder */ static Builder empty() { - return new DefaultConfigurationBuilder(); + return new DefaultStrategiesSupplierBuilder(); } /** - * Return a mutable builder for a {@code Configuration} with a default initialization. + * Return a mutable builder for a {@code StrategiesSupplier} with a default initialization. * @return the builder */ static Builder builder() { - DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); + DefaultStrategiesSupplierBuilder builder = new DefaultStrategiesSupplierBuilder(); builder.defaultConfiguration(); return builder; } @@ -83,21 +122,21 @@ public interface Configuration { * Return a mutable builder based on the given {@linkplain ApplicationContext application context}. * The returned builder will search for all {@link HttpMessageReader}, {@link HttpMessageWriter}, * and {@link ViewResolver} instances in the given application context and return them for - * {@link #messageReaders()}, {@link #messageWriters()}, and {@link #viewResolvers()} in the - * built configuration respectively. - * @param applicationContext the application context to base the configuration on + * {@link #messageReaders()}, {@link #messageWriters()}, and {@link #viewResolvers()} + * respectively. + * @param applicationContext the application context to base the strategies on * @return the builder */ static Builder applicationContext(ApplicationContext applicationContext) { Assert.notNull(applicationContext, "'applicationContext' must not be null"); - DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); + DefaultStrategiesSupplierBuilder builder = new DefaultStrategiesSupplierBuilder(); builder.applicationContext(applicationContext); return builder; } /** - * A mutable builder for a {@link Configuration}. + * A mutable builder for a {@link StrategiesSupplier}. */ interface Builder { @@ -123,10 +162,10 @@ public interface Configuration { Builder viewResolver(ViewResolver viewResolver); /** - * Builds the {@link Configuration}. - * @return the built configuration + * Builds the {@link StrategiesSupplier}. + * @return the built strategies */ - Configuration build(); + StrategiesSupplier build(); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java index d965023746a..077586c07e4 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java @@ -21,8 +21,8 @@ import reactor.core.publisher.Mono; import org.springframework.util.Assert; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.HandlerResultHandler; -import org.springframework.web.reactive.function.Configuration; import org.springframework.web.reactive.function.Response; +import org.springframework.web.reactive.function.StrategiesSupplier; import org.springframework.web.server.ServerWebExchange; /** @@ -33,21 +33,21 @@ import org.springframework.web.server.ServerWebExchange; */ public class ResponseResultHandler implements HandlerResultHandler { - private final Configuration configuration; + private final StrategiesSupplier strategies; /** - * Create a {@code ResponseResultHandler} with a default configuration. + * Create a {@code ResponseResultHandler} with default strategies. */ public ResponseResultHandler() { - this(Configuration.builder().build()); + this(StrategiesSupplier.builder().build()); } /** - * Create a {@code ResponseResultHandler} with the given configuration. + * Create a {@code ResponseResultHandler} with the given strategies. */ - public ResponseResultHandler(Configuration configuration) { - Assert.notNull(configuration, "'configuration' must not be null"); - this.configuration = configuration; + public ResponseResultHandler(StrategiesSupplier strategies) { + Assert.notNull(strategies, "'strategies' must not be null"); + this.strategies = strategies; } @Override @@ -61,6 +61,6 @@ public class ResponseResultHandler implements HandlerResultHandler { public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { Response response = (Response) result.getReturnValue().orElseThrow( IllegalStateException::new); - return response.writeTo(exchange, this.configuration); + return response.writeTo(exchange, this.strategies); } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java index 10ef93ef6fa..ba5f450bea6 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java @@ -48,9 +48,9 @@ public class BodyExtractorsTests { MockServerHttpRequest request = new MockServerHttpRequest(); request.setBody(body); - Configuration configuration = Configuration.builder().build(); + StrategiesSupplier strategies = StrategiesSupplier.builder().build(); - Mono result = extractor.extract(request, configuration); + Mono result = extractor.extract(request, strategies); TestSubscriber.subscribe(result) .assertComplete() @@ -69,9 +69,9 @@ public class BodyExtractorsTests { MockServerHttpRequest request = new MockServerHttpRequest(); request.setBody(body); - Configuration configuration = Configuration.builder().build(); + StrategiesSupplier strategies = StrategiesSupplier.builder().build(); - Flux result = extractor.extract(request, configuration); + Flux result = extractor.extract(request, strategies); TestSubscriber.subscribe(result) .assertComplete() .assertValues("foo"); @@ -90,9 +90,9 @@ public class BodyExtractorsTests { request.getHeaders().setContentType(MediaType.APPLICATION_JSON); request.setBody(body); - Configuration configuration = Configuration.empty().build(); + StrategiesSupplier strategies = StrategiesSupplier.empty().build(); - Flux result = extractor.extract(request, configuration); + Flux result = extractor.extract(request, strategies); TestSubscriber.subscribe(result) .assertError(UnsupportedMediaTypeStatusException.class); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java index 2ceec277621..277a32f5db1 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java @@ -48,7 +48,7 @@ public class BodyInsertersTests { assertEquals(body, inserter.t()); MockServerHttpResponse response = new MockServerHttpResponse(); - Mono result = inserter.insert(response, Configuration.builder().build()); + Mono result = inserter.insert(response, StrategiesSupplier.builder().build()); TestSubscriber.subscribe(result) .assertComplete(); @@ -67,7 +67,7 @@ public class BodyInsertersTests { assertEquals(body, inserter.t()); MockServerHttpResponse response = new MockServerHttpResponse(); - Mono result = inserter.insert(response, Configuration.builder().build()); + Mono result = inserter.insert(response, StrategiesSupplier.builder().build()); TestSubscriber.subscribe(result) .assertComplete(); @@ -86,7 +86,7 @@ public class BodyInsertersTests { assertEquals(body, inserter.t()); MockServerHttpResponse response = new MockServerHttpResponse(); - Mono result = inserter.insert(response, Configuration.builder().build()); + Mono result = inserter.insert(response, StrategiesSupplier.builder().build()); TestSubscriber.subscribe(result) .assertComplete(); @@ -111,7 +111,7 @@ public class BodyInsertersTests { assertEquals(body, inserter.t()); MockServerHttpResponse response = new MockServerHttpResponse(); - Mono result = inserter.insert(response, Configuration.builder().build()); + Mono result = inserter.insert(response, StrategiesSupplier.builder().build()); TestSubscriber.subscribe(result) .assertComplete(); @@ -126,7 +126,7 @@ public class BodyInsertersTests { assertEquals(body, inserter.t()); MockServerHttpResponse response = new MockServerHttpResponse(); - Mono result = inserter.insert(response, Configuration.builder().build()); + Mono result = inserter.insert(response, StrategiesSupplier.builder().build()); TestSubscriber.subscribe(result) .assertComplete(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java index 033b83c9d1b..d48aefc0675 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java @@ -65,7 +65,7 @@ public class DefaultRequestTests { private ServerWebExchange mockExchange; - private Configuration mockConfiguration; + private StrategiesSupplier mockStrategiesSupplier; private DefaultRequest defaultRequest; @@ -77,9 +77,9 @@ public class DefaultRequestTests { mockExchange = mock(ServerWebExchange.class); when(mockExchange.getRequest()).thenReturn(mockRequest); when(mockExchange.getResponse()).thenReturn(mockResponse); - mockConfiguration = mock(Configuration.class); + mockStrategiesSupplier = mock(StrategiesSupplier.class); - defaultRequest = new DefaultRequest(mockExchange, mockConfiguration); + defaultRequest = new DefaultRequest(mockExchange, mockStrategiesSupplier); } @Test @@ -171,7 +171,7 @@ public class DefaultRequestTests { Set> messageReaders = Collections .singleton(new DecoderHttpMessageReader(new StringDecoder())); - when(mockConfiguration.messageReaders()).thenReturn(messageReaders::stream); + when(mockStrategiesSupplier.messageReaders()).thenReturn(messageReaders::stream); Mono resultMono = defaultRequest.body(toMono(String.class)); assertEquals("foo", resultMono.block()); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java index 0b216403f23..711f8698fbd 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java @@ -190,9 +190,9 @@ public class DefaultResponseBuilderTests { ServerWebExchange exchange = mock(ServerWebExchange.class); MockServerHttpResponse response = new MockServerHttpResponse(); when(exchange.getResponse()).thenReturn(response); - Configuration configuration = mock(Configuration.class); + StrategiesSupplier strategies = mock(StrategiesSupplier.class); - result.writeTo(exchange, configuration).block(); + result.writeTo(exchange, strategies).block(); assertEquals(201, response.getStatusCode().value()); assertEquals("MyValue", response.getHeaders().getFirst("MyKey")); assertNull(response.getBody()); @@ -207,9 +207,9 @@ public class DefaultResponseBuilderTests { ServerWebExchange exchange = mock(ServerWebExchange.class); MockServerHttpResponse response = new MockServerHttpResponse(); when(exchange.getResponse()).thenReturn(response); - Configuration configuration = mock(Configuration.class); + StrategiesSupplier strategies = mock(StrategiesSupplier.class); - result.writeTo(exchange, configuration).block(); + result.writeTo(exchange, strategies).block(); assertNull(response.getBody()); } @@ -217,8 +217,8 @@ public class DefaultResponseBuilderTests { public void bodyInserter() throws Exception { String body = "foo"; Supplier supplier = () -> body; - BiFunction> writer = - (response, configuration) -> { + BiFunction> writer = + (response, strategies) -> { byte[] bodyBytes = body.getBytes(UTF_8); ByteBuffer byteBuffer = ByteBuffer.wrap(bodyBytes); DataBuffer buffer = new DefaultDataBufferFactory().wrap(byteBuffer); @@ -238,10 +238,10 @@ public class DefaultResponseBuilderTests { List> messageWriters = new ArrayList<>(); messageWriters.add(new EncoderHttpMessageWriter(new CharSequenceEncoder())); - Configuration configuration = mock(Configuration.class); - when(configuration.messageWriters()).thenReturn(messageWriters::stream); + StrategiesSupplier strategies = mock(StrategiesSupplier.class); + when(strategies.messageWriters()).thenReturn(messageWriters::stream); - result.writeTo(exchange, configuration).block(); + result.writeTo(exchange, strategies).block(); assertNotNull(response.getBody()); } @@ -264,7 +264,7 @@ public class DefaultResponseBuilderTests { List viewResolvers = new ArrayList<>(); viewResolvers.add(viewResolver); - Configuration mockConfig = mock(Configuration.class); + StrategiesSupplier mockConfig = mock(StrategiesSupplier.class); when(mockConfig.viewResolvers()).thenReturn(viewResolvers::stream); result.writeTo(exchange, mockConfig).block(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java index 4c04246ff4b..c1eecceb4c1 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java @@ -120,7 +120,7 @@ public class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegr public HandlerMapping handlerMapping(RouterFunction routerFunction, ApplicationContext applicationContext) { return RouterFunctions.toHandlerMapping(routerFunction, - new org.springframework.web.reactive.function.Configuration() { + new StrategiesSupplier() { @Override public Supplier>> messageReaders() { return () -> getMessageReaders().stream(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java index daa9ec62b34..d108d1bb119 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java @@ -112,17 +112,17 @@ public class RouterFunctionsTests { @Test public void toHttpHandler() throws Exception { - Configuration configuration = mock(Configuration.class); - when(configuration.messageReaders()).thenReturn( + StrategiesSupplier strategies = mock(StrategiesSupplier.class); + when(strategies.messageReaders()).thenReturn( () -> Collections.>emptyList().stream()); - when(configuration.messageWriters()).thenReturn( + when(strategies.messageWriters()).thenReturn( () -> Collections.>emptyList().stream()); - when(configuration.viewResolvers()).thenReturn( + when(strategies.viewResolvers()).thenReturn( () -> Collections.emptyList().stream()); Request request = mock(Request.class); Response response = mock(Response.class); - when(response.writeTo(any(ServerWebExchange.class), eq(configuration))).thenReturn(Mono.empty()); + when(response.writeTo(any(ServerWebExchange.class), eq(strategies))).thenReturn(Mono.empty()); HandlerFunction handlerFunction = mock(HandlerFunction.class); when(handlerFunction.handle(any(Request.class))).thenReturn(response); @@ -134,7 +134,7 @@ public class RouterFunctionsTests { when(requestPredicate.test(request)).thenReturn(false); - HttpHandler result = RouterFunctions.toHttpHandler(routerFunction, configuration); + HttpHandler result = RouterFunctions.toHttpHandler(routerFunction, strategies); assertNotNull(result); MockServerHttpRequest httpRequest = diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/ConfigurationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/StrategiesSupplierTests.java similarity index 66% rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/function/ConfigurationTests.java rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/function/StrategiesSupplierTests.java index dc7c4f69256..cf5e7d7de8c 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/ConfigurationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/StrategiesSupplierTests.java @@ -19,6 +19,9 @@ package org.springframework.web.reactive.function; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.junit.Test; import org.reactivestreams.Publisher; @@ -33,12 +36,41 @@ import org.springframework.http.ReactiveHttpOutputMessage; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Arjen Poutsma */ -public class ConfigurationTests { +public class StrategiesSupplierTests { + + @Test + public void empty() { + StrategiesSupplier strategies = StrategiesSupplier.empty().build(); + assertEquals(Optional.empty(), strategies.messageReaders().get().findFirst()); + assertEquals(Optional.empty(), strategies.messageWriters().get().findFirst()); + assertEquals(Optional.empty(), strategies.viewResolvers().get().findFirst()); + } + + + @Test + public void ofSuppliers() { + HttpMessageReader messageReader = new DummyMessageReader(); + HttpMessageWriter messageWriter = new DummyMessageWriter(); + + StrategiesSupplier strategies = StrategiesSupplier.of( + () -> Stream.of(messageReader), + () -> Stream.of(messageWriter), + null); + + assertEquals(1L, strategies.messageReaders().get().collect(Collectors.counting()).longValue()); + assertEquals(Optional.of(messageReader), strategies.messageReaders().get().findFirst()); + + assertEquals(1L, strategies.messageWriters().get().collect(Collectors.counting()).longValue()); + assertEquals(Optional.of(messageWriter), strategies.messageWriters().get().findFirst()); + + assertEquals(Optional.empty(), strategies.viewResolvers().get().findFirst()); + } @Test public void toConfiguration() throws Exception { @@ -47,10 +79,11 @@ public class ConfigurationTests { applicationContext.registerSingleton("messageReader", DummyMessageReader.class); applicationContext.refresh(); - Configuration configuration = Configuration.applicationContext(applicationContext).build(); - assertTrue(configuration.messageReaders().get() + StrategiesSupplier + strategies = StrategiesSupplier.applicationContext(applicationContext).build(); + assertTrue(strategies.messageReaders().get() .allMatch(r -> r instanceof DummyMessageReader)); - assertTrue(configuration.messageWriters().get() + assertTrue(strategies.messageWriters().get() .allMatch(r -> r instanceof DummyMessageWriter)); }