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/Configuration.java new file mode 100644 index 0000000000..7f49258a28 --- /dev/null +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Configuration.java @@ -0,0 +1,130 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.reactive.function; + +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.springframework.context.ApplicationContext; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +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 + * this class is immutable, but a + * + * @author Arjen Poutsma + * @since 5.0 + */ +public interface Configuration { + + // Static methods + + /** + * Return a mutable, empty builder for a {@code Configuration}. + * @return the builder + */ + static Builder builder() { + return new DefaultConfigurationBuilder(); + } + + /** + * Return a mutable builder for a {@code Configuration} with a default initialization. + * @return the builder + */ + static Builder defaultBuilder() { + DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); + builder.defaultConfiguration(); + return builder; + } + + /** + * 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 + * @return the builder + */ + static Builder applicationContext(ApplicationContext applicationContext) { + Assert.notNull(applicationContext, "'applicationContext' must not be null"); + DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); + builder.applicationContext(applicationContext); + return builder; + } + + // Instance methods + + /** + * Supply a {@linkplain Stream stream} of {@link HttpMessageReader}s to be used for request + * body conversion. + * @return the stream of message readers + */ + Supplier>> messageReaders(); + + /** + * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s to be used for response + * body conversion. + * @return the stream of message writers + */ + Supplier>> messageWriters(); + + /** + * Supply a {@linkplain Stream stream} of {@link ViewResolver}s to be used for view name + * resolution. + * @return the stream of view resolvers + */ + Supplier> viewResolvers(); + + + /** + * A mutable builder for a {@link Configuration}. + */ + interface Builder { + + /** + * Add the given message reader to this builder. + * @param messageReader the message reader to add + * @return this builder + */ + Builder messageReader(HttpMessageReader messageReader); + + /** + * Add the given message writer to this builder. + * @param messageWriter the message writer to add + * @return this builder + */ + Builder messageWriter(HttpMessageWriter messageWriter); + + /** + * Add the given view resolver to this builder. + * @param viewResolver the view resolver to add + * @return this builder + */ + Builder viewResolver(ViewResolver viewResolver); + + /** + * Builds the {@link Configuration}. + * @return the built configuration + */ + Configuration build(); + + } +} diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfiguration.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfiguration.java deleted file mode 100644 index 3eca98b338..0000000000 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfiguration.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.reactive.function; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import org.springframework.core.codec.ByteBufferDecoder; -import org.springframework.core.codec.ByteBufferEncoder; -import org.springframework.core.codec.CharSequenceEncoder; -import org.springframework.core.codec.StringDecoder; -import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.EncoderHttpMessageWriter; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.HttpMessageWriter; -import org.springframework.http.codec.json.Jackson2JsonDecoder; -import org.springframework.http.codec.json.Jackson2JsonEncoder; -import org.springframework.http.codec.xml.Jaxb2XmlDecoder; -import org.springframework.http.codec.xml.Jaxb2XmlEncoder; -import org.springframework.util.ClassUtils; -import org.springframework.web.reactive.result.view.ViewResolver; - -/** - * A default implementation of configuration. - * @author Arjen Poutsma - */ -class DefaultConfiguration implements Router.Configuration { - - private static final boolean jackson2Present = - ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", - DefaultConfiguration.class.getClassLoader()) && - ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", - DefaultConfiguration.class.getClassLoader()); - - private static final boolean jaxb2Present = - ClassUtils.isPresent("javax.xml.bind.Binder", DefaultConfiguration.class.getClassLoader()); - - private final List> messageReaders = new ArrayList<>(); - - private final List> messageWriters = new ArrayList<>(); - - private final List viewResolvers = new ArrayList<>(); - - public DefaultConfiguration() { - this.messageReaders.add(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); - this.messageReaders.add(new DecoderHttpMessageReader<>(new StringDecoder())); - this.messageWriters.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); - this.messageWriters.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder())); - if (jaxb2Present) { - this.messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); - this.messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); - } - if (jackson2Present) { - this.messageReaders.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())); - this.messageWriters.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder())); - } - } - - @Override - public Supplier>> messageReaders() { - return this.messageReaders::stream; - } - - @Override - public Supplier>> messageWriters() { - return this.messageWriters::stream; - } - - @Override - public Supplier> viewResolvers() { - return this.viewResolvers::stream; - } -} 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/DefaultConfigurationBuilder.java new file mode 100644 index 0000000000..7491429ee1 --- /dev/null +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultConfigurationBuilder.java @@ -0,0 +1,151 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.reactive.function; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.springframework.context.ApplicationContext; +import org.springframework.core.codec.ByteBufferDecoder; +import org.springframework.core.codec.ByteBufferEncoder; +import org.springframework.core.codec.CharSequenceEncoder; +import org.springframework.core.codec.StringDecoder; +import org.springframework.http.codec.DecoderHttpMessageReader; +import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.http.codec.xml.Jaxb2XmlDecoder; +import org.springframework.http.codec.xml.Jaxb2XmlEncoder; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.web.reactive.result.view.ViewResolver; + +/** + * @author Arjen Poutsma + * @since 5.0 + */ +class DefaultConfigurationBuilder implements Configuration.Builder { + + private static final boolean jackson2Present = + ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", + DefaultConfigurationBuilder.class.getClassLoader()) && + ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", + DefaultConfigurationBuilder.class.getClassLoader()); + + private static final boolean jaxb2Present = + ClassUtils.isPresent("javax.xml.bind.Binder", + DefaultConfigurationBuilder.class.getClassLoader()); + + + private final List> messageReaders = new ArrayList<>(); + + private final List> messageWriters = new ArrayList<>(); + + private final List viewResolvers = new ArrayList<>(); + + public void defaultConfiguration() { + messageReader(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); + messageReader(new DecoderHttpMessageReader<>(new StringDecoder())); + messageWriter(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); + messageWriter(new EncoderHttpMessageWriter<>(new CharSequenceEncoder())); + if (jaxb2Present) { + messageReader(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); + messageWriter(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); + } + if (jackson2Present) { + messageReader(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())); + messageWriter(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder())); + } + } + + public void applicationContext(ApplicationContext applicationContext) { + applicationContext.getBeansOfType(HttpMessageReader.class).values().forEach(this::messageReader); + applicationContext.getBeansOfType(HttpMessageWriter.class).values().forEach(this::messageWriter); + applicationContext.getBeansOfType(ViewResolver.class).values().forEach(this::viewResolver); + } + + @Override + public Configuration.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) { + Assert.notNull(messageWriter, "'messageWriter' must not be null"); + this.messageWriters.add(messageWriter); + return this; + } + + @Override + public Configuration.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, + this.viewResolvers); + } + + private static class DefaultConfiguration implements Configuration { + + private final List> messageReaders; + + private final List> messageWriters; + + private final List viewResolvers; + + public DefaultConfiguration( + List> messageReaders, + List> messageWriters, + List viewResolvers) { + this.messageReaders = unmodifiableCopy(messageReaders); + this.messageWriters = unmodifiableCopy(messageWriters); + this.viewResolvers = unmodifiableCopy(viewResolvers); + } + + private static List unmodifiableCopy(List list) { + return Collections.unmodifiableList(new ArrayList<>(list)); + } + + @Override + public Supplier>> messageReaders() { + return this.messageReaders::stream; + } + + @Override + public Supplier>> messageWriters() { + return this.messageWriters::stream; + } + + @Override + public Supplier> viewResolvers() { + return this.viewResolvers::stream; + } + } + +} 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 fdbd9e04f1..0eba31be33 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 @@ -95,7 +95,7 @@ class DefaultRequest implements Request { @Override public Map pathVariables() { - return this.exchange.>getAttribute(Router.URI_TEMPLATE_VARIABLES_ATTRIBUTE). + return this.exchange.>getAttribute(RoutingFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE). orElseGet(Collections::emptyMap); } @@ -186,13 +186,14 @@ class DefaultRequest implements Request { Function, S> readerFunction) { ResolvableType elementType = ResolvableType.forClass(targetClass); MediaType contentType = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM); - return messageReaderStream(exchange) + Supplier>> messageReaderStream = configuration(exchange).messageReaders(); + return messageReaderStream.get() .filter(r -> r.canRead(elementType, contentType, Collections.emptyMap())) .findFirst() .map(CastingUtils::cast) .map(readerFunction) .orElseGet(() -> { - List supportedMediaTypes = messageReaderStream(exchange) + List supportedMediaTypes = messageReaderStream.get() .flatMap(messageReader -> messageReader.getReadableMediaTypes().stream()) .collect(Collectors.toList()); return cast( @@ -200,10 +201,11 @@ class DefaultRequest implements Request { }); } - private Stream> messageReaderStream(ServerWebExchange exchange) { - return exchange.>>>getAttribute(Router.HTTP_MESSAGE_READERS_ATTRIBUTE) - .orElseThrow(() -> new IllegalStateException("Could not find HttpMessageReaders in ServerWebExchange")) - .get(); + private Configuration configuration(ServerWebExchange exchange) { + return exchange.getAttribute( + RoutingFunctions.CONFIGURATION_ATTRIBUTE) + .orElseThrow(() -> new IllegalStateException( + "Could not find Configuration in ServerWebExchange")); } @SuppressWarnings("unchecked") diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponses.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponses.java index c73203b880..1934e956f2 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponses.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/DefaultResponses.java @@ -55,9 +55,9 @@ abstract class DefaultResponses { private static final boolean jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", - DefaultConfiguration.class.getClassLoader()) && + DefaultResponses.class.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", - DefaultConfiguration.class.getClassLoader()); + DefaultResponses.class.getClassLoader()); public static Response empty(int statusCode, HttpHeaders headers) { @@ -134,7 +134,8 @@ abstract class DefaultResponses { exchange -> { MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Locale locale = Locale.ENGLISH; // TODO: resolve locale - return Flux.fromStream(viewResolverStream(exchange)) + Stream viewResolverStream = configuration(exchange).viewResolvers().get(); + return Flux.fromStream(viewResolverStream) .concatMap(viewResolver -> viewResolver.resolveViewName(name, locale)) .next() .otherwiseIfEmpty(Mono.error(new IllegalArgumentException("Could not resolve view with name '" + name +"'"))) @@ -153,9 +154,12 @@ abstract class DefaultResponses { private static Mono writeWithMessageWriters(ServerWebExchange exchange, Publisher body, ResolvableType bodyType) { + + // TODO: use ContentNegotiatingResultHandlerSupport MediaType contentType = exchange.getResponse().getHeaders().getContentType(); ServerHttpResponse response = exchange.getResponse(); - return messageWriterStream(exchange) + Stream> messageWriterStream = configuration(exchange).messageWriters().get(); + return messageWriterStream .filter(messageWriter -> messageWriter.canWrite(bodyType, contentType, Collections .emptyMap())) .findFirst() @@ -168,20 +172,11 @@ abstract class DefaultResponses { }); } - private static Stream> messageWriterStream(ServerWebExchange exchange) { - return exchange.>>>getAttribute( - Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE) + private static Configuration configuration(ServerWebExchange exchange) { + return exchange.getAttribute( + RoutingFunctions.CONFIGURATION_ATTRIBUTE) .orElseThrow(() -> new IllegalStateException( - "Could not find HttpMessageWriters in ServerWebExchange")) - .get(); - } - - private static Stream viewResolverStream(ServerWebExchange exchange) { - return exchange.>>getAttribute( - Router.VIEW_RESOLVERS_ATTRIBUTE) - .orElseThrow(() -> new IllegalStateException( - "Could not find ViewResolvers in ServerWebExchange")) - .get(); + "Could not find Configuration in ServerWebExchange")); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Request.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Request.java index 9ca0b1d7af..10e5e1d0d6 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Request.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Request.java @@ -32,6 +32,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRange; import org.springframework.http.MediaType; +import org.springframework.web.client.reactive.BodyExtractor; /** * Represents an HTTP request, as handled by a {@linkplain HandlerFunction handler function}. @@ -68,6 +69,7 @@ public interface Request { * Return the body of this request. */ Body body(); +// T body(BodyExtractor extractor); /** * Return the request attribute value if present. diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicate.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicate.java index 3c26c7d853..0dfdba8062 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicate.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicate.java @@ -25,8 +25,8 @@ import org.springframework.util.Assert; * @author Arjen Poutsma * @since 5.0 * @see RequestPredicates - * @see Router#route(RequestPredicate, HandlerFunction) - * @see Router#subroute(RequestPredicate, RoutingFunction) + * @see RoutingFunctions#route(RequestPredicate, HandlerFunction) + * @see RoutingFunctions#subroute(RequestPredicate, RoutingFunction) */ @FunctionalInterface public interface RequestPredicate { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicates.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicates.java index aa4033a487..2ee9f9f8c5 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicates.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RequestPredicates.java @@ -249,7 +249,7 @@ public abstract class RequestPredicates { if (request instanceof DefaultRequest) { DefaultRequest defaultRequest = (DefaultRequest) request; Map uriTemplateVariables = this.pathMatcher.extractUriTemplateVariables(this.pattern, path); - defaultRequest.exchange().getAttributes().put(Router.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); + defaultRequest.exchange().getAttributes().put(RoutingFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); } return true; } 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 eaa2b4c662..b653dec879 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 @@ -306,6 +306,8 @@ public interface Response { */ BodyBuilder contentType(MediaType contentType); +// Response body(BodyPopulator populator); + /** * Set the body of the response to the given object and return it. * @@ -322,6 +324,7 @@ public interface Response { * @return the built response */ > Response stream(S publisher, Class elementClass); + // ResolvableType /** * Set the body of the response to the given {@link Resource} and return it. @@ -350,6 +353,7 @@ public interface Response { * @return the built response * @see Server-Sent Events W3C recommendation */ + // remove? > Response sse(S eventsPublisher, Class eventClass); /** diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Router.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RoutingFunctions.java similarity index 69% rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Router.java rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RoutingFunctions.java index ea5b5780f3..6c0b6fde3a 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/Router.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/RoutingFunctions.java @@ -18,18 +18,12 @@ package org.springframework.web.reactive.function; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; import reactor.core.publisher.Mono; -import org.springframework.context.ApplicationContext; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.util.Assert; import org.springframework.web.reactive.HandlerMapping; -import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.HttpWebHandlerAdapter; @@ -54,42 +48,27 @@ import org.springframework.web.server.adapter.HttpWebHandlerAdapter; * @author Arjen Poutsma * @since 5.0 */ -public abstract class Router { +public abstract class RoutingFunctions { private static final HandlerFunction NOT_FOUND_HANDLER = request -> Response.notFound().build(); /** * Name of the {@link ServerWebExchange} attribute that contains the {@link Request}. */ - public static final String REQUEST_ATTRIBUTE = Router.class.getName() + ".request"; + public static final String REQUEST_ATTRIBUTE = RoutingFunctions.class.getName() + ".request"; /** - * Name of the {@link ServerWebExchange} attribute that contains a {@link Supplier} to the - * {@linkplain Stream stream} of {@link HttpMessageReader}s obtained - * from the {@linkplain Configuration#messageReaders() configuration}. + * Name of the {@link ServerWebExchange} attribute that contains the + * {@linkplain Configuration configuration} used throughout the routing and handling of the + * request. */ - public static final String HTTP_MESSAGE_READERS_ATTRIBUTE = Router.class.getName() + ".httpMessageReaders"; - - /** - * Name of the {@link ServerWebExchange} attribute that contains a {@link Supplier} to the - * {@linkplain Stream stream} of {@link HttpMessageWriter}s obtained - * from the {@linkplain Configuration#messageWriters() configuration}. - */ - public static final String HTTP_MESSAGE_WRITERS_ATTRIBUTE = Router.class.getName() + ".httpMessageWriters"; + public static final String CONFIGURATION_ATTRIBUTE = RoutingFunctions.class.getName() + ".configuration"; /** * Name of the {@link ServerWebExchange} attribute that contains the URI * templates map, mapping variable names to values. */ - public static final String URI_TEMPLATE_VARIABLES_ATTRIBUTE = Router.class.getName() + ".uriTemplateVariables"; - - /** - * Name of the {@link ServerWebExchange} attribute that contains the {@link Supplier} to the - * {@linkplain Stream stream} of {@link ViewResolver}s obtained - * from the {@linkplain Configuration#viewResolvers() configuration}. - */ - public static final String VIEW_RESOLVERS_ATTRIBUTE = Router.class.getName() + ".viewResolvers"; - + public static final String URI_TEMPLATE_VARIABLES_ATTRIBUTE = RoutingFunctions.class.getName() + ".uriTemplateVariables"; /** * Route to the given handler function if the given request predicate applies. @@ -133,7 +112,7 @@ public abstract class Router { /** * Converts the given {@linkplain RoutingFunction routing function} into a {@link HttpHandler}. - * This conversion uses the {@linkplain #defaultConfiguration() default configuration}. + * This conversion uses the {@linkplain Configuration#defaultBuilder() default configuration}. * *

The returned {@code HttpHandler} can be adapted to run in * {@linkplain org.springframework.http.server.reactive.ServletHttpHandlerAdapter Servlet 3.1+}, @@ -178,7 +157,7 @@ public abstract class Router { /** * Converts the given {@linkplain RoutingFunction routing function} into a {@link HandlerMapping}. - * This conversion uses the {@linkplain #defaultConfiguration() default configuration}. + * This conversion uses the {@linkplain Configuration#defaultBuilder() default configuration}. * *

The returned {@code HttpHandler} can be run in a * {@link org.springframework.web.reactive.DispatcherHandler}. @@ -217,13 +196,15 @@ public abstract class Router { }; } + private static Configuration defaultConfiguration() { + return Configuration.defaultBuilder().build(); + } + private static void addAttributes(ServerWebExchange exchange, Request request, Configuration configuration) { Map attributes = exchange.getAttributes(); attributes.put(REQUEST_ATTRIBUTE, request); - attributes.put(HTTP_MESSAGE_READERS_ATTRIBUTE, configuration.messageReaders()); - attributes.put(HTTP_MESSAGE_WRITERS_ATTRIBUTE, configuration.messageWriters()); - attributes.put(VIEW_RESOLVERS_ATTRIBUTE, configuration.viewResolvers()); + attributes.put(CONFIGURATION_ATTRIBUTE, configuration); } @SuppressWarnings("unchecked") @@ -231,69 +212,4 @@ public abstract class Router { return (HandlerFunction) NOT_FOUND_HANDLER; } - - /** - * Return the default configuration. - */ - public static Configuration defaultConfiguration() { - return new DefaultConfiguration(); - } - - /** - * Returns a configuration based on the given {@linkplain ApplicationContext application context}. - * This configuration will search for all {@link HttpMessageReader} and {@link HttpMessageWriter} - * instances in the given application context. - * @param applicationContext the application context to base the configuration on - * @return the configuration - */ - public static Configuration toConfiguration(ApplicationContext applicationContext) { - return new Configuration() { - - @Override - public Supplier>> messageReaders() { - return () -> applicationContext.getBeansOfType(HttpMessageReader.class).values().stream() - .map(CastingUtils::cast); - } - - @Override - public Supplier>> messageWriters() { - return () -> applicationContext.getBeansOfType(HttpMessageWriter.class).values().stream() - .map(CastingUtils::cast); - } - - @Override - public Supplier> viewResolvers() { - return () -> applicationContext.getBeansOfType(ViewResolver.class).values().stream(); - } - }; - } - - - /** - * Defines the configuration to be used by this {@code Router}. - */ - public interface Configuration { - - /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageReader}s to be used for request - * body conversion. - * @return the stream of message readers - */ - Supplier>> messageReaders(); - - /** - * Supply a {@linkplain Stream stream} of {@link HttpMessageWriter}s to be used for response - * body conversion. - * @return the stream of message writers - */ - Supplier>> messageWriters(); - - /** - * Supply a {@linkplain Stream stream} of {@link ViewResolver}s to be used for view name - * resolution. - * @return the stream of view resolvers - */ - Supplier> viewResolvers(); - } - } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/HandlerFunctionAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/HandlerFunctionAdapter.java index 0a8f7961fd..c777502caa 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/HandlerFunctionAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/support/HandlerFunctionAdapter.java @@ -26,7 +26,7 @@ import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.function.HandlerFunction; import org.springframework.web.reactive.function.Request; import org.springframework.web.reactive.function.Response; -import org.springframework.web.reactive.function.Router; +import org.springframework.web.reactive.function.RoutingFunctions; import org.springframework.web.server.ServerWebExchange; /** @@ -58,7 +58,7 @@ public class HandlerFunctionAdapter implements HandlerAdapter { public Mono handle(ServerWebExchange exchange, Object handler) { HandlerFunction handlerFunction = (HandlerFunction) handler; Request request = - exchange.getAttribute(Router.REQUEST_ATTRIBUTE) + exchange.getAttribute(RoutingFunctions.REQUEST_ATTRIBUTE) .orElseThrow(() -> new IllegalStateException("Could not find Request in exchange attributes")); Response response = handlerFunction.handle(request); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/AbstractRoutingFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/AbstractRoutingFunctionIntegrationTests.java index def736f3be..0dcaf4a580 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/AbstractRoutingFunctionIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/AbstractRoutingFunctionIntegrationTests.java @@ -28,7 +28,7 @@ public abstract class AbstractRoutingFunctionIntegrationTests @Override protected final HttpHandler createHttpHandler() { RoutingFunction routingFunction = routingFunction(); - return Router.toHttpHandler(routingFunction); + return RoutingFunctions.toHttpHandler(routingFunction); } protected abstract RoutingFunction routingFunction(); 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/ConfigurationTests.java new file mode 100644 index 0000000000..10270d7aac --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/ConfigurationTests.java @@ -0,0 +1,105 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.reactive.function; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.context.support.StaticApplicationContext; +import org.springframework.core.ResolvableType; +import org.springframework.http.MediaType; +import org.springframework.http.ReactiveHttpInputMessage; +import org.springframework.http.ReactiveHttpOutputMessage; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; + +import static org.junit.Assert.assertTrue; + +/** + * @author Arjen Poutsma + */ +public class ConfigurationTests { + + @Test + public void toConfiguration() throws Exception { + StaticApplicationContext applicationContext = new StaticApplicationContext(); + applicationContext.registerSingleton("messageWriter", DummyMessageWriter.class); + applicationContext.registerSingleton("messageReader", DummyMessageReader.class); + applicationContext.refresh(); + + Configuration configuration = Configuration.toConfiguration(applicationContext); + assertTrue(configuration.messageReaders().get() + .allMatch(r -> r instanceof DummyMessageReader)); + assertTrue(configuration.messageWriters().get() + .allMatch(r -> r instanceof DummyMessageWriter)); + + } + + + private static class DummyMessageWriter implements HttpMessageWriter { + + @Override + public boolean canWrite(ResolvableType type, MediaType mediaType, Map hints) { + return false; + } + + @Override + public List getWritableMediaTypes() { + return Collections.emptyList(); + } + + @Override + public Mono write(Publisher inputStream, ResolvableType type, + MediaType contentType, + ReactiveHttpOutputMessage outputMessage, + Map hints) { + return Mono.empty(); + } + } + + private static class DummyMessageReader implements HttpMessageReader { + + @Override + public boolean canRead(ResolvableType type, MediaType mediaType, Map hints) { + return false; + } + + @Override + public List getReadableMediaTypes() { + return Collections.emptyList(); + } + + @Override + public Flux read(ResolvableType type, ReactiveHttpInputMessage inputMessage, + Map hints) { + return Flux.empty(); + } + + @Override + public Mono readMono(ResolvableType type, ReactiveHttpInputMessage inputMessage, + Map hints) { + return Mono.empty(); + } + } +} + diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultConfigurationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultConfigurationTests.java deleted file mode 100644 index 12a6ce444a..0000000000 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/DefaultConfigurationTests.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.reactive.function; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Arjen Poutsma - */ -public class DefaultConfigurationTests { - - private DefaultConfiguration configuration = new DefaultConfiguration(); - - @Test - public void messageReaders() throws Exception { - assertEquals(4, configuration.messageReaders().get().count()); - } - - @Test - public void messageWriters() throws Exception { - assertEquals(4, configuration.messageWriters().get().count()); - } - -} \ No newline at end of file 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 c415fe9d84..f5acad0a35 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 @@ -115,7 +115,7 @@ public class DefaultRequestTests { @Test public void pathVariables() throws Exception { Map pathVariables = Collections.singletonMap("foo", "bar"); - when(mockExchange.getAttribute(Router.URI_TEMPLATE_VARIABLES_ATTRIBUTE)).thenReturn(Optional.of(pathVariables)); + when(mockExchange.getAttribute(RoutingFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE)).thenReturn(Optional.of(pathVariables)); assertEquals(pathVariables, defaultRequest.pathVariables()); } @@ -161,9 +161,10 @@ public class DefaultRequestTests { Set> messageReaders = Collections .singleton(new DecoderHttpMessageReader(new StringDecoder())); - when(mockExchange.getAttribute(Router.HTTP_MESSAGE_READERS_ATTRIBUTE)) - .thenReturn(Optional.of( - (Supplier>>) messageReaders::stream)); + Configuration mockConfig = mock(Configuration.class); + when(mockConfig.messageReaders()).thenReturn(messageReaders::stream); + when(mockExchange.getAttribute(RoutingFunctions.CONFIGURATION_ATTRIBUTE)) + .thenReturn(Optional.of(mockConfig)); assertEquals(body, defaultRequest.body().stream()); 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 01acfccb94..69e11372a7 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 @@ -18,7 +18,9 @@ package org.springframework.web.reactive.function; import java.net.URI; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -218,11 +220,13 @@ public class DefaultResponseBuilderTests { MockServerHttpResponse response = new MockServerHttpResponse(); ServerWebExchange exchange = new DefaultServerWebExchange(request, response, new MockWebSessionManager()); - Set> - messageWriters = Collections - .singleton(new EncoderHttpMessageWriter(new CharSequenceEncoder())); - exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE, - (Supplier>>) messageWriters::stream); + + List> messageWriters = new ArrayList<>(); + messageWriters.add(new EncoderHttpMessageWriter(new CharSequenceEncoder())); + + Configuration mockConfig = mock(Configuration.class); + when(mockConfig.messageWriters()).thenReturn(messageWriters::stream); + exchange.getAttributes().put(RoutingFunctions.CONFIGURATION_ATTRIBUTE, mockConfig); result.writeTo(exchange).block(); assertNotNull(response.getBody()); @@ -239,11 +243,13 @@ public class DefaultResponseBuilderTests { MockServerHttpResponse response = new MockServerHttpResponse(); ServerWebExchange exchange = new DefaultServerWebExchange(request, response, new MockWebSessionManager()); - Set> - messageWriters = Collections - .singleton(new EncoderHttpMessageWriter(new CharSequenceEncoder())); - exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE, - (Supplier>>) messageWriters::stream); + + List> messageWriters = new ArrayList<>(); + messageWriters.add(new EncoderHttpMessageWriter(new CharSequenceEncoder())); + + Configuration mockConfig = mock(Configuration.class); + when(mockConfig.messageWriters()).thenReturn(messageWriters::stream); + exchange.getAttributes().put(RoutingFunctions.CONFIGURATION_ATTRIBUTE, mockConfig); result.writeTo(exchange).block(); assertEquals(HttpStatus.NOT_ACCEPTABLE, response.getStatusCode()); @@ -259,10 +265,13 @@ public class DefaultResponseBuilderTests { MockServerHttpResponse response = new MockServerHttpResponse(); ServerWebExchange exchange = new DefaultServerWebExchange(request, response, new MockWebSessionManager()); - Set> messageWriters = Collections - .singleton(new EncoderHttpMessageWriter(new CharSequenceEncoder())); - exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE, - (Supplier>>) messageWriters::stream); + + List> messageWriters = new ArrayList<>(); + messageWriters.add(new EncoderHttpMessageWriter(new CharSequenceEncoder())); + + Configuration mockConfig = mock(Configuration.class); + when(mockConfig.messageWriters()).thenReturn(messageWriters::stream); + exchange.getAttributes().put(RoutingFunctions.CONFIGURATION_ATTRIBUTE, mockConfig); result.writeTo(exchange).block(); assertNotNull(response.getBody()); @@ -311,10 +320,13 @@ public class DefaultResponseBuilderTests { View view = mock(View.class); when(viewResolver.resolveViewName("view", Locale.ENGLISH)).thenReturn(Mono.just(view)); when(view.render(model, null, exchange)).thenReturn(Mono.empty()); - exchange.getAttributes().put(Router.VIEW_RESOLVERS_ATTRIBUTE, - (Supplier>) () -> Collections - .singleton(viewResolver).stream()); + List viewResolvers = new ArrayList<>(); + viewResolvers.add(viewResolver); + + Configuration mockConfig = mock(Configuration.class); + when(mockConfig.viewResolvers()).thenReturn(viewResolvers::stream); + exchange.getAttributes().put(RoutingFunctions.CONFIGURATION_ATTRIBUTE, mockConfig); result.writeTo(exchange).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 bd94eca51f..33a1f9a726 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 @@ -50,7 +50,7 @@ import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; import static org.junit.Assert.assertEquals; -import static org.springframework.web.reactive.function.Router.route; +import static org.springframework.web.reactive.function.RoutingFunctions.route; /** * Tests the use of {@link HandlerFunction} and {@link RoutingFunction} in a @@ -119,8 +119,8 @@ public class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegr @Bean public HandlerMapping handlerMapping(RoutingFunction routingFunction, ApplicationContext applicationContext) { - return Router.toHandlerMapping(routingFunction, - new Router.Configuration() { + return RoutingFunctions.toHandlerMapping(routingFunction, + new org.springframework.web.reactive.function.Configuration() { @Override public Supplier>> messageReaders() { return () -> getMessageReaders().stream(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/PublisherHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/PublisherHandlerFunctionIntegrationTests.java index de93778147..b46e63a9f1 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/PublisherHandlerFunctionIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/PublisherHandlerFunctionIntegrationTests.java @@ -35,7 +35,7 @@ import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertEquals; import static org.springframework.web.reactive.function.RequestPredicates.GET; import static org.springframework.web.reactive.function.RequestPredicates.POST; -import static org.springframework.web.reactive.function.Router.route; +import static org.springframework.web.reactive.function.RoutingFunctions.route; /** * @author Arjen Poutsma diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterTests.java index f6a8b88b9e..b790287beb 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/RouterTests.java @@ -57,7 +57,7 @@ public class RouterTests { RequestPredicate requestPredicate = mock(RequestPredicate.class); when(requestPredicate.test(request)).thenReturn(true); - RoutingFunction result = Router.route(requestPredicate, handlerFunction); + RoutingFunction result = RoutingFunctions.route(requestPredicate, handlerFunction); assertNotNull(result); Optional> resultHandlerFunction = result.route(request); @@ -73,7 +73,7 @@ public class RouterTests { RequestPredicate requestPredicate = mock(RequestPredicate.class); when(requestPredicate.test(request)).thenReturn(false); - RoutingFunction result = Router.route(requestPredicate, handlerFunction); + RoutingFunction result = RoutingFunctions.route(requestPredicate, handlerFunction); assertNotNull(result); Optional> resultHandlerFunction = result.route(request); @@ -89,7 +89,7 @@ public class RouterTests { RequestPredicate requestPredicate = mock(RequestPredicate.class); when(requestPredicate.test(request)).thenReturn(true); - RoutingFunction result = Router.subroute(requestPredicate, routingFunction); + RoutingFunction result = RoutingFunctions.subroute(requestPredicate, routingFunction); assertNotNull(result); Optional> resultHandlerFunction = result.route(request); @@ -106,7 +106,7 @@ public class RouterTests { RequestPredicate requestPredicate = mock(RequestPredicate.class); when(requestPredicate.test(request)).thenReturn(false); - RoutingFunction result = Router.subroute(requestPredicate, routingFunction); + RoutingFunction result = RoutingFunctions.subroute(requestPredicate, routingFunction); assertNotNull(result); Optional> resultHandlerFunction = result.route(request); @@ -128,7 +128,7 @@ public class RouterTests { RequestPredicate requestPredicate = mock(RequestPredicate.class); when(requestPredicate.test(request)).thenReturn(false); - Router.Configuration configuration = mock(Router.Configuration.class); + Configuration configuration = mock(Configuration.class); when(configuration.messageReaders()).thenReturn( () -> Collections.>emptyList().stream()); when(configuration.messageWriters()).thenReturn( @@ -136,72 +136,13 @@ public class RouterTests { when(configuration.viewResolvers()).thenReturn( () -> Collections.emptyList().stream()); - HttpHandler result = Router.toHttpHandler(routingFunction, configuration); + HttpHandler result = RoutingFunctions.toHttpHandler(routingFunction, configuration); assertNotNull(result); - MockServerHttpRequest httpRequest = new MockServerHttpRequest(HttpMethod.GET, "http://localhost"); + MockServerHttpRequest httpRequest = + new MockServerHttpRequest(HttpMethod.GET, "http://localhost"); MockServerHttpResponse serverHttpResponse = new MockServerHttpResponse(); result.handle(httpRequest, serverHttpResponse); } - @Test - public void toConfiguration() throws Exception { - StaticApplicationContext applicationContext = new StaticApplicationContext(); - applicationContext.registerSingleton("messageWriter", DummyMessageWriter.class); - applicationContext.registerSingleton("messageReader", DummyMessageReader.class); - applicationContext.refresh(); - - Router.Configuration configuration = Router.toConfiguration(applicationContext); - assertTrue(configuration.messageReaders().get() - .allMatch(r -> r instanceof DummyMessageReader)); - assertTrue(configuration.messageWriters().get() - .allMatch(r -> r instanceof DummyMessageWriter)); - - } - - private static class DummyMessageWriter implements HttpMessageWriter { - - @Override - public boolean canWrite(ResolvableType elementType, MediaType mediaType, Map hints) { - return false; - } - - @Override - public List getWritableMediaTypes() { - return Collections.emptyList(); - } - - @Override - public Mono write(Publisher inputStream, ResolvableType elementType, - MediaType mediaType, - ReactiveHttpOutputMessage outputMessage, - Map hints) { - return Mono.empty(); - } - } - - private static class DummyMessageReader implements HttpMessageReader { - - @Override - public boolean canRead(ResolvableType elementType, MediaType mediaType, Map hints) { - return false; - } - - @Override - public List getReadableMediaTypes() { - return Collections.emptyList(); - } - - @Override - public Flux read(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, - Map hints) { - return Flux.empty(); - } - - @Override - public Mono readMono(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, - Map hints) { - return Mono.empty(); - } - } -} \ No newline at end of file +} diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java index 0bc85aa39e..e61636a96d 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java @@ -32,7 +32,7 @@ import org.springframework.web.client.reactive.WebClient; import static org.springframework.web.client.reactive.ClientWebRequestBuilders.get; import static org.springframework.web.client.reactive.ResponseExtractors.bodyStream; -import static org.springframework.web.reactive.function.Router.route; +import static org.springframework.web.reactive.function.RoutingFunctions.route; /** * @author Arjen Poutsma