From 5589804d2c553ff1c873b0569e7c9f7cf40f3230 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 May 2017 10:29:47 +0100 Subject: [PATCH] Add support for single valued Supplier as well --- ...ntextFunctionCatalogAutoConfiguration.java | 6 +-- .../cloud/function/support/FluxSupplier.java | 3 -- .../flux/response/FluxReturnValueHandler.java | 21 +++++++-- .../function/web/RestApplicationTests.java | 43 +++++++++++++------ 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/ContextFunctionCatalogAutoConfiguration.java index a92f9c6f3..1fd346301 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/ContextFunctionCatalogAutoConfiguration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/ContextFunctionCatalogAutoConfiguration.java @@ -482,7 +482,7 @@ public class ContextFunctionCatalogAutoConfiguration { } private Class findInputWrapper(String name) { - if (!registry.containsBeanDefinition(name)) { + if (name == null || !registry.containsBeanDefinition(name)) { return Object.class; } return findType(name, @@ -491,7 +491,7 @@ public class ContextFunctionCatalogAutoConfiguration { } private Class findOutputWrapper(String name) { - if (!registry.containsBeanDefinition(name)) { + if (name == null || !registry.containsBeanDefinition(name)) { return Object.class; } return findType(name, @@ -500,7 +500,7 @@ public class ContextFunctionCatalogAutoConfiguration { } private Class findInputType(String name) { - if (!registry.containsBeanDefinition(name)) { + if (name == null || !registry.containsBeanDefinition(name)) { return Object.class; } return findType(name, diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/support/FluxSupplier.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/support/FluxSupplier.java index 183568331..07aa3205a 100644 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/support/FluxSupplier.java +++ b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/support/FluxSupplier.java @@ -58,9 +58,6 @@ public class FluxSupplier implements Supplier> { if (result instanceof Stream) { return Flux.fromStream((Stream) result); } - if (result instanceof Iterable) { - return Flux.fromIterable((Iterable) result); - } return Flux.just((T) result); } } diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/response/FluxReturnValueHandler.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/response/FluxReturnValueHandler.java index 3ce1f76c4..af4e991cb 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/response/FluxReturnValueHandler.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/response/FluxReturnValueHandler.java @@ -20,6 +20,8 @@ import java.lang.reflect.Method; import java.time.Duration; import java.util.Arrays; import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Stream; import javax.servlet.http.HttpServletResponse; @@ -137,9 +139,8 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand NativeWebRequest.SCOPE_REQUEST); Class type = inspector.getOutputType(inspector.getName(handler)); - Boolean inputSingle = (Boolean) webRequest.getAttribute( - WebRequestConstants.INPUT_SINGLE, NativeWebRequest.SCOPE_REQUEST); - if (inputSingle!=null && inputSingle && isOutputSingle(handler)) { + boolean inputSingle = isInputSingle(webRequest, handler); + if (inputSingle && isOutputSingle(handler)) { single.handleReturnValue(Flux.from(flux).blockFirst(), singleReturnType, mavContainer, webRequest); return; @@ -160,11 +161,23 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand mavContainer, webRequest); } + private boolean isInputSingle(NativeWebRequest webRequest, Object handler) { + Boolean single = (Boolean) webRequest.getAttribute( + WebRequestConstants.INPUT_SINGLE, NativeWebRequest.SCOPE_REQUEST); + if (single == null) { + return handler instanceof Supplier; + } + return single; + } + private boolean isOutputSingle(Object handler) { String name = inspector.getName(handler); Class type = inspector.getOutputType(name); Class wrapper = inspector.getOutputWrapper(name); - if (wrapper==type) { + if (Stream.class.isAssignableFrom(type)) { + return false; + } + if (wrapper == type) { return true; } if (Mono.class.equals(wrapper) || Optional.class.equals(wrapper)) { diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java index 240cfcfdb..f5dc2e5bb 100644 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java +++ b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java @@ -109,6 +109,14 @@ public class RestApplicationTests { assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); } + @Test + public void word() throws Exception { + ResponseEntity result = rest + .exchange(RequestEntity.get(new URI("/word")).build(), String.class); + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(result.getBody()).isEqualTo("foo"); + } + @Test public void foos() throws Exception { ResponseEntity result = rest @@ -120,9 +128,9 @@ public class RestApplicationTests { @Test public void qualifierFoos() throws Exception { - ResponseEntity result = rest.exchange(RequestEntity - .post(new URI("/foos")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); + ResponseEntity result = rest.exchange(RequestEntity.post(new URI("/foos")) + .contentType(MediaType.APPLICATION_JSON).body("[\"foo\",\"bar\"]"), + String.class); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(result.getBody()) .isEqualTo("[{\"value\":\"[FOO]\"},{\"value\":\"[BAR]\"}]"); @@ -249,18 +257,21 @@ public class RestApplicationTests { @Test public void uppercaseSingleValue() throws Exception { - ResponseEntity result = rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.TEXT_PLAIN) - .body("foo"), String.class); + ResponseEntity result = rest + .exchange( + RequestEntity.post(new URI("/uppercase")) + .contentType(MediaType.TEXT_PLAIN).body("foo"), + String.class); assertThat(result.getBody()).isEqualTo("(FOO)"); } @Test @Ignore("WebFlux would split the request body into lines: TODO make this work the same") public void uppercasePlainText() throws Exception { - ResponseEntity result = rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.TEXT_PLAIN) - .body("foo\nbar"), String.class); + ResponseEntity result = rest.exchange( + RequestEntity.post(new URI("/uppercase")) + .contentType(MediaType.TEXT_PLAIN).body("foo\nbar"), + String.class); assertThat(result.getBody()).isEqualTo("(FOO)(BAR)"); } @@ -279,8 +290,7 @@ public class RestApplicationTests { ResponseEntity result = rest.exchange(RequestEntity .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"}]"); + assertThat(result.getBody()).isEqualTo("[{\"value\":\"FOO\"}]"); } @Test @@ -294,12 +304,12 @@ public class RestApplicationTests { @Test public void bareUppercaseFoo() throws Exception { - // Single Foo can be parsed and returns a single value if the function is defined that way + // Single Foo can be parsed and returns a single value if the function is defined + // that way ResponseEntity result = rest.exchange(RequestEntity .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()) - .isEqualTo("{\"value\":\"FOO\"}"); + assertThat(result.getBody()).isEqualTo("{\"value\":\"FOO\"}"); } @Test @@ -430,6 +440,11 @@ public class RestApplicationTests { return () -> Flux.just("foo", "bar"); } + @Bean + public Supplier word() { + return () -> "foo"; + } + @Bean public Supplier> foos() { return () -> Flux.just(new Foo("foo"), new Foo("bar"));