Browse Source

Rename Configuration to StrategiesSupplier

pull/1181/head
Arjen Poutsma 9 years ago
parent
commit
753bb854aa
  1. 4
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java
  2. 9
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java
  3. 6
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java
  4. 22
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java
  5. 8
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java
  6. 14
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java
  7. 25
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultStrategiesSupplierBuilder.java
  8. 5
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java
  9. 37
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java
  10. 71
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/StrategiesSupplier.java
  11. 18
      spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java
  12. 12
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java
  13. 10
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java
  14. 8
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java
  15. 20
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java
  16. 2
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java
  17. 12
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java
  18. 41
      spring-web-reactive/src/test/java/org/springframework/web/reactive/function/StrategiesSupplierTests.java

4
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractor.java

@ -33,9 +33,9 @@ public interface BodyExtractor<T> { @@ -33,9 +33,9 @@ public interface BodyExtractor<T> {
/**
* 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);
}

9
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java

@ -61,7 +61,7 @@ public abstract class BodyExtractors { @@ -61,7 +61,7 @@ public abstract class BodyExtractors {
*/
public static <T> BodyExtractor<Mono<T>> 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 { @@ -86,7 +86,7 @@ public abstract class BodyExtractors {
*/
public static <T> BodyExtractor<Flux<T>> 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 { @@ -94,14 +94,13 @@ public abstract class BodyExtractors {
private static <T, S extends Publisher<T>> S readWithMessageReaders(
ServerHttpRequest request,
Configuration configuration,
StrategiesSupplier strategies,
ResolvableType elementType,
Function<HttpMessageReader<T>, S> readerFunction,
Function<Throwable, S> unsupportedError) {
MediaType contentType = contentType(request);
Supplier<Stream<HttpMessageReader<?>>> messageReaders =
configuration.messageReaders();
Supplier<Stream<HttpMessageReader<?>>> messageReaders = strategies.messageReaders();
return messageReaders.get()
.filter(r -> r.canRead(elementType, contentType, Collections.emptyMap()))
.findFirst()

6
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserter.java

@ -39,10 +39,10 @@ public interface BodyInserter<T> { @@ -39,10 +39,10 @@ public interface BodyInserter<T> {
/**
* 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<Void> insert(ServerHttpResponse response, Configuration configuration);
Mono<Void> insert(ServerHttpResponse response, StrategiesSupplier strategies);
/**
* Return the type contained in the body.
@ -58,7 +58,7 @@ public interface BodyInserter<T> { @@ -58,7 +58,7 @@ public interface BodyInserter<T> {
* @param <T> the type supplied and written by the inserter
* @return the new {@code BodyInserter}
*/
static <T> BodyInserter<T> of(BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer,
static <T> BodyInserter<T> of(BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> writer,
Supplier<T> supplier) {
Assert.notNull(writer, "'writer' must not be null");

22
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/BodyInserters.java

@ -64,7 +64,7 @@ public abstract class BodyInserters { @@ -64,7 +64,7 @@ public abstract class BodyInserters {
public static <T> BodyInserter<T> 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 { @@ -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 { @@ -117,7 +117,7 @@ public abstract class BodyInserters {
public static <T extends Resource> BodyInserter<T> 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 { @@ -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 { @@ -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 { @@ -201,13 +201,13 @@ public abstract class BodyInserters {
}
private static <T> Mono<Void> writeWithMessageWriters(ServerHttpResponse response,
Configuration configuration,
StrategiesSupplier strategies,
Publisher<T> 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 { @@ -228,20 +228,20 @@ public abstract class BodyInserters {
static class DefaultBodyInserter<T> implements BodyInserter<T> {
private final BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer;
private final BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> writer;
private final Supplier<T> supplier;
public DefaultBodyInserter(
BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer,
BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> writer,
Supplier<T> supplier) {
this.writer = writer;
this.supplier = supplier;
}
@Override
public Mono<Void> insert(ServerHttpResponse response, Configuration configuration) {
return this.writer.apply(response, configuration);
public Mono<Void> insert(ServerHttpResponse response, StrategiesSupplier strategies) {
return this.writer.apply(response, strategies);
}
@Override

8
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultRequest.java

@ -42,11 +42,11 @@ class DefaultRequest implements Request { @@ -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 { @@ -67,7 +67,7 @@ class DefaultRequest implements Request {
@Override
public <T> T body(BodyExtractor<T> extractor) {
return extractor.extract(request(), this.configuration);
return extractor.extract(request(), this.strategies);
}
@Override

14
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponseBuilder.java

@ -142,7 +142,7 @@ class DefaultResponseBuilder implements Response.BodyBuilder { @@ -142,7 +142,7 @@ class DefaultResponseBuilder implements Response.BodyBuilder {
@Override
public Response<Void> build() {
return body(BodyInserter.of(
(response, configuration) -> response.setComplete(),
(response, strategies) -> response.setComplete(),
() -> null));
}
@ -150,12 +150,12 @@ class DefaultResponseBuilder implements Response.BodyBuilder { @@ -150,12 +150,12 @@ class DefaultResponseBuilder implements Response.BodyBuilder {
public <T extends Publisher<Void>> Response<T> 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 <T> Response<T> body(BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer,
public <T> Response<T> body(BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> writer,
Supplier<T> supplier) {
return body(BodyInserter.of(writer, supplier));
}
@ -250,10 +250,10 @@ class DefaultResponseBuilder implements Response.BodyBuilder { @@ -250,10 +250,10 @@ class DefaultResponseBuilder implements Response.BodyBuilder {
}
@Override
public Mono<Void> writeTo(ServerWebExchange exchange, Configuration configuration) {
public Mono<Void> 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 { @@ -281,12 +281,12 @@ class DefaultResponseBuilder implements Response.BodyBuilder {
}
@Override
public Mono<Void> writeTo(ServerWebExchange exchange, Configuration configuration) {
public Mono<Void> 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<ViewResolver> viewResolverStream = configuration.viewResolvers().get();
Stream<ViewResolver> viewResolverStream = strategies.viewResolvers().get();
return Flux.fromStream(viewResolverStream)
.concatMap(viewResolver -> viewResolver.resolveViewName(this.name, locale))
.next()

25
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfigurationBuilder.java → spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultStrategiesSupplierBuilder.java

@ -17,7 +17,6 @@ @@ -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; @@ -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<HttpMessageReader<?>> messageReaders = new ArrayList<>();
@ -85,33 +86,33 @@ class DefaultConfigurationBuilder implements Configuration.Builder { @@ -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<HttpMessageReader<?>> messageReaders;
@ -119,7 +120,7 @@ class DefaultConfigurationBuilder implements Configuration.Builder { @@ -119,7 +120,7 @@ class DefaultConfigurationBuilder implements Configuration.Builder {
private final List<ViewResolver> viewResolvers;
public DefaultConfiguration(
public DefaultStrategiesSupplier(
List<HttpMessageReader<?>> messageReaders,
List<HttpMessageWriter<?>> messageWriters,
List<ViewResolver> viewResolvers) {

5
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Response.java

@ -67,9 +67,10 @@ public interface Response<T> { @@ -67,9 +67,10 @@ public interface Response<T> {
* 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<Void>} to indicate when request handling is complete
*/
Mono<Void> writeTo(ServerWebExchange exchange, Configuration configuration);
Mono<Void> writeTo(ServerWebExchange exchange, StrategiesSupplier strategies);
// Static builder methods
@ -315,7 +316,7 @@ public interface Response<T> { @@ -315,7 +316,7 @@ public interface Response<T> {
* @param <T> the type contained in the body
* @return the built response
*/
<T> Response<T> body(BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer,
<T> Response<T> body(BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> writer,
Supplier<T> supplier);
/**

37
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RouterFunctions.java

@ -38,7 +38,7 @@ import org.springframework.web.server.adapter.HttpWebHandlerAdapter; @@ -38,7 +38,7 @@ import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
* <p>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 { @@ -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}.
*
* <p>The returned {@code HttpHandler} can be adapted to run in
* <ul>
@ -121,12 +121,12 @@ public abstract class RouterFunctions { @@ -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.
*
* <p>The returned {@code HttpHandler} can be adapted to run in
* <ul>
@ -141,26 +141,26 @@ public abstract class RouterFunctions { @@ -141,26 +141,26 @@ public abstract class RouterFunctions {
* </ul>
*
* @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}.
*
* <p>The returned {@code HandlerMapping} can be run in a
* {@link org.springframework.web.reactive.DispatcherHandler}.
@ -171,27 +171,28 @@ public abstract class RouterFunctions { @@ -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.
*
* <p>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<? extends HandlerFunction<?>> route = routerFunction.route(request);
@ -199,8 +200,8 @@ public abstract class RouterFunctions { @@ -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) {

71
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Configuration.java → spring-web-reactive/src/main/java/org/springframework/web/reactive/function/StrategiesSupplier.java

@ -26,15 +26,18 @@ import org.springframework.util.Assert; @@ -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 { @@ -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<Stream<HttpMessageReader<?>>> messageReaders,
Supplier<Stream<HttpMessageWriter<?>>> messageWriters,
Supplier<Stream<ViewResolver>> viewResolvers) {
return new StrategiesSupplier() {
@Override
public Supplier<Stream<HttpMessageReader<?>>> messageReaders() {
return checkForNull(messageReaders);
}
@Override
public Supplier<Stream<HttpMessageWriter<?>>> messageWriters() {
return checkForNull(messageWriters);
}
@Override
public Supplier<Stream<ViewResolver>> viewResolvers() {
return checkForNull(viewResolvers);
}
private <T> Supplier<Stream<T>> checkForNull(Supplier<Stream<T>> 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 { @@ -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 { @@ -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();
}
}

18
spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/ResponseResultHandler.java

@ -21,8 +21,8 @@ import reactor.core.publisher.Mono; @@ -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; @@ -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 { @@ -61,6 +61,6 @@ public class ResponseResultHandler implements HandlerResultHandler {
public Mono<Void> 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);
}
}

12
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java

@ -48,9 +48,9 @@ public class BodyExtractorsTests { @@ -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<String> result = extractor.extract(request, configuration);
Mono<String> result = extractor.extract(request, strategies);
TestSubscriber.subscribe(result)
.assertComplete()
@ -69,9 +69,9 @@ public class BodyExtractorsTests { @@ -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<String> result = extractor.extract(request, configuration);
Flux<String> result = extractor.extract(request, strategies);
TestSubscriber.subscribe(result)
.assertComplete()
.assertValues("foo");
@ -90,9 +90,9 @@ public class BodyExtractorsTests { @@ -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<String> result = extractor.extract(request, configuration);
Flux<String> result = extractor.extract(request, strategies);
TestSubscriber.subscribe(result)
.assertError(UnsupportedMediaTypeStatusException.class);

10
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/BodyInsertersTests.java

@ -48,7 +48,7 @@ public class BodyInsertersTests { @@ -48,7 +48,7 @@ public class BodyInsertersTests {
assertEquals(body, inserter.t());
MockServerHttpResponse response = new MockServerHttpResponse();
Mono<Void> result = inserter.insert(response, Configuration.builder().build());
Mono<Void> result = inserter.insert(response, StrategiesSupplier.builder().build());
TestSubscriber.subscribe(result)
.assertComplete();
@ -67,7 +67,7 @@ public class BodyInsertersTests { @@ -67,7 +67,7 @@ public class BodyInsertersTests {
assertEquals(body, inserter.t());
MockServerHttpResponse response = new MockServerHttpResponse();
Mono<Void> result = inserter.insert(response, Configuration.builder().build());
Mono<Void> result = inserter.insert(response, StrategiesSupplier.builder().build());
TestSubscriber.subscribe(result)
.assertComplete();
@ -86,7 +86,7 @@ public class BodyInsertersTests { @@ -86,7 +86,7 @@ public class BodyInsertersTests {
assertEquals(body, inserter.t());
MockServerHttpResponse response = new MockServerHttpResponse();
Mono<Void> result = inserter.insert(response, Configuration.builder().build());
Mono<Void> result = inserter.insert(response, StrategiesSupplier.builder().build());
TestSubscriber.subscribe(result)
.assertComplete();
@ -111,7 +111,7 @@ public class BodyInsertersTests { @@ -111,7 +111,7 @@ public class BodyInsertersTests {
assertEquals(body, inserter.t());
MockServerHttpResponse response = new MockServerHttpResponse();
Mono<Void> result = inserter.insert(response, Configuration.builder().build());
Mono<Void> result = inserter.insert(response, StrategiesSupplier.builder().build());
TestSubscriber.subscribe(result)
.assertComplete();
@ -126,7 +126,7 @@ public class BodyInsertersTests { @@ -126,7 +126,7 @@ public class BodyInsertersTests {
assertEquals(body, inserter.t());
MockServerHttpResponse response = new MockServerHttpResponse();
Mono<Void> result = inserter.insert(response, Configuration.builder().build());
Mono<Void> result = inserter.insert(response, StrategiesSupplier.builder().build());
TestSubscriber.subscribe(result)
.assertComplete();

8
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultRequestTests.java

@ -65,7 +65,7 @@ public class DefaultRequestTests { @@ -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 { @@ -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 { @@ -171,7 +171,7 @@ public class DefaultRequestTests {
Set<HttpMessageReader<?>> messageReaders = Collections
.singleton(new DecoderHttpMessageReader<String>(new StringDecoder()));
when(mockConfiguration.messageReaders()).thenReturn(messageReaders::stream);
when(mockStrategiesSupplier.messageReaders()).thenReturn(messageReaders::stream);
Mono<String> resultMono = defaultRequest.body(toMono(String.class));
assertEquals("foo", resultMono.block());

20
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultResponseBuilderTests.java

@ -190,9 +190,9 @@ public class DefaultResponseBuilderTests { @@ -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 { @@ -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 { @@ -217,8 +217,8 @@ public class DefaultResponseBuilderTests {
public void bodyInserter() throws Exception {
String body = "foo";
Supplier<String> supplier = () -> body;
BiFunction<ServerHttpResponse, Configuration, Mono<Void>> writer =
(response, configuration) -> {
BiFunction<ServerHttpResponse, StrategiesSupplier, Mono<Void>> 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 { @@ -238,10 +238,10 @@ public class DefaultResponseBuilderTests {
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(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 { @@ -264,7 +264,7 @@ public class DefaultResponseBuilderTests {
List<ViewResolver> 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();

2
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DispatcherHandlerIntegrationTests.java

@ -120,7 +120,7 @@ public class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegr @@ -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<Stream<HttpMessageReader<?>>> messageReaders() {
return () -> getMessageReaders().stream();

12
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterFunctionsTests.java

@ -112,17 +112,17 @@ public class RouterFunctionsTests { @@ -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.<HttpMessageReader<?>>emptyList().stream());
when(configuration.messageWriters()).thenReturn(
when(strategies.messageWriters()).thenReturn(
() -> Collections.<HttpMessageWriter<?>>emptyList().stream());
when(configuration.viewResolvers()).thenReturn(
when(strategies.viewResolvers()).thenReturn(
() -> Collections.<ViewResolver>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 { @@ -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 =

41
spring-web-reactive/src/test/java/org/springframework/web/reactive/function/ConfigurationTests.java → spring-web-reactive/src/test/java/org/springframework/web/reactive/function/StrategiesSupplierTests.java

@ -19,6 +19,9 @@ package org.springframework.web.reactive.function; @@ -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; @@ -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 { @@ -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));
}
Loading…
Cancel
Save