From a48c9b6305a9aab74168b5c5455f8b5ef9eb466b Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 30 Oct 2015 17:58:59 -0400 Subject: [PATCH] Replace DefaultConversionService in spring-reactive --- .../support/DefaultConversionService.java | 47 ------- .../RequestBodyArgumentResolver.java | 38 +++--- .../RequestMappingHandlerAdapter.java | 27 ++-- .../annotation/ResponseBodyResultHandler.java | 40 +++--- .../RequestMappingIntegrationTests.java | 123 ++++++++++++------ .../ResponseBodyResultHandlerTests.java | 16 ++- 6 files changed, 141 insertions(+), 150 deletions(-) delete mode 100644 spring-web-reactive/src/main/java/org/springframework/reactive/convert/support/DefaultConversionService.java diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/convert/support/DefaultConversionService.java b/spring-web-reactive/src/main/java/org/springframework/reactive/convert/support/DefaultConversionService.java deleted file mode 100644 index a3e345f1f1..0000000000 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/convert/support/DefaultConversionService.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2015 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.reactive.convert.support; - -import reactor.core.publisher.convert.DependencyUtils; - -import org.springframework.core.convert.converter.ConverterRegistry; -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutureConverter; -import org.springframework.core.convert.support.ReactiveStreamsToReactorConverter; -import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter; - -/** - * TODO temporary class designed to be replaced by org.springframework.core.convert.support.DefaultConversionService when it will contain Reactive Streams converter - * @author Sebastien Deleuze - */ -public class DefaultConversionService extends GenericConversionService { - - public DefaultConversionService() { - addDefaultConverters(this); - } - - public static void addDefaultConverters(ConverterRegistry converterRegistry) { - converterRegistry.addConverter(new ReactiveStreamsToCompletableFutureConverter()); - if (DependencyUtils.hasReactorStream()) { - converterRegistry.addConverter(new ReactiveStreamsToReactorConverter()); - } - if (DependencyUtils.hasRxJava1()) { - converterRegistry.addConverter(new ReactiveStreamsToRxJava1Converter()); - } - } - -} diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestBodyArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestBodyArgumentResolver.java index d9b5359f90..60f8aa8055 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestBodyArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestBodyArgumentResolver.java @@ -19,6 +19,7 @@ package org.springframework.reactive.web.dispatch.method.annotation; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -32,7 +33,9 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.reactive.codec.decoder.ByteToMessageDecoder; +import org.springframework.reactive.codec.decoder.JsonObjectDecoder; import org.springframework.reactive.web.dispatch.method.HandlerMethodArgumentResolver; +import org.springframework.util.Assert; import org.springframework.web.bind.annotation.RequestBody; /** @@ -44,25 +47,19 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve private static final Charset UTF_8 = Charset.forName("UTF-8"); - private final List> deserializers; - - private final List> preProcessors; + private final List> decoders; private final ConversionService conversionService; + // TODO: remove field + private final List> preProcessors = Arrays.asList(new JsonObjectDecoder()); - public RequestBodyArgumentResolver(List> decoders, - ConversionService conversionService) { - this(decoders, conversionService, Collections.EMPTY_LIST); - } - - public RequestBodyArgumentResolver(List> decoders, - ConversionService service, List> preProcessors) { - - this.deserializers = decoders; + public RequestBodyArgumentResolver(List> decoders, ConversionService service) { + Assert.notEmpty(decoders, "At least one decoder is required."); + Assert.notNull(service, "'conversionService' is required."); + this.decoders = decoders; this.conversionService = service; - this.preProcessors = preProcessors; } @@ -80,10 +77,10 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve Publisher inputStream = request.getBody(); Publisher elementStream = inputStream; ResolvableType elementType = type.hasGenerics() ? type.getGeneric(0) : type; - ByteToMessageDecoder decoder = resolveDecoder(request, elementType, mediaType, hints.toArray()); + ByteToMessageDecoder decoder = resolveDecoder(elementType, mediaType, hints.toArray()); if (decoder != null) { List> preProcessors = resolvePreProcessors( - request, elementType, mediaType,hints.toArray()); + elementType, mediaType,hints.toArray()); for (ByteToMessageDecoder preProcessor : preProcessors) { inputStream = preProcessor.decode(inputStream, elementType, mediaType, hints.toArray()); @@ -103,10 +100,8 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve return ( mediaTypes.size() > 0 ? mediaTypes.get(0) : MediaType.TEXT_PLAIN); } - private ByteToMessageDecoder resolveDecoder(ReactiveServerHttpRequest request, - ResolvableType type, MediaType mediaType, Object[] hints) { - - for (ByteToMessageDecoder deserializer : this.deserializers) { + private ByteToMessageDecoder resolveDecoder(ResolvableType type, MediaType mediaType, Object[] hints) { + for (ByteToMessageDecoder deserializer : this.decoders) { if (deserializer.canDecode(type, mediaType, hints)) { return deserializer; } @@ -114,9 +109,8 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve return null; } - private List> resolvePreProcessors( - ReactiveServerHttpRequest request, ResolvableType type, MediaType mediaType, - Object[] hints) { + private List> resolvePreProcessors(ResolvableType type, + MediaType mediaType, Object[] hints) { List> preProcessors = new ArrayList<>(); for (ByteToMessageDecoder preProcessor : this.preProcessors) { diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java index 75f20e7dbb..f604fa0b3c 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java @@ -16,24 +16,21 @@ package org.springframework.reactive.web.dispatch.method.annotation; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.reactivestreams.Publisher; import reactor.Publishers; import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.convert.ConversionService; import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.http.server.ReactiveServerHttpResponse; import org.springframework.reactive.codec.decoder.ByteBufferDecoder; import org.springframework.reactive.codec.decoder.ByteToMessageDecoder; import org.springframework.reactive.codec.decoder.JacksonJsonDecoder; -import org.springframework.reactive.codec.decoder.JsonObjectDecoder; import org.springframework.reactive.codec.decoder.StringDecoder; -import org.springframework.reactive.convert.support.DefaultConversionService; import org.springframework.reactive.web.dispatch.HandlerAdapter; import org.springframework.reactive.web.dispatch.HandlerResult; import org.springframework.reactive.web.dispatch.method.HandlerMethodArgumentResolver; @@ -48,12 +45,26 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Initializin private List argumentResolvers; + private ConversionService conversionService; - public void setHandlerMethodArgumentResolvers(List resolvers) { + + public void setArgumentResolvers(List resolvers) { this.argumentResolvers.clear(); this.argumentResolvers.addAll(resolvers); } + public List getArgumentResolvers() { + return this.argumentResolvers; + } + + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + public ConversionService getConversionService() { + return this.conversionService; + } + @Override public void afterPropertiesSet() throws Exception { @@ -62,13 +73,9 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Initializin List> decoders = Arrays.asList(new ByteBufferDecoder(), new StringDecoder(), new JacksonJsonDecoder()); - List> preProcessors = Collections.singletonList( - new JsonObjectDecoder()); - this.argumentResolvers = new ArrayList<>(); this.argumentResolvers.add(new RequestParamArgumentResolver()); - this.argumentResolvers.add(new RequestBodyArgumentResolver(decoders, - new DefaultConversionService(), preProcessors)); + this.argumentResolvers.add(new RequestBodyArgumentResolver(decoders, this.conversionService)); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandler.java index aa2a14bb0a..ec66870464 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandler.java @@ -20,7 +20,7 @@ import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import org.reactivestreams.Publisher; @@ -35,10 +35,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.http.server.ReactiveServerHttpResponse; +import org.springframework.reactive.codec.encoder.JsonObjectEncoder; import org.springframework.reactive.codec.encoder.MessageToByteEncoder; -import org.springframework.reactive.convert.support.DefaultConversionService; import org.springframework.reactive.web.dispatch.HandlerResult; import org.springframework.reactive.web.dispatch.HandlerResultHandler; +import org.springframework.util.Assert; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; @@ -56,29 +57,21 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered private final List> serializers; - private final List> postProcessors; + private final ConversionService conversionService; private int order = 0; + // TODO: remove field + private final List> postProcessors = Arrays.asList(new JsonObjectEncoder()); - public ResponseBodyResultHandler(List> encoders) { - this(encoders, Collections.EMPTY_LIST); - } - public ResponseBodyResultHandler(List> encoders, - List> postProcessors) { - - this(encoders, postProcessors, new DefaultConversionService()); - } - - public ResponseBodyResultHandler(List> encoders, - List> postProcessors, - ConversionService conversionService) { + public ResponseBodyResultHandler(List> encoders, ConversionService service) { + Assert.notEmpty(encoders, "At least one encoder is required."); + Assert.notNull(service, "'conversionService' is required."); this.serializers = encoders; - this.postProcessors = postProcessors; - this.conversionService = conversionService; + this.conversionService = service; } @@ -131,11 +124,11 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered } MessageToByteEncoder encoder = (MessageToByteEncoder) resolveEncoder( - request, elementType, mediaType, hints.toArray()); + elementType, mediaType, hints.toArray()); if (encoder != null) { Publisher outputStream = encoder.encode(elementStream, type, mediaType, hints.toArray()); - List> postProcessors = resolvePostProcessors(request, + List> postProcessors = resolvePostProcessors( elementType, mediaType, hints.toArray()); for (MessageToByteEncoder postProcessor : postProcessors) { outputStream = postProcessor.encode(outputStream, elementType, mediaType, hints.toArray()); @@ -155,9 +148,7 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered return ( mediaTypes.size() > 0 ? mediaTypes.get(0) : MediaType.TEXT_PLAIN); } - private MessageToByteEncoder resolveEncoder(ReactiveServerHttpRequest request, - ResolvableType type, MediaType mediaType, Object[] hints) { - + private MessageToByteEncoder resolveEncoder(ResolvableType type, MediaType mediaType, Object[] hints) { for (MessageToByteEncoder codec : this.serializers) { if (codec.canEncode(type, mediaType, hints)) { return codec; @@ -166,9 +157,8 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered return null; } - private List> resolvePostProcessors( - ReactiveServerHttpRequest request, ResolvableType type, MediaType mediaType, - Object[] hints) { + private List> resolvePostProcessors(ResolvableType type, + MediaType mediaType, Object[] hints) { List> postProcessors = new ArrayList<>(); for (MessageToByteEncoder postProcessor : this.postProcessors) { diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingIntegrationTests.java index fc6133e00f..f8f14cd64e 100644 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingIntegrationTests.java @@ -21,17 +21,11 @@ import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; -import static org.junit.Assert.assertEquals; - import org.junit.Test; import org.reactivestreams.Publisher; - -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.core.ResolvableType; import reactor.io.buffer.Buffer; import reactor.rx.Promise; import reactor.rx.Promises; @@ -40,14 +34,22 @@ import reactor.rx.Streams; import rx.Observable; import rx.Single; +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.convert.ConversionService; +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.ReactiveStreamsToReactorConverter; +import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.reactive.codec.encoder.ByteBufferEncoder; import org.springframework.reactive.codec.encoder.JacksonJsonEncoder; -import org.springframework.reactive.codec.encoder.JsonObjectEncoder; import org.springframework.reactive.codec.encoder.StringEncoder; import org.springframework.reactive.web.dispatch.DispatcherHandler; import org.springframework.reactive.web.dispatch.SimpleHandlerResultHandler; @@ -59,7 +61,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.client.RestTemplate; -import org.springframework.web.context.support.StaticWebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + +import static org.junit.Assert.assertEquals; /** * @author Rossen Stoyanchev @@ -68,26 +72,17 @@ import org.springframework.web.context.support.StaticWebApplicationContext; */ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrationTests { - private TestController controller; + private AnnotationConfigWebApplicationContext wac; @Override protected HttpHandler createHttpHandler() { - - StaticWebApplicationContext wac = new StaticWebApplicationContext(); - DefaultListableBeanFactory factory = wac.getDefaultListableBeanFactory(); - wac.registerSingleton("handlerMapping", RequestMappingHandlerMapping.class); - wac.registerSingleton("handlerAdapter", RequestMappingHandlerAdapter.class); - factory.registerSingleton("responseBodyResultHandler", new ResponseBodyResultHandler( - Arrays.asList(new ByteBufferEncoder(), new StringEncoder(),new JacksonJsonEncoder()), - Collections.singletonList(new JsonObjectEncoder()))); - wac.registerSingleton("simpleResultHandler", SimpleHandlerResultHandler.class); - this.controller = new TestController(); - factory.registerSingleton("controller", this.controller); - wac.refresh(); + this.wac = new AnnotationConfigWebApplicationContext(); + this.wac.register(FrameworkConfig.class, ApplicationConfig.class); + this.wac.refresh(); DispatcherHandler dispatcherHandler = new DispatcherHandler(); - dispatcherHandler.setApplicationContext(wac); + dispatcherHandler.setApplicationContext(this.wac); return dispatcherHandler; } @@ -212,11 +207,11 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati ResponseEntity response = restTemplate.exchange(request, Void.class); assertEquals(HttpStatus.OK, response.getStatusCode()); - assertEquals(2, this.controller.persons.size()); + assertEquals(2, this.wac.getBean(TestController.class).persons.size()); } - public void serializeAsPojo(String requestUrl) throws Exception { + private void serializeAsPojo(String requestUrl) throws Exception { RestTemplate restTemplate = new RestTemplate(); RequestEntity request = RequestEntity.get(new URI(requestUrl)) .accept(MediaType.APPLICATION_JSON) @@ -226,17 +221,7 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati assertEquals(new Person("Robert"), response.getBody()); } - public void postAsPojo(String requestUrl) throws Exception { - RestTemplate restTemplate = new RestTemplate(); - RequestEntity request = RequestEntity.post(new URI(requestUrl)) - .accept(MediaType.APPLICATION_JSON) - .body(new Person("Robert")); - ResponseEntity response = restTemplate.exchange(request, Person.class); - - assertEquals(new Person("Robert"), response.getBody()); - } - - public void serializeAsCollection(String requestUrl) throws Exception { + private void serializeAsCollection(String requestUrl) throws Exception { RestTemplate restTemplate = new RestTemplate(); RequestEntity request = RequestEntity.get(new URI(requestUrl)) .accept(MediaType.APPLICATION_JSON) @@ -250,7 +235,7 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati } - public void capitalizePojo(String requestUrl) throws Exception { + private void capitalizePojo(String requestUrl) throws Exception { RestTemplate restTemplate = new RestTemplate(); RequestEntity request = RequestEntity.post(new URI(requestUrl)) .contentType(MediaType.APPLICATION_JSON) @@ -261,8 +246,7 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati assertEquals(new Person("ROBERT"), response.getBody()); } - - public void capitalizeCollection(String requestUrl) throws Exception { + private void capitalizeCollection(String requestUrl) throws Exception { RestTemplate restTemplate = new RestTemplate(); RequestEntity> request = RequestEntity.post(new URI(requestUrl)) .contentType(MediaType.APPLICATION_JSON) @@ -277,6 +261,57 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati } + @Configuration + @SuppressWarnings("unused") + static class FrameworkConfig { + + @Bean + public RequestMappingHandlerMapping handlerMapping() { + return new RequestMappingHandlerMapping(); + } + + @Bean + public RequestMappingHandlerAdapter handlerAdapter() { + RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter(); + handlerAdapter.setConversionService(conversionService()); + return handlerAdapter; + } + + @Bean + public ConversionService conversionService() { + // TODO: test failures with DefaultConversionService + GenericConversionService service = new GenericConversionService(); + service.addConverter(new ReactiveStreamsToCompletableFutureConverter()); + service.addConverter(new ReactiveStreamsToReactorConverter()); + service.addConverter(new ReactiveStreamsToRxJava1Converter()); + return service; + } + + @Bean + public ResponseBodyResultHandler responseBodyResultHandler() { + return new ResponseBodyResultHandler(Arrays.asList( + new ByteBufferEncoder(), new StringEncoder(),new JacksonJsonEncoder()), + conversionService()); + } + + @Bean + public SimpleHandlerResultHandler simpleHandlerResultHandler() { + return new SimpleHandlerResultHandler(); + } + + } + + @Configuration + @SuppressWarnings("unused") + static class ApplicationConfig { + + @Bean + public TestController testController() { + return new TestController(); + } + } + + @Controller @SuppressWarnings("unused") private static class TestController { @@ -427,6 +462,7 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati private String name; + @SuppressWarnings("unused") public Person() { } @@ -444,12 +480,19 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati @Override public boolean equals(Object o) { - return name.equals(((Person)o).name); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Person person = (Person) o; + return !(this.name != null ? !this.name.equals(person.name) : person.name != null); } @Override public int hashCode() { - return name.hashCode(); + return this.name != null ? this.name.hashCode() : 0; } } diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandlerTests.java index c37f6dc19f..ea97ee81a9 100644 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/ResponseBodyResultHandlerTests.java @@ -18,15 +18,18 @@ package org.springframework.reactive.web.dispatch.method.annotation; import java.util.Collections; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import org.junit.Test; import org.reactivestreams.Publisher; +import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.reactive.codec.encoder.StringEncoder; import org.springframework.reactive.web.dispatch.HandlerResult; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * @author Sebastien Deleuze */ @@ -35,17 +38,18 @@ public class ResponseBodyResultHandlerTests { @Test public void supports() throws NoSuchMethodException { - ResponseBodyResultHandler resultHandler = new ResponseBodyResultHandler(Collections.emptyList()); + ResponseBodyResultHandler handler = new ResponseBodyResultHandler(Collections.singletonList( + new StringEncoder()), new DefaultConversionService()); TestController controller = new TestController(); HandlerMethod hm = new HandlerMethod(controller,TestController.class.getMethod("notAnnotated")); - assertFalse(resultHandler.supports(new HandlerResult(hm, null))); + assertFalse(handler.supports(new HandlerResult(hm, null))); hm = new HandlerMethod(controller, TestController.class.getMethod("publisherString")); - assertTrue(resultHandler.supports(new HandlerResult(hm, null))); + assertTrue(handler.supports(new HandlerResult(hm, null))); hm = new HandlerMethod(controller, TestController.class.getMethod("publisherVoid")); - assertTrue(resultHandler.supports(new HandlerResult(hm, null))); + assertTrue(handler.supports(new HandlerResult(hm, null))); }