diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java index ac32b95b35a..bd9dab70254 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java @@ -32,6 +32,7 @@ import org.reactivestreams.Subscription; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; +import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.http.MediaType; import org.springframework.http.codec.ServerSentEvent; @@ -78,6 +79,10 @@ class ReactiveTypeHandler { private final ContentNegotiationManager contentNegotiationManager; + public ReactiveTypeHandler() { + this(new ReactiveAdapterRegistry(), new SyncTaskExecutor(), new ContentNegotiationManager()); + } + ReactiveTypeHandler(ReactiveAdapterRegistry registry, TaskExecutor executor, ContentNegotiationManager manager) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java index 92b441677c4..f09da9eac17 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java @@ -50,6 +50,9 @@ import org.springframework.web.method.support.ModelAndViewContainer; * such as {@link SseEmitter} including the same types wrapped with * {@link ResponseEntity}. * + *

As of 5.0 also supports reactive return value types for any reactive + * library with registered adapters in {@link ReactiveAdapterRegistry}. + * * @author Rossen Stoyanchev * @since 4.2 */ @@ -63,6 +66,28 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur private final ReactiveTypeHandler reactiveHandler; + /** + * Simple constructor with reactive type support based on a default instance of + * {@link ReactiveAdapterRegistry}, + * {@link org.springframework.core.task.SyncTaskExecutor}, and + * {@link ContentNegotiationManager} with an Accept header strategy. + */ + public ResponseBodyEmitterReturnValueHandler(List> messageConverters) { + Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty"); + this.messageConverters = messageConverters; + this.reactiveHandler = new ReactiveTypeHandler(); + } + + /** + * Complete constructor with pluggable "reactive" type support. + * + * @param messageConverters converters to write emitted objects with + * @param reactiveRegistry for reactive return value type support + * @param executor for blocking I/O writes of items emitted from reactive types + * @param manager for detecting streaming media types + * + * @since 5.0 + */ public ResponseBodyEmitterReturnValueHandler(List> messageConverters, ReactiveAdapterRegistry reactiveRegistry, TaskExecutor executor, ContentNegotiationManager manager) { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandlerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandlerTests.java index 40444414697..3b8d3972d34 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandlerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandlerTests.java @@ -67,10 +67,7 @@ public class ResponseBodyEmitterReturnValueHandlerTests { List> converters = Arrays.asList( new StringHttpMessageConverter(), new MappingJackson2HttpMessageConverter()); - ReactiveAdapterRegistry registry = new ReactiveAdapterRegistry(); - TaskExecutor executor = new SyncTaskExecutor(); - ContentNegotiationManager manager = new ContentNegotiationManager(); - this.handler = new ResponseBodyEmitterReturnValueHandler(converters, registry, executor, manager); + this.handler = new ResponseBodyEmitterReturnValueHandler(converters); this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); this.webRequest = new ServletWebRequest(this.request, this.response); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java index 8b849e12261..73f6c244bee 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java @@ -28,9 +28,7 @@ import org.junit.Test; import reactor.core.publisher.Flux; import org.springframework.core.MethodParameter; -import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.annotation.AliasFor; -import org.springframework.core.task.SyncTaskExecutor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageConverter; @@ -256,9 +254,7 @@ public class ServletInvocableHandlerMethodTests { @Test public void wrapConcurrentResult_ResponseBodyEmitter() throws Exception { - this.returnValueHandlers.addHandler( - new ResponseBodyEmitterReturnValueHandler(this.converters, - new ReactiveAdapterRegistry(), new SyncTaskExecutor(), new ContentNegotiationManager())); + this.returnValueHandlers.addHandler(new ResponseBodyEmitterReturnValueHandler(this.converters)); ServletInvocableHandlerMethod handlerMethod = getHandlerMethod(new StreamingHandler(), "handleEmitter"); handlerMethod = handlerMethod.wrapConcurrentResult(null);