Refactor reactive type conversion support
This commit replaces Reactive Streams converters for RxJava1 and CompletableFuture with Reactor specific ones. The results in conversion that preserves stream semantics, i.e. Mono vs Flux. For example this is allowed: Flux -> Observable Mono -> Single Mono -> CompletableFuture This is not allowed: Flux -> Single Mono -> Observable Flux -> CompletableFuture As a result it is now possible to check through the ConversionService if a target type to convert to is a stream of many or of one which is useful for decoding purposes. The commit also adds PublisherToFluxConverter to allow conversion from raw Publisher to Flux. The reverse is not necessary since Flux is a Publisher and it's a no-op conversion.
This commit is contained in:
committed by
Rossen Stoyanchev
parent
952395192f
commit
12d7b78169
@@ -24,13 +24,12 @@ import reactor.core.publisher.Flux;
|
||||
import rx.Observable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
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.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.result.SimpleResultHandler;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -46,8 +45,9 @@ public class SimpleResultHandlerTests {
|
||||
public void supportsWithConversionService() throws NoSuchMethodException {
|
||||
|
||||
GenericConversionService conversionService = new GenericConversionService();
|
||||
conversionService.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
conversionService.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
conversionService.addConverter(new MonoToCompletableFutureConverter());
|
||||
conversionService.addConverter(new PublisherToFluxConverter());
|
||||
conversionService.addConverter(new ReactorToRxJava1Converter());
|
||||
|
||||
SimpleResultHandler resultHandler = new SimpleResultHandler(conversionService);
|
||||
TestController controller = new TestController();
|
||||
|
||||
@@ -40,8 +40,9 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
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.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
@@ -136,7 +137,6 @@ public class MessageConverterResultHandlerTests {
|
||||
}
|
||||
|
||||
@Test // SPR-12811
|
||||
@Ignore
|
||||
public void jacksonTypeOfListElement() throws Exception {
|
||||
List<ParentClass> body = Arrays.asList(new Foo("foo"), new Bar("bar"));
|
||||
ResolvableType bodyType = ResolvableType.forClassWithGenerics(List.class, ParentClass.class);
|
||||
@@ -185,8 +185,9 @@ public class MessageConverterResultHandlerTests {
|
||||
}
|
||||
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
service.addConverter(new MonoToCompletableFutureConverter());
|
||||
service.addConverter(new PublisherToFluxConverter());
|
||||
service.addConverter(new ReactorToRxJava1Converter());
|
||||
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -43,11 +42,12 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.core.codec.Decoder;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.http.codec.json.JacksonJsonDecoder;
|
||||
import org.springframework.core.codec.StringDecoder;
|
||||
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.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -169,10 +169,7 @@ public class RequestBodyArgumentResolverTests {
|
||||
assertEquals(map, resolveValue("map", Map.class, body));
|
||||
}
|
||||
|
||||
// TODO: @Ignore
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void list() throws Exception {
|
||||
String body = "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]";
|
||||
assertEquals(Arrays.asList(new TestBean("f1", "b1"), new TestBean("f2", "b2")),
|
||||
@@ -180,7 +177,6 @@ public class RequestBodyArgumentResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void array() throws Exception {
|
||||
String body = "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]";
|
||||
assertArrayEquals(new TestBean[] {new TestBean("f1", "b1"), new TestBean("f2", "b2")},
|
||||
@@ -220,8 +216,9 @@ public class RequestBodyArgumentResolverTests {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<>();
|
||||
Arrays.asList(decoders).forEach(decoder -> converters.add(new CodecHttpMessageConverter<>(decoder)));
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
service.addConverter(new MonoToCompletableFutureConverter());
|
||||
service.addConverter(new PublisherToFluxConverter());
|
||||
service.addConverter(new ReactorToRxJava1Converter());
|
||||
return new RequestBodyArgumentResolver(converters, service, new TestBeanValidator());
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,9 @@ import org.springframework.core.codec.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
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.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.codec.json.JacksonJsonEncoder;
|
||||
@@ -100,8 +101,9 @@ public class ResponseBodyResultHandlerTests {
|
||||
converterList = Arrays.asList(converters);
|
||||
}
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
service.addConverter(new MonoToCompletableFutureConverter());
|
||||
service.addConverter(new PublisherToFluxConverter());
|
||||
service.addConverter(new ReactorToRxJava1Converter());
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
|
||||
|
||||
return new ResponseBodyResultHandler(converterList, new DefaultConversionService(), resolver);
|
||||
|
||||
@@ -33,8 +33,9 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
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.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -105,8 +106,11 @@ public class ResponseEntityResultHandlerTests {
|
||||
converterList = Arrays.asList(converters);
|
||||
}
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter());
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
service.addConverter(new MonoToCompletableFutureConverter());
|
||||
service.addConverter(new PublisherToFluxConverter());
|
||||
service.addConverter(new ReactorToRxJava1Converter());
|
||||
|
||||
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
|
||||
|
||||
return new ResponseEntityResultHandler(converterList, service, resolver);
|
||||
|
||||
@@ -39,7 +39,8 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
@@ -252,7 +253,8 @@ public class ViewResolutionResultHandlerTests {
|
||||
|
||||
private ViewResolutionResultHandler createResultHandler(List<View> defaultViews, ViewResolver... resolvers) {
|
||||
ConfigurableConversionService service = new DefaultConversionService();
|
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter());
|
||||
service.addConverter(new ReactorToRxJava1Converter());
|
||||
service.addConverter(new PublisherToFluxConverter());
|
||||
List<ViewResolver> resolverList = Arrays.asList(resolvers);
|
||||
ViewResolutionResultHandler handler = new ViewResolutionResultHandler(resolverList, service);
|
||||
handler.setDefaultViews(defaultViews);
|
||||
|
||||
Reference in New Issue
Block a user