Add Web Reactive Java config
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.codec.support.JacksonJsonEncoder;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.reactive.result.view.HttpMessageConverterView;
|
||||
import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
|
||||
import org.springframework.web.reactive.result.view.View;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigurer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ViewResolverRegistry}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ViewResolverRegistryTests {
|
||||
|
||||
private ViewResolverRegistry registry;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerSingleton("freeMarkerConfigurer", FreeMarkerConfigurer.class);
|
||||
this.registry = new ViewResolverRegistry(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void order() {
|
||||
assertEquals(Ordered.LOWEST_PRECEDENCE, this.registry.getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasRegistrations() {
|
||||
assertFalse(this.registry.hasRegistrations());
|
||||
|
||||
this.registry.freeMarker();
|
||||
assertTrue(this.registry.hasRegistrations());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noResolvers() {
|
||||
assertNotNull(this.registry.getViewResolvers());
|
||||
assertEquals(0, this.registry.getViewResolvers().size());
|
||||
assertFalse(this.registry.hasRegistrations());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customViewResolver() {
|
||||
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
|
||||
this.registry.viewResolver(viewResolver);
|
||||
|
||||
assertSame(viewResolver, this.registry.getViewResolvers().get(0));
|
||||
assertEquals(1, this.registry.getViewResolvers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultViews() throws Exception {
|
||||
View view = new HttpMessageConverterView(new JacksonJsonEncoder());
|
||||
this.registry.defaultViews(view);
|
||||
|
||||
assertEquals(1, this.registry.getDefaultViews().size());
|
||||
assertSame(view, this.registry.getDefaultViews().get(0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import rx.Observable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.support.JacksonJsonEncoder;
|
||||
import org.springframework.core.codec.support.Jaxb2Decoder;
|
||||
import org.springframework.core.codec.support.Jaxb2Encoder;
|
||||
import org.springframework.core.codec.support.Pojo;
|
||||
import org.springframework.core.codec.support.StringDecoder;
|
||||
import org.springframework.core.codec.support.StringEncoder;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.reactive.CodecHttpMessageConverter;
|
||||
import org.springframework.http.converter.reactive.HttpMessageConverter;
|
||||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
|
||||
import org.springframework.web.reactive.result.view.HttpMessageConverterView;
|
||||
import org.springframework.web.reactive.result.view.View;
|
||||
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigurer;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerViewResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WebReactiveConfiguration}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class WebReactiveConfigurationTests {
|
||||
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.request = new MockServerHttpRequest(HttpMethod.GET, new URI("/"));
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
this.exchange = new DefaultServerWebExchange(this.request, response, mock(WebSessionManager.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerMapping() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
|
||||
String name = "requestMappingHandlerMapping";
|
||||
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
|
||||
assertEquals(0, mapping.getOrder());
|
||||
|
||||
assertTrue(mapping.useSuffixPatternMatch());
|
||||
assertTrue(mapping.useTrailingSlashMatch());
|
||||
assertTrue(mapping.useRegisteredSuffixPatternMatch());
|
||||
|
||||
name = "mvcContentTypeResolver";
|
||||
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
|
||||
assertSame(resolver, mapping.getContentTypeResolver());
|
||||
|
||||
this.request.setUri(new URI("/path.json"));
|
||||
List<MediaType> list = Collections.singletonList(MediaType.APPLICATION_JSON);
|
||||
assertEquals(list, resolver.resolveMediaTypes(this.exchange));
|
||||
|
||||
this.request.setUri(new URI("/path.xml"));
|
||||
assertEquals(Collections.emptyList(), resolver.resolveMediaTypes(this.exchange));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customPathMatchConfig() throws Exception {
|
||||
ApplicationContext context = loadConfig(CustomPatchMatchConfig.class);
|
||||
|
||||
String name = "requestMappingHandlerMapping";
|
||||
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
|
||||
assertFalse(mapping.useSuffixPatternMatch());
|
||||
assertFalse(mapping.useTrailingSlashMatch());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
|
||||
String name = "requestMappingHandlerAdapter";
|
||||
RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class);
|
||||
assertNotNull(adapter);
|
||||
|
||||
List<HttpMessageConverter<?>> converters = adapter.getMessageConverters();
|
||||
assertEquals(5, converters.size());
|
||||
|
||||
assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM);
|
||||
assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN);
|
||||
assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG);
|
||||
assertHasConverter(converters, Pojo.class, MediaType.APPLICATION_XML);
|
||||
assertHasConverter(converters, Pojo.class, MediaType.APPLICATION_JSON);
|
||||
|
||||
name = "mvcConversionService";
|
||||
ConversionService service = context.getBean(name, ConversionService.class);
|
||||
assertSame(service, adapter.getConversionService());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customMessageConverterConfig() throws Exception {
|
||||
ApplicationContext context = loadConfig(CustomMessageConverterConfig.class);
|
||||
|
||||
String name = "requestMappingHandlerAdapter";
|
||||
RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class);
|
||||
assertNotNull(adapter);
|
||||
|
||||
List<HttpMessageConverter<?>> converters = adapter.getMessageConverters();
|
||||
assertEquals(2, converters.size());
|
||||
|
||||
assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN);
|
||||
assertHasConverter(converters, Pojo.class, MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mvcConversionService() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
|
||||
String name = "mvcConversionService";
|
||||
ConversionService service = context.getBean(name, ConversionService.class);
|
||||
assertNotNull(service);
|
||||
|
||||
service.canConvert(CompletableFuture.class, Mono.class);
|
||||
service.canConvert(Observable.class, Flux.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void responseBodyResultHandler() throws Exception {
|
||||
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
|
||||
|
||||
String name = "responseBodyResultHandler";
|
||||
ResponseBodyResultHandler handler = context.getBean(name, ResponseBodyResultHandler.class);
|
||||
assertNotNull(handler);
|
||||
|
||||
assertEquals(0, handler.getOrder());
|
||||
|
||||
List<HttpMessageConverter<?>> converters = handler.getMessageConverters();
|
||||
assertEquals(5, converters.size());
|
||||
|
||||
assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM);
|
||||
assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN);
|
||||
assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG);
|
||||
assertHasConverter(converters, Pojo.class, MediaType.APPLICATION_XML);
|
||||
assertHasConverter(converters, Pojo.class, MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viewResolutionResultHandler() throws Exception {
|
||||
ApplicationContext context = loadConfig(CustomViewResolverConfig.class);
|
||||
|
||||
String name = "viewResolutionResultHandler";
|
||||
ViewResolutionResultHandler handler = context.getBean(name, ViewResolutionResultHandler.class);
|
||||
assertNotNull(handler);
|
||||
|
||||
assertEquals(Ordered.LOWEST_PRECEDENCE, handler.getOrder());
|
||||
|
||||
List<ViewResolver> resolvers = handler.getViewResolvers();
|
||||
assertEquals(1, resolvers.size());
|
||||
assertEquals(FreeMarkerViewResolver.class, resolvers.get(0).getClass());
|
||||
|
||||
List<View> views = handler.getDefaultViews();
|
||||
assertEquals(1, views.size());
|
||||
|
||||
MimeType type = MimeTypeUtils.parseMimeType("application/json;charset=UTF-8");
|
||||
assertEquals(type, views.get(0).getSupportedMediaTypes().get(0));
|
||||
}
|
||||
|
||||
|
||||
private void assertHasConverter(List<HttpMessageConverter<?>> converters, Class<?> clazz, MediaType mediaType) {
|
||||
ResolvableType type = ResolvableType.forClass(clazz);
|
||||
assertTrue(converters.stream()
|
||||
.filter(c -> c.canRead(type, mediaType) && c.canWrite(type, mediaType))
|
||||
.findAny()
|
||||
.isPresent());
|
||||
}
|
||||
|
||||
private ApplicationContext loadConfig(Class<?>... configurationClasses) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(configurationClasses);
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class CustomPatchMatchConfig extends WebReactiveConfiguration {
|
||||
|
||||
@Override
|
||||
public void configurePathMatching(PathMatchConfigurer configurer) {
|
||||
configurer.setUseSuffixPatternMatch(false);
|
||||
configurer.setUseTrailingSlashMatch(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomMessageConverterConfig extends WebReactiveConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(new CodecHttpMessageConverter<>(new StringEncoder(), new StringDecoder()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(new CodecHttpMessageConverter<>(new Jaxb2Encoder(), new Jaxb2Decoder()));
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration @SuppressWarnings("unused")
|
||||
static class CustomViewResolverConfig extends WebReactiveConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.freeMarker();
|
||||
registry.defaultViews(new HttpMessageConverterView(new JacksonJsonEncoder()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FreeMarkerConfigurer freeMarkerConfig() {
|
||||
return new FreeMarkerConfigurer();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import java.nio.ByteBuffer;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -40,19 +39,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.support.ByteBufferDecoder;
|
||||
import org.springframework.core.codec.support.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.support.JacksonJsonDecoder;
|
||||
import org.springframework.core.codec.support.JacksonJsonEncoder;
|
||||
import org.springframework.core.codec.support.Jaxb2Decoder;
|
||||
import org.springframework.core.codec.support.Jaxb2Encoder;
|
||||
import org.springframework.core.codec.support.JsonObjectDecoder;
|
||||
import org.springframework.core.codec.support.StringDecoder;
|
||||
import org.springframework.core.codec.support.StringEncoder;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
@@ -62,9 +49,6 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.reactive.CodecHttpMessageConverter;
|
||||
import org.springframework.http.converter.reactive.HttpMessageConverter;
|
||||
import org.springframework.http.converter.reactive.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ZeroCopyIntegrationTests;
|
||||
@@ -78,11 +62,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.result.SimpleResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
import org.springframework.web.reactive.config.ViewResolverRegistry;
|
||||
import org.springframework.web.reactive.config.WebReactiveConfiguration;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigurer;
|
||||
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerViewResolver;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
@@ -385,61 +367,11 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
static class FrameworkConfig {
|
||||
static class FrameworkConfig extends WebReactiveConfiguration {
|
||||
|
||||
@Bean
|
||||
public RequestMappingHandlerMapping handlerMapping() {
|
||||
return new RequestMappingHandlerMapping();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RequestMappingHandlerAdapter handlerAdapter() {
|
||||
RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
|
||||
handlerAdapter.setMessageConverters(getDefaultMessageConverters());
|
||||
handlerAdapter.setConversionService(conversionService());
|
||||
return handlerAdapter;
|
||||
}
|
||||
|
||||
private List<HttpMessageConverter<?>> getDefaultMessageConverters() {
|
||||
return Arrays.asList(
|
||||
new CodecHttpMessageConverter<>(new ByteBufferEncoder(), new ByteBufferDecoder()),
|
||||
new CodecHttpMessageConverter<>(new StringEncoder(), new StringDecoder()),
|
||||
new CodecHttpMessageConverter<>(new Jaxb2Encoder(), new Jaxb2Decoder()),
|
||||
new CodecHttpMessageConverter<>(new JacksonJsonEncoder(),
|
||||
new JacksonJsonDecoder(new JsonObjectDecoder())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConversionService conversionService() {
|
||||
// TODO: test failures with DefaultConversionService
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
return service;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResponseBodyResultHandler responseBodyResultHandler() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<>();
|
||||
converters.add(new ResourceHttpMessageConverter());
|
||||
converters.addAll(getDefaultMessageConverters());
|
||||
return new ResponseBodyResultHandler(converters, conversionService());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleResultHandler simpleHandlerResultHandler() {
|
||||
return new SimpleResultHandler(conversionService());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolutionResultHandler viewResolverResultHandler() {
|
||||
List<ViewResolver> resolvers = Collections.singletonList(freeMarkerViewResolver());
|
||||
return new ViewResolutionResultHandler(resolvers, conversionService());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver freeMarkerViewResolver() {
|
||||
return new FreeMarkerViewResolver("", ".ftl");
|
||||
@Override
|
||||
protected void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.freeMarker();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user