Refactor Router to RoutingFunctions
This commit refactors the Router into a RoutingFunctions class, by: - Renaming the class :) - Moving all Configuration logic into a separate, top-level Configuration class with mutable builder.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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<Object> {
|
||||
|
||||
@Override
|
||||
public boolean canWrite(ResolvableType type, MediaType mediaType, Map<String, Object> hints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getWritableMediaTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> write(Publisher<?> inputStream, ResolvableType type,
|
||||
MediaType contentType,
|
||||
ReactiveHttpOutputMessage outputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummyMessageReader implements HttpMessageReader<Object> {
|
||||
|
||||
@Override
|
||||
public boolean canRead(ResolvableType type, MediaType mediaType, Map<String, Object> hints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getReadableMediaTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Object> read(ResolvableType type, ReactiveHttpInputMessage inputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> readMono(ResolvableType type, ReactiveHttpInputMessage inputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public class DefaultRequestTests {
|
||||
@Test
|
||||
public void pathVariables() throws Exception {
|
||||
Map<String, String> 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<HttpMessageReader<?>> messageReaders = Collections
|
||||
.singleton(new DecoderHttpMessageReader<String>(new StringDecoder()));
|
||||
when(mockExchange.getAttribute(Router.HTTP_MESSAGE_READERS_ATTRIBUTE))
|
||||
.thenReturn(Optional.of(
|
||||
(Supplier<Stream<HttpMessageReader<?>>>) 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());
|
||||
|
||||
|
||||
@@ -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<HttpMessageWriter<?>>
|
||||
messageWriters = Collections
|
||||
.singleton(new EncoderHttpMessageWriter<CharSequence>(new CharSequenceEncoder()));
|
||||
exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE,
|
||||
(Supplier<Stream<HttpMessageWriter<?>>>) messageWriters::stream);
|
||||
|
||||
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
|
||||
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(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<HttpMessageWriter<?>>
|
||||
messageWriters = Collections
|
||||
.singleton(new EncoderHttpMessageWriter<CharSequence>(new CharSequenceEncoder()));
|
||||
exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE,
|
||||
(Supplier<Stream<HttpMessageWriter<?>>>) messageWriters::stream);
|
||||
|
||||
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
|
||||
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(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<HttpMessageWriter<?>> messageWriters = Collections
|
||||
.singleton(new EncoderHttpMessageWriter<CharSequence>(new CharSequenceEncoder()));
|
||||
exchange.getAttributes().put(Router.HTTP_MESSAGE_WRITERS_ATTRIBUTE,
|
||||
(Supplier<Stream<HttpMessageWriter<?>>>) messageWriters::stream);
|
||||
|
||||
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
|
||||
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(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<Stream<ViewResolver>>) () -> Collections
|
||||
.singleton(viewResolver).stream());
|
||||
|
||||
List<ViewResolver> 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();
|
||||
}
|
||||
|
||||
@@ -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<Stream<HttpMessageReader<?>>> messageReaders() {
|
||||
return () -> getMessageReaders().stream();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,7 +57,7 @@ public class RouterTests {
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
when(requestPredicate.test(request)).thenReturn(true);
|
||||
|
||||
RoutingFunction<Void> result = Router.route(requestPredicate, handlerFunction);
|
||||
RoutingFunction<Void> result = RoutingFunctions.route(requestPredicate, handlerFunction);
|
||||
assertNotNull(result);
|
||||
|
||||
Optional<HandlerFunction<Void>> resultHandlerFunction = result.route(request);
|
||||
@@ -73,7 +73,7 @@ public class RouterTests {
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
when(requestPredicate.test(request)).thenReturn(false);
|
||||
|
||||
RoutingFunction<Void> result = Router.route(requestPredicate, handlerFunction);
|
||||
RoutingFunction<Void> result = RoutingFunctions.route(requestPredicate, handlerFunction);
|
||||
assertNotNull(result);
|
||||
|
||||
Optional<HandlerFunction<Void>> resultHandlerFunction = result.route(request);
|
||||
@@ -89,7 +89,7 @@ public class RouterTests {
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
when(requestPredicate.test(request)).thenReturn(true);
|
||||
|
||||
RoutingFunction<Void> result = Router.subroute(requestPredicate, routingFunction);
|
||||
RoutingFunction<Void> result = RoutingFunctions.subroute(requestPredicate, routingFunction);
|
||||
assertNotNull(result);
|
||||
|
||||
Optional<HandlerFunction<Void>> resultHandlerFunction = result.route(request);
|
||||
@@ -106,7 +106,7 @@ public class RouterTests {
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
when(requestPredicate.test(request)).thenReturn(false);
|
||||
|
||||
RoutingFunction<Void> result = Router.subroute(requestPredicate, routingFunction);
|
||||
RoutingFunction<Void> result = RoutingFunctions.subroute(requestPredicate, routingFunction);
|
||||
assertNotNull(result);
|
||||
|
||||
Optional<HandlerFunction<Void>> 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.<HttpMessageReader<?>>emptyList().stream());
|
||||
when(configuration.messageWriters()).thenReturn(
|
||||
@@ -136,72 +136,13 @@ public class RouterTests {
|
||||
when(configuration.viewResolvers()).thenReturn(
|
||||
() -> Collections.<ViewResolver>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<Object> {
|
||||
|
||||
@Override
|
||||
public boolean canWrite(ResolvableType elementType, MediaType mediaType, Map<String, Object> hints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getWritableMediaTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> write(Publisher<?> inputStream, ResolvableType elementType,
|
||||
MediaType mediaType,
|
||||
ReactiveHttpOutputMessage outputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummyMessageReader implements HttpMessageReader<Object> {
|
||||
|
||||
@Override
|
||||
public boolean canRead(ResolvableType elementType, MediaType mediaType, Map<String, Object> hints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getReadableMediaTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Object> read(ResolvableType elementType, ReactiveHttpInputMessage inputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> readMono(ResolvableType elementType, ReactiveHttpInputMessage inputMessage,
|
||||
Map<String, Object> hints) {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user