17 changed files with 731 additions and 43 deletions
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
/* |
||||
* 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.config; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.format.FormatterRegistry; |
||||
import org.springframework.http.codec.HttpMessageReader; |
||||
import org.springframework.http.codec.HttpMessageWriter; |
||||
import org.springframework.util.CollectionUtils; |
||||
import org.springframework.validation.MessageCodesResolver; |
||||
import org.springframework.validation.Validator; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; |
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; |
||||
|
||||
/** |
||||
* A subclass of {@code WebReactiveConfigurationSupport} that detects and delegates |
||||
* to all beans of type {@link WebReactiveConfigurer} allowing them to customize the |
||||
* configuration provided by {@code WebReactiveConfigurationSupport}. This is the |
||||
* class actually imported by {@link EnableWebReactive @EnableWebReactive}. |
||||
* |
||||
* @author Brian Clozel |
||||
* @since 5.0 |
||||
*/ |
||||
@Configuration |
||||
public class DelegatingWebReactiveConfiguration extends WebReactiveConfigurationSupport { |
||||
|
||||
private final WebReactiveConfigurerComposite configurers = new WebReactiveConfigurerComposite(); |
||||
|
||||
@Autowired(required = false) |
||||
public void setConfigurers(List<WebReactiveConfigurer> configurers) { |
||||
if (!CollectionUtils.isEmpty(configurers)) { |
||||
this.configurers.addWebReactiveConfigurers(configurers); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { |
||||
return this.configurers.createRequestMappingHandlerMapping() |
||||
.orElse(super.createRequestMappingHandlerMapping()); |
||||
} |
||||
|
||||
@Override |
||||
protected void configureRequestedContentTypeResolver(RequestedContentTypeResolverBuilder builder) { |
||||
this.configurers.configureRequestedContentTypeResolver(builder); |
||||
} |
||||
|
||||
@Override |
||||
protected void addCorsMappings(CorsRegistry registry) { |
||||
this.configurers.addCorsMappings(registry); |
||||
} |
||||
|
||||
@Override |
||||
public void configurePathMatching(PathMatchConfigurer configurer) { |
||||
this.configurers.configurePathMatching(configurer); |
||||
} |
||||
|
||||
@Override |
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) { |
||||
this.configurers.addResourceHandlers(registry); |
||||
} |
||||
|
||||
@Override |
||||
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { |
||||
return this.configurers.createRequestMappingHandlerAdapter() |
||||
.orElse(super.createRequestMappingHandlerAdapter()); |
||||
} |
||||
|
||||
@Override |
||||
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
||||
this.configurers.addArgumentResolvers(resolvers); |
||||
} |
||||
|
||||
@Override |
||||
protected void configureMessageReaders(List<HttpMessageReader<?>> messageReaders) { |
||||
this.configurers.configureMessageReaders(messageReaders); |
||||
} |
||||
|
||||
@Override |
||||
protected void extendMessageReaders(List<HttpMessageReader<?>> messageReaders) { |
||||
this.configurers.extendMessageReaders(messageReaders); |
||||
} |
||||
|
||||
@Override |
||||
protected void addFormatters(FormatterRegistry registry) { |
||||
this.configurers.addFormatters(registry); |
||||
} |
||||
|
||||
@Override |
||||
protected Validator getValidator() { |
||||
return this.configurers.getValidator().orElse(super.getValidator()); |
||||
} |
||||
|
||||
@Override |
||||
protected MessageCodesResolver getMessageCodesResolver() { |
||||
return this.configurers.getMessageCodesResolver().orElse(super.getMessageCodesResolver()); |
||||
} |
||||
|
||||
@Override |
||||
protected void configureMessageWriters(List<HttpMessageWriter<?>> messageWriters) { |
||||
this.configurers.configureMessageWriters(messageWriters); |
||||
} |
||||
|
||||
@Override |
||||
protected void extendMessageWriters(List<HttpMessageWriter<?>> messageWriters) { |
||||
this.configurers.extendMessageWriters(messageWriters); |
||||
} |
||||
|
||||
@Override |
||||
protected void configureViewResolvers(ViewResolverRegistry registry) { |
||||
this.configurers.configureViewResolvers(registry); |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/* |
||||
* 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.config; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.context.annotation.Import; |
||||
|
||||
/** |
||||
* Adding this annotation to an {@code @Configuration} class imports the Spring Web |
||||
* Reactive configuration from {@link WebReactiveConfigurationSupport}, e.g.: |
||||
* |
||||
* <pre class="code"> |
||||
* @Configuration |
||||
* @EnableWebReactive |
||||
* @ComponentScan(basePackageClasses = { MyConfiguration.class }) |
||||
* public class MyWebConfiguration { |
||||
* |
||||
* } |
||||
* </pre> |
||||
* |
||||
* <p>To customize the imported configuration, implement the interface
|
||||
* {@link WebReactiveConfigurer} and override individual methods, e.g.: |
||||
* |
||||
* <pre class="code"> |
||||
* @Configuration |
||||
* @EnableWebMvc |
||||
* @ComponentScan(basePackageClasses = { MyConfiguration.class }) |
||||
* public class MyConfiguration implements WebReactiveConfigurer { |
||||
* |
||||
* @Override |
||||
* public void addFormatters(FormatterRegistry formatterRegistry) { |
||||
* formatterRegistry.addConverter(new MyConverter()); |
||||
* } |
||||
* |
||||
* @Override |
||||
* public void configureMessageWriters(List<HttpMessageWriter<?>> messageWriters) { |
||||
* messageWriters.add(new MyHttpMessageWriter()); |
||||
* } |
||||
* |
||||
* // More overridden methods ...
|
||||
* } |
||||
* </pre> |
||||
* |
||||
* <p>If {@link WebReactiveConfigurer} does not expose some advanced setting that |
||||
* needs to be configured, consider removing the {@code @EnableWebReactive} |
||||
* annotation and extending directly from {@link WebReactiveConfigurationSupport} |
||||
* or {@link DelegatingWebReactiveConfiguration} if you still want to allow |
||||
* {@link WebReactiveConfigurer} instances to customize the configuration. |
||||
* |
||||
* @author Brian Clozel |
||||
* @since 5.0 |
||||
* @see WebReactiveConfigurer |
||||
* @see WebReactiveConfigurationSupport |
||||
*/ |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target(ElementType.TYPE) |
||||
@Documented |
||||
@Import(DelegatingWebReactiveConfiguration.class) |
||||
public @interface EnableWebReactive { |
||||
} |
||||
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
/* |
||||
* 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.config; |
||||
|
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.springframework.core.convert.converter.Converter; |
||||
import org.springframework.format.Formatter; |
||||
import org.springframework.format.FormatterRegistry; |
||||
import org.springframework.http.codec.HttpMessageReader; |
||||
import org.springframework.http.codec.HttpMessageWriter; |
||||
import org.springframework.validation.MessageCodesResolver; |
||||
import org.springframework.validation.Validator; |
||||
import org.springframework.web.reactive.accept.CompositeContentTypeResolver; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; |
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; |
||||
|
||||
/** |
||||
* Defines callback methods to customize the configuration for Web Reactive |
||||
* applications enabled via {@code @EnableWebReactive}. |
||||
* |
||||
* <p>{@code @EnableWebReactive}-annotated configuration classes may implement |
||||
* this interface to be called back and given a chance to customize the |
||||
* default configuration. Consider implementing this interface and |
||||
* overriding the relevant methods for your needs. |
||||
* |
||||
* @author Brian Clozel |
||||
* @since 5.0 |
||||
*/ |
||||
public interface WebReactiveConfigurer { |
||||
|
||||
/** |
||||
* Configure how the requested content type is resolved. |
||||
* <p>The given builder will create a composite of multiple |
||||
* {@link RequestedContentTypeResolver}s, each defining a way to resolve the |
||||
* the requested content type (accept HTTP header, path extension, parameter, etc). |
||||
* @param builder factory that creates a {@link CompositeContentTypeResolver} instance |
||||
*/ |
||||
default void configureRequestedContentTypeResolver(RequestedContentTypeResolverBuilder builder) { |
||||
} |
||||
|
||||
/** |
||||
* Configure cross origin requests processing. |
||||
* @see CorsRegistry |
||||
*/ |
||||
default void addCorsMappings(CorsRegistry registry) { |
||||
} |
||||
|
||||
/** |
||||
* Configure path matching options. |
||||
* <p>The given configurer assists with configuring |
||||
* {@code HandlerMapping}s with path matching options. |
||||
* @param configurer the {@link PathMatchConfigurer} instance |
||||
*/ |
||||
default void configurePathMatching(PathMatchConfigurer configurer) { |
||||
} |
||||
|
||||
/** |
||||
* Add resource handlers for serving static resources. |
||||
* @see ResourceHandlerRegistry |
||||
*/ |
||||
default void addResourceHandlers(ResourceHandlerRegistry registry) { |
||||
} |
||||
|
||||
/** |
||||
* Provide custom argument resolvers without overriding the built-in ones. |
||||
* @param resolvers a list of resolvers to add to the built-in ones |
||||
*/ |
||||
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
||||
} |
||||
|
||||
/** |
||||
* Configure the message readers to use for decoding controller method arguments. |
||||
* <p>If no message readers are specified, default readers will be added via |
||||
* {@link WebReactiveConfigurationSupport#addDefaultHttpMessageReaders}. |
||||
* @param readers a list to add message readers to, initially an empty list |
||||
*/ |
||||
default void configureMessageReaders(List<HttpMessageReader<?>> readers) { |
||||
} |
||||
|
||||
/** |
||||
* Modify the list of message readers to use for decoding controller method arguments, |
||||
* for example to add some in addition to the ones already configured. |
||||
*/ |
||||
default void extendMessageReaders(List<HttpMessageReader<?>> readers) { |
||||
} |
||||
|
||||
/** |
||||
* Add custom {@link Converter}s and {@link Formatter}s. |
||||
*/ |
||||
default void addFormatters(FormatterRegistry registry) { |
||||
} |
||||
|
||||
/** |
||||
* Provide a custom {@link Validator}, instead of the instance configured by default. |
||||
* <p>Only a single instance is allowed, an error will be thrown if multiple |
||||
* {@code Validator}s are returned by {@code WebReactiveConfigurer}s. |
||||
* The default implementation returns {@code Optional.empty()}. |
||||
*/ |
||||
default Optional<Validator> getValidator() { |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
/** |
||||
* Provide a custom {@link MessageCodesResolver}, instead of using the one |
||||
* provided by {@link org.springframework.validation.DataBinder} instances. |
||||
* The default implementation returns {@code Optional.empty()}. |
||||
*/ |
||||
default Optional<MessageCodesResolver> getMessageCodesResolver() { |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
/** |
||||
* Configure the message writers to use for encoding return values. |
||||
* <p>If no message writers are specified, default writers will be added via |
||||
* {@link WebReactiveConfigurationSupport#addDefaultHttpMessageWriters(List)}. |
||||
* @param writers a list to add message writers to, initially an empty list |
||||
*/ |
||||
default void configureMessageWriters(List<HttpMessageWriter<?>> writers) { |
||||
} |
||||
|
||||
/** |
||||
* Modify the list of message writers to use for encoding return values, |
||||
* for example to add some in addition to the ones already configured. |
||||
*/ |
||||
default void extendMessageWriters(List<HttpMessageWriter<?>> writers) { |
||||
} |
||||
|
||||
/** |
||||
* Configure view resolution for supporting template engines. |
||||
* @see ViewResolverRegistry |
||||
*/ |
||||
default void configureViewResolvers(ViewResolverRegistry registry) { |
||||
} |
||||
|
||||
/** |
||||
* Factory method for the {@link RequestMappingHandlerMapping} bean creating |
||||
* an instance or a custom extension of it. Note that only one configurer |
||||
* is allowed to implement this method. |
||||
* The default implementation returns {@code Optional.empty()}. |
||||
*/ |
||||
default Optional<RequestMappingHandlerMapping> createRequestMappingHandlerMapping() { |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
/** |
||||
* Factory method for the {@link RequestMappingHandlerAdapter} bean creating |
||||
* an instance or a custom extension of it. Note that only one configurer |
||||
* is allowed to implement this method. |
||||
* The default implementation returns {@code Optional.empty()}. |
||||
*/ |
||||
default Optional<RequestMappingHandlerAdapter> createRequestMappingHandlerAdapter() { |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
/* |
||||
* 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.config; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
import java.util.function.Function; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import org.springframework.format.FormatterRegistry; |
||||
import org.springframework.http.codec.HttpMessageReader; |
||||
import org.springframework.http.codec.HttpMessageWriter; |
||||
import org.springframework.util.CollectionUtils; |
||||
import org.springframework.validation.MessageCodesResolver; |
||||
import org.springframework.validation.Validator; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; |
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; |
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; |
||||
|
||||
/** |
||||
* A {@link WebReactiveConfigurer} that delegates to one or more others. |
||||
* |
||||
* @author Brian Clozel |
||||
* @author Rossen Stoyanchev |
||||
* @since 5.0 |
||||
*/ |
||||
public class WebReactiveConfigurerComposite implements WebReactiveConfigurer { |
||||
|
||||
private final List<WebReactiveConfigurer> delegates = new ArrayList<>(); |
||||
|
||||
|
||||
public void addWebReactiveConfigurers(List<WebReactiveConfigurer> configurers) { |
||||
if (!CollectionUtils.isEmpty(configurers)) { |
||||
this.delegates.addAll(configurers); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void configureRequestedContentTypeResolver(RequestedContentTypeResolverBuilder builder) { |
||||
this.delegates.stream().forEach(delegate -> delegate.configureRequestedContentTypeResolver(builder)); |
||||
} |
||||
|
||||
@Override |
||||
public void addCorsMappings(CorsRegistry registry) { |
||||
this.delegates.stream().forEach(delegate -> delegate.addCorsMappings(registry)); |
||||
} |
||||
|
||||
@Override |
||||
public void configurePathMatching(PathMatchConfigurer configurer) { |
||||
this.delegates.stream().forEach(delegate -> delegate.configurePathMatching(configurer)); |
||||
} |
||||
|
||||
@Override |
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) { |
||||
this.delegates.stream().forEach(delegate -> delegate.addResourceHandlers(registry)); |
||||
} |
||||
|
||||
@Override |
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
||||
this.delegates.stream().forEach(delegate -> delegate.addArgumentResolvers(resolvers)); |
||||
} |
||||
|
||||
@Override |
||||
public void configureMessageReaders(List<HttpMessageReader<?>> readers) { |
||||
this.delegates.stream().forEach(delegate -> delegate.configureMessageReaders(readers)); |
||||
} |
||||
|
||||
@Override |
||||
public void extendMessageReaders(List<HttpMessageReader<?>> readers) { |
||||
this.delegates.stream().forEach(delegate -> delegate.extendMessageReaders(readers)); |
||||
} |
||||
|
||||
@Override |
||||
public void addFormatters(FormatterRegistry registry) { |
||||
this.delegates.stream().forEach(delegate -> delegate.addFormatters(registry)); |
||||
} |
||||
|
||||
@Override |
||||
public Optional<Validator> getValidator() { |
||||
return createSingleBean(WebReactiveConfigurer::getValidator, Validator.class); |
||||
} |
||||
|
||||
@Override |
||||
public Optional<MessageCodesResolver> getMessageCodesResolver() { |
||||
return createSingleBean(WebReactiveConfigurer::getMessageCodesResolver, MessageCodesResolver.class); |
||||
} |
||||
|
||||
@Override |
||||
public void configureMessageWriters(List<HttpMessageWriter<?>> writers) { |
||||
this.delegates.stream().forEach(delegate -> delegate.configureMessageWriters(writers)); |
||||
} |
||||
|
||||
@Override |
||||
public void extendMessageWriters(List<HttpMessageWriter<?>> writers) { |
||||
this.delegates.stream().forEach(delegate -> delegate.extendMessageWriters(writers)); |
||||
} |
||||
|
||||
@Override |
||||
public void configureViewResolvers(ViewResolverRegistry registry) { |
||||
this.delegates.stream().forEach(delegate -> delegate.configureViewResolvers(registry)); |
||||
} |
||||
|
||||
@Override |
||||
public Optional<RequestMappingHandlerMapping> createRequestMappingHandlerMapping() { |
||||
return createSingleBean(WebReactiveConfigurer::createRequestMappingHandlerMapping, |
||||
RequestMappingHandlerMapping.class); |
||||
} |
||||
|
||||
@Override |
||||
public Optional<RequestMappingHandlerAdapter> createRequestMappingHandlerAdapter() { |
||||
return createSingleBean(WebReactiveConfigurer::createRequestMappingHandlerAdapter, |
||||
RequestMappingHandlerAdapter.class); |
||||
} |
||||
|
||||
private <T> Optional<T> createSingleBean(Function<WebReactiveConfigurer, Optional<T>> factory, |
||||
Class<T> beanType) { |
||||
|
||||
List<Optional<T>> result = this.delegates.stream() |
||||
.map(factory).filter(Optional::isPresent).collect(Collectors.toList()); |
||||
|
||||
if (result.isEmpty()) { |
||||
return Optional.empty(); |
||||
} |
||||
else if (result.size() == 1) { |
||||
return result.get(1); |
||||
} |
||||
else { |
||||
throw new IllegalStateException("More than one WebReactiveConfigurer implements " + |
||||
beanType.getSimpleName() + " factory method."); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,144 @@
@@ -0,0 +1,144 @@
|
||||
/* |
||||
* 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.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)); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue