From 31d1e26c95ebaf179a20ffe9b1328a21857954c3 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 24 May 2017 13:48:03 +0200 Subject: [PATCH] Use List instead of Supplier> This commit changes all methods that return `Supplier` to return `List` instead. This includes the HandlerStrategies, but also BodyInserter.Context, BodyExtractor.Context, and ServerResponse.Context. The reason for this change is that most of the strategies have some sort of order, where more specific message readers - for instance - come before generic ones. Such an ordering can only be enforced through a List. Issue: SPR-15578 --- .../web/reactive/function/BodyExtractor.java | 8 ++- .../web/reactive/function/BodyExtractors.java | 10 ++-- .../web/reactive/function/BodyInserter.java | 8 ++- .../web/reactive/function/BodyInserters.java | 12 ++--- .../client/DefaultClientRequestBuilder.java | 5 +- .../client/DefaultClientResponse.java | 4 +- .../DefaultExchangeStrategiesBuilder.java | 10 ++-- .../function/client/ExchangeStrategies.java | 16 +++--- .../server/DefaultEntityResponseBuilder.java | 5 +- .../DefaultHandlerStrategiesBuilder.java | 22 ++++----- .../DefaultRenderingResponseBuilder.java | 2 +- .../function/server/DefaultServerRequest.java | 18 ++++--- .../server/DefaultServerResponseBuilder.java | 5 +- .../function/server/HandlerStrategies.java | 38 ++++++-------- .../function/server/RouterFunctions.java | 49 ++++++++++--------- .../function/server/ServerRequest.java | 2 +- .../function/server/ServerResponse.java | 13 ++--- .../support/ServerResponseResultHandler.java | 10 ++-- .../function/BodyExtractorsTests.java | 10 ++-- .../reactive/function/BodyInsertersTests.java | 10 ++-- .../DefaultClientRequestBuilderTests.java | 8 +-- .../client/DefaultClientResponseTests.java | 19 ++++--- .../client/ExchangeStrategiesTests.java | 10 ++-- .../DefaultEntityResponseBuilderTests.java | 10 ++-- .../server/DefaultRenderingResponseTests.java | 5 +- .../server/DefaultServerRequestTests.java | 8 ++- .../server/HandlerStrategiesTests.java | 14 +++--- .../server/ResourceHandlerFunctionTests.java | 7 ++- 28 files changed, 150 insertions(+), 188 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java index 67cbefc265..f5833db804 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java @@ -16,10 +16,9 @@ package org.springframework.web.reactive.function; +import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.http.codec.HttpMessageReader; @@ -52,11 +51,10 @@ public interface BodyExtractor { interface Context { /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageReader}s - * to be used for body extraction. + * Return the {@link HttpMessageReader}s to be used for body extraction. * @return the stream of message readers */ - Supplier>> messageReaders(); + List> messageReaders(); /** * Optionally return the {@link ServerHttpResponse}, if present. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java index 36999443fa..e2074416c1 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java @@ -19,9 +19,7 @@ package org.springframework.web.reactive.function; import java.util.List; import java.util.Optional; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -197,14 +195,14 @@ public abstract class BodyExtractors { Function, S> readerFunction, Function unsupportedError) { MediaType contentType = contentType(inputMessage); - Supplier>> messageReaders = context.messageReaders(); - return messageReaders.get() + List> messageReaders = context.messageReaders(); + return messageReaders.stream() .filter(r -> r.canRead(elementType, contentType)) .findFirst() .map(BodyExtractors::cast) .map(readerFunction) .orElseGet(() -> { - List supportedMediaTypes = messageReaders.get() + List supportedMediaTypes = messageReaders.stream() .flatMap(reader -> reader.getReadableMediaTypes().stream()) .collect(Collectors.toList()); UnsupportedMediaTypeException error = @@ -215,7 +213,7 @@ public abstract class BodyExtractors { private static HttpMessageReader messageReader(ResolvableType elementType, MediaType mediaType, BodyExtractor.Context context) { - return context.messageReaders().get() + return context.messageReaders().stream() .filter(messageReader -> messageReader.canRead(elementType, mediaType)) .findFirst() .map(BodyExtractors::cast) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserter.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserter.java index 317a2e4dcd..f300ad1f11 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserter.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserter.java @@ -16,10 +16,9 @@ package org.springframework.web.reactive.function; +import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Mono; @@ -54,11 +53,10 @@ public interface BodyInserter { interface Context { /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s - * to be used for response body conversion. + * Return the {@link HttpMessageWriter}s to be used for response body conversion. * @return the stream of message writers */ - Supplier>> messageWriters(); + List> messageWriters(); /** * Optionally return the {@link ServerHttpRequest}, if present. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java index 8e12b60f2a..55b1c4455a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java @@ -18,9 +18,7 @@ package org.springframework.web.reactive.function; import java.util.List; import java.util.Optional; -import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -141,7 +139,7 @@ public abstract class BodyInserters { } private static HttpMessageWriter resourceHttpMessageWriter(BodyInserter.Context context) { - return context.messageWriters().get() + return context.messageWriters().stream() .filter(messageWriter -> messageWriter.canWrite(RESOURCE_TYPE, null)) .findFirst() .map(BodyInserters::cast) @@ -288,8 +286,8 @@ public abstract class BodyInserters { return (outputMessage, context) -> { MediaType contentType = outputMessage.getHeaders().getContentType(); - Supplier>> messageWriters = context.messageWriters(); - return messageWriters.get() + List> messageWriters = context.messageWriters(); + return messageWriters.stream() .filter(messageWriter -> messageWriter.canWrite(bodyType, contentType)) .findFirst() .map(BodyInserters::cast) @@ -305,7 +303,7 @@ public abstract class BodyInserters { } }) .orElseGet(() -> { - List supportedMediaTypes = messageWriters.get() + List supportedMediaTypes = messageWriters.stream() .flatMap(reader -> reader.getWritableMediaTypes().stream()) .collect(Collectors.toList()); UnsupportedMediaTypeException error = @@ -318,7 +316,7 @@ public abstract class BodyInserters { private static HttpMessageWriter findMessageWriter( BodyInserter.Context context, ResolvableType type, MediaType mediaType) { - return context.messageWriters().get() + return context.messageWriters().stream() .filter(messageWriter -> messageWriter.canWrite(type, mediaType)) .findFirst() .map(BodyInserters::cast) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java index 17bb7c860e..43f306aee8 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java @@ -18,10 +18,9 @@ package org.springframework.web.reactive.function.client; import java.net.URI; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -187,7 +186,7 @@ class DefaultClientRequestBuilder implements ClientRequest.Builder { return this.inserter.insert(request, new BodyInserter.Context() { @Override - public Supplier>> messageWriters() { + public List> messageWriters() { return strategies.messageWriters(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java index dc2b8a0a7d..01c5417158 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java @@ -21,8 +21,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -79,7 +77,7 @@ class DefaultClientResponse implements ClientResponse { public T body(BodyExtractor extractor) { return extractor.extract(this.response, new BodyExtractor.Context() { @Override - public Supplier>> messageReaders() { + public List> messageReaders() { return strategies.messageReaders(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java index 4ecdd878be..10fe28383d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.HttpMessageReader; @@ -88,13 +86,13 @@ class DefaultExchangeStrategiesBuilder implements ExchangeStrategies.Builder { } @Override - public Supplier>> messageReaders() { - return this.messageReaders::stream; + public List> messageReaders() { + return this.messageReaders; } @Override - public Supplier>> messageWriters() { - return this.messageWriters::stream; + public List> messageWriters() { + return this.messageWriters; } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java index 6aee224e7a..14b13095f4 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java @@ -16,9 +16,8 @@ package org.springframework.web.reactive.function.client; +import java.util.List; import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.HttpMessageReader; @@ -28,8 +27,7 @@ import org.springframework.http.codec.HttpMessageWriter; * Defines the strategies for invoking {@link ExchangeFunction}s. An instance of * this class is immutable; instances are typically created through the mutable {@link Builder}: * either through {@link #builder()} to set up default strategies, or {@link #empty()} to start - * from scratch. Alternatively, {@code ExchangeStrategies} instances can be created through - * {@link #of(Supplier, Supplier)}. + * from scratch. * * @author Brian Clozel * @author Arjen Poutsma @@ -40,18 +38,16 @@ public interface ExchangeStrategies { // Instance methods /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageReader}s to be used for request - * body conversion. + * Return the {@link HttpMessageReader}s to be used for request body conversion. * @return the stream of message readers */ - Supplier>> messageReaders(); + List> messageReaders(); /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s to be used for response - * body conversion. + * Return the {@link HttpMessageWriter}s to be used for response body conversion. * @return the stream of message writers */ - Supplier>> messageWriters(); + List> messageWriters(); // Static methods diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java index 61817ee017..9062db6012 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java @@ -23,11 +23,10 @@ import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Mono; @@ -208,7 +207,7 @@ class DefaultEntityResponseBuilder implements EntityResponse.Builder { writeStatusAndHeaders(response); return inserter().insert(response, new BodyInserter.Context() { @Override - public Supplier>> messageWriters() { + public List> messageWriters() { return context.messageWriters(); } 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 a31a9f7109..309f37eed1 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 @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.springframework.http.codec.CodecConfigurer; import org.springframework.http.codec.HttpMessageReader; @@ -135,28 +133,28 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { } @Override - public Supplier>> messageReaders() { - return this.messageReaders::stream; + public List> messageReaders() { + return this.messageReaders; } @Override - public Supplier>> messageWriters() { - return this.messageWriters::stream; + public List> messageWriters() { + return this.messageWriters; } @Override - public Supplier> viewResolvers() { - return this.viewResolvers::stream; + public List viewResolvers() { + return this.viewResolvers; } @Override - public Supplier> webFilters() { - return this.webFilters::stream; + public List webFilters() { + return this.webFilters; } @Override - public Supplier> exceptionHandlers() { - return this.exceptionHandlers::stream; + public List exceptionHandlers() { + return this.exceptionHandlers; } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java index 6a24d4f5db..48c78004ea 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java @@ -164,7 +164,7 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder { writeStatusAndHeaders(response); MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Locale locale = resolveLocale(exchange); - Stream viewResolverStream = context.viewResolvers().get(); + Stream viewResolverStream = context.viewResolvers().stream(); return Flux.fromStream(viewResolverStream) .concatMap(viewResolver -> viewResolver.resolveViewName(name(), locale)) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java index ba563a0197..4dde1f6fca 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java @@ -20,6 +20,7 @@ import java.net.InetSocketAddress; import java.net.URI; import java.nio.charset.Charset; import java.security.Principal; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -27,8 +28,6 @@ import java.util.Map; import java.util.Optional; import java.util.OptionalLong; import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -66,15 +65,20 @@ class DefaultServerRequest implements ServerRequest { private final Headers headers; - private final Supplier>> messageReaders; + private final List> messageReaders; - DefaultServerRequest(ServerWebExchange exchange, Supplier>> messageReaders) { + DefaultServerRequest(ServerWebExchange exchange, List> messageReaders) { this.exchange = exchange; - this.messageReaders = messageReaders; + this.messageReaders = unmodifiableCopy(messageReaders); this.headers = new DefaultHeaders(); } + private static List unmodifiableCopy(List list) { + return Collections.unmodifiableList(new ArrayList<>(list)); + } + + @Override public HttpMethod method() { @@ -102,8 +106,8 @@ class DefaultServerRequest implements ServerRequest { return extractor.extract(request(), new BodyExtractor.Context() { @Override - public Supplier>> messageReaders() { - return DefaultServerRequest.this.messageReaders; + public List> messageReaders() { + return messageReaders; } @Override public Optional serverResponse() { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java index c65468f12c..9ed32619a6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java @@ -23,12 +23,11 @@ import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -314,7 +313,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { writeStatusAndHeaders(response); return this.inserter.insert(response, new BodyInserter.Context() { @Override - public Supplier>> messageWriters() { + public List> messageWriters() { return context.messageWriters(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java index cb24450f04..86f0f6e75d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java @@ -16,9 +16,8 @@ package org.springframework.web.reactive.function.server; +import java.util.List; import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; @@ -43,39 +42,34 @@ public interface HandlerStrategies { // Instance methods /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageReader}s to be used for request - * body conversion. - * @return the stream of message readers + * Return the {@link HttpMessageReader}s to be used for request body conversion. + * @return the message readers */ - Supplier>> messageReaders(); + List> messageReaders(); /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s to be used for response - * body conversion. - * @return the stream of message writers + * Return the {@link HttpMessageWriter}s to be used for response body conversion. + * @return the message writers */ - Supplier>> messageWriters(); + List> messageWriters(); /** - * Supply a {@linkplain Stream stream} of {@link ViewResolver}s to be used for view name - * resolution. - * @return the stream of view resolvers + * Return the {@link ViewResolver}s to be used for view name resolution. + * @return the view resolvers */ - Supplier> viewResolvers(); + List viewResolvers(); /** - * Supply a {@linkplain Stream stream} of {@link WebFilter}s to be used for filtering the - * request and response. - * @return the stream of web filters + * Return the {@link WebFilter}s to be used for filtering the request and response. + * @return the web filters */ - Supplier> webFilters(); + List webFilters(); /** - * Supply a {@linkplain Stream stream} of {@link WebExceptionHandler}s to be used for handling - * exceptions. - * @return the stream of exception handlers + * Return the {@link WebExceptionHandler}s to be used for handling exceptions. + * @return the exception handlers */ - Supplier> exceptionHandlers(); + List exceptionHandlers(); // Static methods diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java index 0ccf687b08..4be209d888 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java @@ -16,10 +16,10 @@ package org.springframework.web.reactive.function.server; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Stream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -45,9 +45,6 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder; *

Additionally, this class can {@linkplain #toHttpHandler(RouterFunction) transform} a * {@code RouterFunction} into an {@code HttpHandler}, which can be run in Servlet 3.1+, * Reactor, or Undertow. - * And it can {@linkplain #toHandlerMapping(RouterFunction, HandlerStrategies) transform} a - * {@code RouterFunction} into an {@code HandlerMapping}, which can be run in a - * {@code DispatcherHandler}. * * @author Arjen Poutsma * @since 5.0 @@ -199,10 +196,10 @@ public abstract class RouterFunctions { Assert.notNull(strategies, "HandlerStrategies must not be null"); WebHandler webHandler = toWebHandler(routerFunction, strategies); - WebHttpHandlerBuilder handlerBuilder = WebHttpHandlerBuilder.webHandler(webHandler); - strategies.webFilters().get().forEach(handlerBuilder::filter); - strategies.exceptionHandlers().get().forEach(handlerBuilder::exceptionHandler); - return handlerBuilder.build(); + return WebHttpHandlerBuilder.webHandler(webHandler) + .filters(strategies.webFilters()) + .exceptionHandlers(strategies.exceptionHandlers()) + .build(); } /** @@ -222,7 +219,8 @@ public abstract class RouterFunctions { return routerFunction.route(request) .defaultIfEmpty(notFound()) .flatMap(handlerFunction -> wrapException(() -> handlerFunction.handle(request))) - .flatMap(response -> wrapException(() -> response.writeTo(exchange, toContext(strategies)))); + .flatMap(response -> wrapException(() -> response.writeTo(exchange, + new HandlerStrategiesResponseContext(strategies)))); }; } @@ -235,20 +233,6 @@ public abstract class RouterFunctions { } } - private static ServerResponse.Context toContext(HandlerStrategies strategies) { - return new ServerResponse.Context() { - @Override - public Supplier>> messageWriters() { - return strategies.messageWriters(); - } - - @Override - public Supplier> viewResolvers() { - return strategies.viewResolvers(); - } - }; - } - private static void addAttributes(ServerWebExchange exchange, ServerRequest request) { Map attributes = exchange.getAttributes(); attributes.put(REQUEST_ATTRIBUTE, request); @@ -332,4 +316,23 @@ public abstract class RouterFunctions { } } + + private static class HandlerStrategiesResponseContext implements ServerResponse.Context { + + private final HandlerStrategies strategies; + + public HandlerStrategiesResponseContext(HandlerStrategies strategies) { + this.strategies = strategies; + } + + @Override + public List> messageWriters() { + return this.strategies.messageWriters(); + } + + @Override + public List viewResolvers() { + return this.strategies.viewResolvers(); + } + } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java index 51d921c774..7eae733b4d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java @@ -187,7 +187,7 @@ public interface ServerRequest { static ServerRequest create(ServerWebExchange exchange, List> messageReaders) { - return new DefaultServerRequest(exchange, messageReaders::stream); + return new DefaultServerRequest(exchange, messageReaders); } /** diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java index ea31e47ba1..29773850ba 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java @@ -19,11 +19,10 @@ package org.springframework.web.reactive.function.server; import java.net.URI; import java.time.ZonedDateTime; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -395,18 +394,16 @@ public interface ServerResponse { interface Context { /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s - * to be used for response body conversion. + * Return the {@link HttpMessageWriter}s to be used for response body conversion. * @return the stream of message writers */ - Supplier>> messageWriters(); + List> messageWriters(); /** - * Supply a {@linkplain Stream stream} of {@link ViewResolver}s to be used for view name - * resolution. + * Return the {@link ViewResolver}s to be used for view name resolution. * @return the stream of view resolvers */ - Supplier> viewResolvers(); + List viewResolvers(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerResponseResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerResponseResultHandler.java index 2a4853d865..a0a28443cb 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerResponseResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerResponseResultHandler.java @@ -18,8 +18,6 @@ package org.springframework.web.reactive.function.server.support; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Mono; @@ -99,13 +97,13 @@ public class ServerResponseResultHandler implements HandlerResultHandler, Initia Assert.state(response != null, "No ServerResponse"); return response.writeTo(exchange, new ServerResponse.Context() { @Override - public Supplier>> messageWriters() { - return messageCodecConfigurer.getWriters()::stream; + public List> messageWriters() { + return messageCodecConfigurer.getWriters(); } @Override - public Supplier> viewResolvers() { - return viewResolvers::stream; + public List viewResolvers() { + return viewResolvers; } }); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java index 07d7229284..040bf0694c 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java @@ -24,8 +24,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import com.fasterxml.jackson.annotation.JsonView; import org.junit.Before; @@ -86,8 +84,8 @@ public class BodyExtractorsTests { this.context = new BodyExtractor.Context() { @Override - public Supplier>> messageReaders() { - return messageReaders::stream; + public List> messageReaders() { + return messageReaders; } @Override @@ -209,8 +207,8 @@ public class BodyExtractorsTests { BodyExtractor.Context emptyContext = new BodyExtractor.Context() { @Override - public Supplier>> messageReaders() { - return Stream::empty; + public List> messageReaders() { + return Collections.emptyList(); } @Override diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java index 092f77704f..90b5bf4e2e 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java @@ -26,8 +26,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import com.fasterxml.jackson.annotation.JsonView; import org.junit.Before; @@ -93,8 +91,8 @@ public class BodyInsertersTests { this.context = new BodyInserter.Context() { @Override - public Supplier>> messageWriters() { - return messageWriters::stream; + public List> messageWriters() { + return messageWriters; } @Override @@ -207,8 +205,8 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, new BodyInserter.Context() { @Override - public Supplier>> messageWriters() { - return Collections.>singleton(new ResourceHttpMessageWriter())::stream; + public List> messageWriters() { + return Collections.singletonList(new ResourceHttpMessageWriter()); } @Override diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java index 7948b0a524..494fba7a9b 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java @@ -34,10 +34,12 @@ import org.springframework.http.codec.HttpMessageWriter; import org.springframework.mock.http.client.reactive.test.MockClientHttpRequest; import org.springframework.web.reactive.function.BodyInserter; -import static java.nio.charset.StandardCharsets.*; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import static org.springframework.http.HttpMethod.*; +import static org.springframework.http.HttpMethod.DELETE; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; /** * @author Arjen Poutsma @@ -107,7 +109,7 @@ public class DefaultClientRequestBuilderTests { messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); ExchangeStrategies strategies = mock(ExchangeStrategies.class); - when(strategies.messageWriters()).thenReturn(messageWriters::stream); + when(strategies.messageWriters()).thenReturn(messageWriters); MockClientHttpRequest request = new MockClientHttpRequest(GET, "/"); result.writeTo(request, strategies).block(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java index a3c5253268..c2bdc28b67 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.OptionalLong; -import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -121,9 +120,9 @@ public class DefaultClientResponseTests { when(mockResponse.getHeaders()).thenReturn(httpHeaders); when(mockResponse.getBody()).thenReturn(body); - Set> messageReaders = Collections - .singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); - when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream); + List> messageReaders = Collections + .singletonList(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); + when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders); Mono resultMono = defaultClientResponse.body(toMono(String.class)); assertEquals("foo", resultMono.block()); @@ -142,9 +141,9 @@ public class DefaultClientResponseTests { when(mockResponse.getStatusCode()).thenReturn(HttpStatus.OK); when(mockResponse.getBody()).thenReturn(body); - Set> messageReaders = Collections - .singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); - when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream); + List> messageReaders = Collections + .singletonList(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); + when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders); Mono resultMono = defaultClientResponse.bodyToMono(String.class); assertEquals("foo", resultMono.block()); @@ -163,9 +162,9 @@ public class DefaultClientResponseTests { when(mockResponse.getStatusCode()).thenReturn(HttpStatus.OK); when(mockResponse.getBody()).thenReturn(body); - Set> messageReaders = Collections - .singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); - when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream); + List> messageReaders = Collections + .singletonList(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); + when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders); Flux resultFlux = defaultClientResponse.bodyToFlux(String.class); Mono> result = resultFlux.collectList(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java index d98560488f..8fa1f0a1d2 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java @@ -16,8 +16,6 @@ package org.springframework.web.reactive.function.client; -import java.util.Optional; - import org.junit.Test; import static org.junit.Assert.*; @@ -30,15 +28,15 @@ public class ExchangeStrategiesTests { @Test public void empty() { ExchangeStrategies strategies = ExchangeStrategies.empty().build(); - assertEquals(Optional.empty(), strategies.messageReaders().get().findFirst()); - assertEquals(Optional.empty(), strategies.messageWriters().get().findFirst()); + assertTrue(strategies.messageReaders().isEmpty()); + assertTrue(strategies.messageWriters().isEmpty()); } @Test public void withDefaults() { ExchangeStrategies strategies = ExchangeStrategies.withDefaults(); - assertNotEquals(Optional.empty(), strategies.messageReaders().get().findFirst()); - assertNotEquals(Optional.empty(), strategies.messageWriters().get().findFirst()); + assertFalse(strategies.messageReaders().isEmpty()); + assertFalse(strategies.messageWriters().isEmpty()); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilderTests.java index 29436538cc..f7d1fc0889 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilderTests.java @@ -23,8 +23,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.junit.Test; import org.reactivestreams.Publisher; @@ -196,13 +194,13 @@ public class DefaultEntityResponseBuilderTests { ServerResponse.Context context = new ServerResponse.Context() { @Override - public Supplier>> messageWriters() { - return Collections.>singletonList(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()))::stream; + public List> messageWriters() { + return Collections.>singletonList(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); } @Override - public Supplier> viewResolvers() { - return Collections.emptyList()::stream; + public List viewResolvers() { + return Collections.emptyList(); } }; HandlerStrategies strategies = HandlerStrategies.empty() diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java index 677c4a1f9c..7d396874d6 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java @@ -33,8 +33,7 @@ import org.springframework.mock.http.server.reactive.test.MockServerWebExchange; import org.springframework.web.reactive.result.view.View; import org.springframework.web.reactive.result.view.ViewResolver; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; /** * @author Arjen Poutsma @@ -119,7 +118,7 @@ public class DefaultRenderingResponseTests { viewResolvers.add(viewResolver); HandlerStrategies mockConfig = mock(HandlerStrategies.class); - when(mockConfig.viewResolvers()).thenReturn(viewResolvers::stream); + when(mockConfig.viewResolvers()).thenReturn(viewResolvers); StepVerifier.create(result) .expectNextMatches(response -> "view".equals(response.name()) && diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultServerRequestTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultServerRequestTests.java index f00d89fc4e..b6efb6a73b 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultServerRequestTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultServerRequestTests.java @@ -26,8 +26,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; -import java.util.function.Supplier; -import java.util.stream.Stream; import org.junit.Before; import org.junit.Test; @@ -66,7 +64,7 @@ public class DefaultServerRequestTests { private ServerWebExchange mockExchange; - Supplier>> messageReaders; + List> messageReaders; private DefaultServerRequest defaultRequest; @@ -80,7 +78,7 @@ public class DefaultServerRequestTests { when(mockExchange.getRequest()).thenReturn(mockRequest); when(mockExchange.getResponse()).thenReturn(mockResponse); - this.messageReaders = Collections.>singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true)))::stream; + this.messageReaders = Collections.>singletonList(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true))); defaultRequest = new DefaultServerRequest(mockExchange, messageReaders); } @@ -238,7 +236,7 @@ public class DefaultServerRequestTests { when(mockRequest.getHeaders()).thenReturn(httpHeaders); when(mockRequest.getBody()).thenReturn(body); - this.messageReaders = Collections.>emptySet()::stream; + this.messageReaders = Collections.emptyList(); this.defaultRequest = new DefaultServerRequest(mockExchange, messageReaders); Flux resultFlux = defaultRequest.bodyToFlux(String.class); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/HandlerStrategiesTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/HandlerStrategiesTests.java index f34ed8b063..6613996d94 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/HandlerStrategiesTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/HandlerStrategiesTests.java @@ -16,8 +16,6 @@ package org.springframework.web.reactive.function.server; -import java.util.Optional; - import org.junit.Test; import static org.junit.Assert.*; @@ -30,17 +28,17 @@ public class HandlerStrategiesTests { @Test public void empty() { HandlerStrategies strategies = HandlerStrategies.empty().build(); - assertEquals(Optional.empty(), strategies.messageReaders().get().findFirst()); - assertEquals(Optional.empty(), strategies.messageWriters().get().findFirst()); - assertEquals(Optional.empty(), strategies.viewResolvers().get().findFirst()); + assertTrue(strategies.messageReaders().isEmpty()); + assertTrue(strategies.messageWriters().isEmpty()); + assertTrue(strategies.viewResolvers().isEmpty()); } @Test public void withDefaults() { HandlerStrategies strategies = HandlerStrategies.withDefaults(); - assertNotEquals(Optional.empty(), strategies.messageReaders().get().findFirst()); - assertNotEquals(Optional.empty(), strategies.messageWriters().get().findFirst()); - assertEquals(Optional.empty(), strategies.viewResolvers().get().findFirst()); + assertFalse(strategies.messageReaders().isEmpty()); + assertFalse(strategies.messageWriters().isEmpty()); + assertTrue(strategies.viewResolvers().isEmpty()); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ResourceHandlerFunctionTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ResourceHandlerFunctionTests.java index 6d3edf51fc..0cd27b9836 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ResourceHandlerFunctionTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/ResourceHandlerFunctionTests.java @@ -19,8 +19,7 @@ package org.springframework.web.reactive.function.server; import java.io.IOException; import java.nio.file.Files; import java.util.EnumSet; -import java.util.function.Supplier; -import java.util.stream.Stream; +import java.util.List; import org.junit.Before; import org.junit.Test; @@ -56,12 +55,12 @@ public class ResourceHandlerFunctionTests { HandlerStrategies strategies = HandlerStrategies.withDefaults(); context = new ServerResponse.Context() { @Override - public Supplier>> messageWriters() { + public List> messageWriters() { return strategies.messageWriters(); } @Override - public Supplier> viewResolvers() { + public List viewResolvers() { return strategies.viewResolvers(); } };