Add support for single valued Supplier as well

This commit is contained in:
Dave Syer
2017-05-24 10:29:47 +01:00
parent 20a6796793
commit 5589804d2c
4 changed files with 49 additions and 24 deletions

View File

@@ -482,7 +482,7 @@ public class ContextFunctionCatalogAutoConfiguration {
} }
private Class<?> findInputWrapper(String name) { private Class<?> findInputWrapper(String name) {
if (!registry.containsBeanDefinition(name)) { if (name == null || !registry.containsBeanDefinition(name)) {
return Object.class; return Object.class;
} }
return findType(name, return findType(name,
@@ -491,7 +491,7 @@ public class ContextFunctionCatalogAutoConfiguration {
} }
private Class<?> findOutputWrapper(String name) { private Class<?> findOutputWrapper(String name) {
if (!registry.containsBeanDefinition(name)) { if (name == null || !registry.containsBeanDefinition(name)) {
return Object.class; return Object.class;
} }
return findType(name, return findType(name,
@@ -500,7 +500,7 @@ public class ContextFunctionCatalogAutoConfiguration {
} }
private Class<?> findInputType(String name) { private Class<?> findInputType(String name) {
if (!registry.containsBeanDefinition(name)) { if (name == null || !registry.containsBeanDefinition(name)) {
return Object.class; return Object.class;
} }
return findType(name, return findType(name,

View File

@@ -58,9 +58,6 @@ public class FluxSupplier<T> implements Supplier<Flux<T>> {
if (result instanceof Stream) { if (result instanceof Stream) {
return Flux.fromStream((Stream) result); return Flux.fromStream((Stream) result);
} }
if (result instanceof Iterable) {
return Flux.fromIterable((Iterable) result);
}
return Flux.just((T) result); return Flux.just((T) result);
} }
} }

View File

@@ -20,6 +20,8 @@ import java.lang.reflect.Method;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -137,9 +139,8 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand
NativeWebRequest.SCOPE_REQUEST); NativeWebRequest.SCOPE_REQUEST);
Class<?> type = inspector.getOutputType(inspector.getName(handler)); Class<?> type = inspector.getOutputType(inspector.getName(handler));
Boolean inputSingle = (Boolean) webRequest.getAttribute( boolean inputSingle = isInputSingle(webRequest, handler);
WebRequestConstants.INPUT_SINGLE, NativeWebRequest.SCOPE_REQUEST); if (inputSingle && isOutputSingle(handler)) {
if (inputSingle!=null && inputSingle && isOutputSingle(handler)) {
single.handleReturnValue(Flux.from(flux).blockFirst(), singleReturnType, single.handleReturnValue(Flux.from(flux).blockFirst(), singleReturnType,
mavContainer, webRequest); mavContainer, webRequest);
return; return;
@@ -160,11 +161,23 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand
mavContainer, webRequest); 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) { private boolean isOutputSingle(Object handler) {
String name = inspector.getName(handler); String name = inspector.getName(handler);
Class<?> type = inspector.getOutputType(name); Class<?> type = inspector.getOutputType(name);
Class<?> wrapper = inspector.getOutputWrapper(name); Class<?> wrapper = inspector.getOutputWrapper(name);
if (wrapper==type) { if (Stream.class.isAssignableFrom(type)) {
return false;
}
if (wrapper == type) {
return true; return true;
} }
if (Mono.class.equals(wrapper) || Optional.class.equals(wrapper)) { if (Mono.class.equals(wrapper) || Optional.class.equals(wrapper)) {

View File

@@ -109,6 +109,14 @@ public class RestApplicationTests {
assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]");
} }
@Test
public void word() throws Exception {
ResponseEntity<String> result = rest
.exchange(RequestEntity.get(new URI("/word")).build(), String.class);
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(result.getBody()).isEqualTo("foo");
}
@Test @Test
public void foos() throws Exception { public void foos() throws Exception {
ResponseEntity<String> result = rest ResponseEntity<String> result = rest
@@ -120,9 +128,9 @@ public class RestApplicationTests {
@Test @Test
public void qualifierFoos() throws Exception { public void qualifierFoos() throws Exception {
ResponseEntity<String> result = rest.exchange(RequestEntity ResponseEntity<String> result = rest.exchange(RequestEntity.post(new URI("/foos"))
.post(new URI("/foos")).contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON).body("[\"foo\",\"bar\"]"),
.body("[\"foo\",\"bar\"]"), String.class); String.class);
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(result.getBody()) assertThat(result.getBody())
.isEqualTo("[{\"value\":\"[FOO]\"},{\"value\":\"[BAR]\"}]"); .isEqualTo("[{\"value\":\"[FOO]\"},{\"value\":\"[BAR]\"}]");
@@ -249,18 +257,21 @@ public class RestApplicationTests {
@Test @Test
public void uppercaseSingleValue() throws Exception { public void uppercaseSingleValue() throws Exception {
ResponseEntity<String> result = rest.exchange(RequestEntity ResponseEntity<String> result = rest
.post(new URI("/uppercase")).contentType(MediaType.TEXT_PLAIN) .exchange(
.body("foo"), String.class); RequestEntity.post(new URI("/uppercase"))
.contentType(MediaType.TEXT_PLAIN).body("foo"),
String.class);
assertThat(result.getBody()).isEqualTo("(FOO)"); assertThat(result.getBody()).isEqualTo("(FOO)");
} }
@Test @Test
@Ignore("WebFlux would split the request body into lines: TODO make this work the same") @Ignore("WebFlux would split the request body into lines: TODO make this work the same")
public void uppercasePlainText() throws Exception { public void uppercasePlainText() throws Exception {
ResponseEntity<String> result = rest.exchange(RequestEntity ResponseEntity<String> result = rest.exchange(
.post(new URI("/uppercase")).contentType(MediaType.TEXT_PLAIN) RequestEntity.post(new URI("/uppercase"))
.body("foo\nbar"), String.class); .contentType(MediaType.TEXT_PLAIN).body("foo\nbar"),
String.class);
assertThat(result.getBody()).isEqualTo("(FOO)(BAR)"); assertThat(result.getBody()).isEqualTo("(FOO)(BAR)");
} }
@@ -279,8 +290,7 @@ public class RestApplicationTests {
ResponseEntity<String> result = rest.exchange(RequestEntity ResponseEntity<String> result = rest.exchange(RequestEntity
.post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON)
.body("{\"value\":\"foo\"}"), String.class); .body("{\"value\":\"foo\"}"), String.class);
assertThat(result.getBody()) assertThat(result.getBody()).isEqualTo("[{\"value\":\"FOO\"}]");
.isEqualTo("[{\"value\":\"FOO\"}]");
} }
@Test @Test
@@ -294,12 +304,12 @@ public class RestApplicationTests {
@Test @Test
public void bareUppercaseFoo() throws Exception { 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<String> result = rest.exchange(RequestEntity ResponseEntity<String> result = rest.exchange(RequestEntity
.post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON)
.body("{\"value\":\"foo\"}"), String.class); .body("{\"value\":\"foo\"}"), String.class);
assertThat(result.getBody()) assertThat(result.getBody()).isEqualTo("{\"value\":\"FOO\"}");
.isEqualTo("{\"value\":\"FOO\"}");
} }
@Test @Test
@@ -430,6 +440,11 @@ public class RestApplicationTests {
return () -> Flux.just("foo", "bar"); return () -> Flux.just("foo", "bar");
} }
@Bean
public Supplier<String> word() {
return () -> "foo";
}
@Bean @Bean
public Supplier<Flux<Foo>> foos() { public Supplier<Flux<Foo>> foos() {
return () -> Flux.just(new Foo("foo"), new Foo("bar")); return () -> Flux.just(new Foo("foo"), new Foo("bar"));