Add EnableWebReactive + WebReactiveConfigurer
This commit improves the existing web reactive configuration infrastructure with the following changes: * renamed `WebReactiveConfiguration` to `WebReactiveConfigurationSupport` and is is no longer a Configuration class * created the `WebReactiveConfigurer` interface; Configuration classes implementing it will augment the web reactive configuration support * created the `DelegatingWebReactiveConfiguration` and `WebReactiveConfigurerComposite` to effectively tie those custom-defined configurers to the main configuration support * created the `@EnableWebReactive` to active that support in configuration classes Issue: SPR-14754
This commit is contained in:
committed by
Rossen Stoyanchev
parent
ea319345ed
commit
3533024ab8
@@ -0,0 +1,128 @@
|
||||
package org.springframework.web.reactive.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.codec.HttpMessageWriter;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link DelegatingWebReactiveConfiguration} tests.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class DelegatingWebReactiveConfigurationTests {
|
||||
|
||||
private DelegatingWebReactiveConfiguration delegatingConfig;
|
||||
|
||||
@Mock
|
||||
private WebReactiveConfigurer webReactiveConfigurer;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<List<HttpMessageReader<?>>> readers;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<List<HttpMessageWriter<?>>> writers;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<FormatterRegistry> formatterRegistry;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
delegatingConfig = new DelegatingWebReactiveConfiguration();
|
||||
delegatingConfig.setApplicationContext(new StaticApplicationContext());
|
||||
given(webReactiveConfigurer.createRequestMappingHandlerMapping()).willReturn(Optional.empty());
|
||||
given(webReactiveConfigurer.createRequestMappingHandlerAdapter()).willReturn(Optional.empty());
|
||||
given(webReactiveConfigurer.getValidator()).willReturn(Optional.empty());
|
||||
given(webReactiveConfigurer.getMessageCodesResolver()).willReturn(Optional.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webReactiveConfigurer));
|
||||
RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter();
|
||||
|
||||
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
|
||||
ConversionService initializerConversionService = initializer.getConversionService();
|
||||
assertTrue(initializer.getValidator() instanceof LocalValidatorFactoryBean);
|
||||
|
||||
verify(webReactiveConfigurer).createRequestMappingHandlerAdapter();
|
||||
verify(webReactiveConfigurer).configureMessageReaders(readers.capture());
|
||||
verify(webReactiveConfigurer).extendMessageReaders(readers.capture());
|
||||
verify(webReactiveConfigurer).getValidator();
|
||||
verify(webReactiveConfigurer).getMessageCodesResolver();
|
||||
verify(webReactiveConfigurer).addFormatters(formatterRegistry.capture());
|
||||
verify(webReactiveConfigurer).addArgumentResolvers(any());
|
||||
|
||||
assertSame(formatterRegistry.getValue(), initializerConversionService);
|
||||
assertEquals(5, readers.getValue().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerMapping() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webReactiveConfigurer));
|
||||
delegatingConfig.requestMappingHandlerMapping();
|
||||
|
||||
verify(webReactiveConfigurer).createRequestMappingHandlerMapping();
|
||||
verify(webReactiveConfigurer).configureRequestedContentTypeResolver(any(RequestedContentTypeResolverBuilder.class));
|
||||
verify(webReactiveConfigurer).addCorsMappings(any(CorsRegistry.class));
|
||||
verify(webReactiveConfigurer).configurePathMatching(any(PathMatchConfigurer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceHandlerMapping() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webReactiveConfigurer));
|
||||
doAnswer(invocation -> {
|
||||
ResourceHandlerRegistry registry = invocation.getArgumentAt(0, ResourceHandlerRegistry.class);
|
||||
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static");
|
||||
return null;
|
||||
}).when(webReactiveConfigurer).addResourceHandlers(any(ResourceHandlerRegistry.class));
|
||||
|
||||
delegatingConfig.resourceHandlerMapping();
|
||||
verify(webReactiveConfigurer).addResourceHandlers(any(ResourceHandlerRegistry.class));
|
||||
verify(webReactiveConfigurer).configurePathMatching(any(PathMatchConfigurer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseBodyResultHandler() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webReactiveConfigurer));
|
||||
delegatingConfig.responseBodyResultHandler();
|
||||
|
||||
verify(webReactiveConfigurer).configureMessageWriters(writers.capture());
|
||||
verify(webReactiveConfigurer).extendMessageWriters(writers.capture());
|
||||
verify(webReactiveConfigurer).configureRequestedContentTypeResolver(any(RequestedContentTypeResolverBuilder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viewResolutionResultHandler() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webReactiveConfigurer));
|
||||
delegatingConfig.viewResolutionResultHandler();
|
||||
|
||||
verify(webReactiveConfigurer).configureViewResolvers(any(ViewResolverRegistry.class));
|
||||
}
|
||||
}
|
||||
@@ -80,10 +80,10 @@ import static org.springframework.http.MediaType.IMAGE_PNG;
|
||||
import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WebReactiveConfiguration}.
|
||||
* Unit tests for {@link WebReactiveConfigurationSupport}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class WebReactiveConfigurationTests {
|
||||
public class WebReactiveConfigurationSupportTests {
|
||||
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
@@ -100,7 +100,7 @@ public class WebReactiveConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerMapping() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
ApplicationContext context = loadConfig(WebReactiveConfig.class);
|
||||
|
||||
String name = "requestMappingHandlerMapping";
|
||||
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
|
||||
@@ -138,10 +138,10 @@ public class WebReactiveConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
ApplicationContext context = loadConfig(WebReactiveConfig.class);
|
||||
|
||||
String name = "requestMappingHandlerAdapter";
|
||||
RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class);
|
||||
RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class);
|
||||
assertNotNull(adapter);
|
||||
|
||||
List<HttpMessageReader<?>> readers = adapter.getMessageReaders();
|
||||
@@ -185,7 +185,7 @@ public class WebReactiveConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void responseEntityResultHandler() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
ApplicationContext context = loadConfig(WebReactiveConfig.class);
|
||||
|
||||
String name = "responseEntityResultHandler";
|
||||
ResponseEntityResultHandler handler = context.getBean(name, ResponseEntityResultHandler.class);
|
||||
@@ -210,7 +210,7 @@ public class WebReactiveConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void responseBodyResultHandler() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
ApplicationContext context = loadConfig(WebReactiveConfig.class);
|
||||
|
||||
String name = "responseBodyResultHandler";
|
||||
ResponseBodyResultHandler handler = context.getBean(name, ResponseBodyResultHandler.class);
|
||||
@@ -262,7 +262,7 @@ public class WebReactiveConfigurationTests {
|
||||
AbstractHandlerMapping handlerMapping = context.getBean(name, AbstractHandlerMapping.class);
|
||||
assertNotNull(handlerMapping);
|
||||
|
||||
assertEquals(Ordered.LOWEST_PRECEDENCE -1, handlerMapping.getOrder());
|
||||
assertEquals(Ordered.LOWEST_PRECEDENCE - 1, handlerMapping.getOrder());
|
||||
|
||||
assertNotNull(handlerMapping.getPathHelper());
|
||||
assertNotNull(handlerMapping.getPathMatcher());
|
||||
@@ -296,9 +296,12 @@ public class WebReactiveConfigurationTests {
|
||||
return context;
|
||||
}
|
||||
|
||||
@EnableWebReactive
|
||||
static class WebReactiveConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomPatchMatchConfig extends WebReactiveConfiguration {
|
||||
static class CustomPatchMatchConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
public void configurePathMatching(PathMatchConfigurer configurer) {
|
||||
@@ -308,7 +311,7 @@ public class WebReactiveConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomMessageConverterConfig extends WebReactiveConfiguration {
|
||||
static class CustomMessageConverterConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected void configureMessageReaders(List<HttpMessageReader<?>> messageReaders) {
|
||||
@@ -331,8 +334,9 @@ public class WebReactiveConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration @SuppressWarnings("unused")
|
||||
static class CustomViewResolverConfig extends WebReactiveConfiguration {
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
static class CustomViewResolverConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
@@ -348,7 +352,7 @@ public class WebReactiveConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomResourceHandlingConfig extends WebReactiveConfiguration {
|
||||
static class CustomResourceHandlingConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
@@ -43,7 +43,7 @@ import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.HandlerAdapter;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfigurationSupport;
|
||||
import org.springframework.web.reactive.function.support.HandlerFunctionAdapter;
|
||||
import org.springframework.web.reactive.function.support.ResponseResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
@@ -104,7 +104,7 @@ public class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegr
|
||||
|
||||
|
||||
@Configuration
|
||||
static class TestConfiguration extends WebReactiveConfiguration {
|
||||
static class TestConfiguration extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Bean
|
||||
public PersonHandler personHandler() {
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -222,9 +222,10 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebReactive
|
||||
@ComponentScan(resourcePattern = "**/CrossOriginAnnotationIntegrationTests*")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig {
|
||||
}
|
||||
|
||||
@RestController @SuppressWarnings("unused")
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.config.CorsRegistry;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfigurationSupport;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -137,7 +137,7 @@ public class GlobalCorsConfigIntegrationTests extends AbstractRequestMappingInte
|
||||
@Configuration
|
||||
@ComponentScan(resourcePattern = "**/GlobalCorsConfigIntegrationTests*.class")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected void addCorsMappings(CorsRegistry registry) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
@@ -93,8 +93,9 @@ public class JacksonHintsIntegrationTests extends AbstractRequestMappingIntegrat
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(resourcePattern = "**/JacksonHintsIntegrationTests*.class")
|
||||
@EnableWebReactive
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig {
|
||||
}
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -64,9 +64,10 @@ public class RequestMappingExceptionHandlingIntegrationTests extends AbstractReq
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebReactive
|
||||
@ComponentScan(resourcePattern = "**/RequestMappingExceptionHandlingIntegrationTests$*.class")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -74,9 +74,10 @@ public class RequestMappingIntegrationTests extends AbstractRequestMappingIntegr
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebReactive
|
||||
@ComponentScan(resourcePattern = "**/RequestMappingIntegrationTests$*.class")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig {
|
||||
}
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -56,11 +56,12 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.http.MediaType.*;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.MediaType.APPLICATION_XML;
|
||||
|
||||
/**
|
||||
* {@code @RequestMapping} integration tests focusing on serialization and
|
||||
@@ -371,9 +372,10 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebReactive
|
||||
@ComponentScan(resourcePattern = "**/RequestMappingMessageConversionIntegrationTests$*.class")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.reactive.config.ViewResolverRegistry;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfigurationSupport;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigurer;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class RequestMappingViewResolutionIntegrationTests extends AbstractReques
|
||||
@Configuration
|
||||
@ComponentScan(resourcePattern = "**/RequestMappingViewResolutionIntegrationTests$*.class")
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
static class WebConfig extends WebReactiveConfiguration {
|
||||
static class WebConfig extends WebReactiveConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.reactive.WebClient;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.config.EnableWebReactive;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import static org.springframework.web.client.reactive.ClientWebRequestBuilders.get;
|
||||
@@ -163,8 +163,9 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebReactive
|
||||
@SuppressWarnings("unused")
|
||||
static class TestConfiguration extends WebReactiveConfiguration {
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public SseController sseController() {
|
||||
|
||||
Reference in New Issue
Block a user