Strangle old inspector methods
Fixes gh-81
This commit is contained in:
@@ -62,8 +62,6 @@ public class SpringFunctionInitializer implements Closeable {
|
|||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private FunctionCatalog catalog;
|
private FunctionCatalog catalog;
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
public SpringFunctionInitializer(Class<?> configurationClass) {
|
public SpringFunctionInitializer(Class<?> configurationClass) {
|
||||||
@@ -102,19 +100,16 @@ public class SpringFunctionInitializer implements Closeable {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.function = this.catalog.lookupFunction(name);
|
this.function = this.catalog.lookupFunction(name);
|
||||||
this.name = name;
|
|
||||||
if (this.function == null) {
|
if (this.function == null) {
|
||||||
if (defaultName) {
|
if (defaultName) {
|
||||||
name = "consumer";
|
name = "consumer";
|
||||||
}
|
}
|
||||||
this.consumer = this.catalog.lookupConsumer(name);
|
this.consumer = this.catalog.lookupConsumer(name);
|
||||||
this.name = name;
|
|
||||||
if (this.consumer == null) {
|
if (this.consumer == null) {
|
||||||
if (defaultName) {
|
if (defaultName) {
|
||||||
name = "supplier";
|
name = "supplier";
|
||||||
}
|
}
|
||||||
this.supplier = this.catalog.lookupSupplier(name);
|
this.supplier = this.catalog.lookupSupplier(name);
|
||||||
this.name = name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,11 +118,16 @@ public class SpringFunctionInitializer implements Closeable {
|
|||||||
|
|
||||||
protected Class<?> getInputType() {
|
protected Class<?> getInputType() {
|
||||||
if (inspector != null) {
|
if (inspector != null) {
|
||||||
return inspector.getInputType(this.name);
|
return inspector.getInputType(function());
|
||||||
}
|
}
|
||||||
return Object.class;
|
return Object.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object function() {
|
||||||
|
return this.function != null ? this.function
|
||||||
|
: (this.consumer != null ? this.consumer : this.supplier);
|
||||||
|
}
|
||||||
|
|
||||||
protected Flux<?> apply(Flux<?> input) {
|
protected Flux<?> apply(Flux<?> input) {
|
||||||
if (this.function != null) {
|
if (this.function != null) {
|
||||||
return function.apply(input);
|
return function.apply(input);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public class FunctionInitializer {
|
|||||||
if ("function".equals(type)) {
|
if ("function".equals(type)) {
|
||||||
this.function = this.catalog.lookupFunction(name);
|
this.function = this.catalog.lookupFunction(name);
|
||||||
if (this.function != null && !FunctionUtils.isFluxFunction(this.function)) {
|
if (this.function != null && !FunctionUtils.isFluxFunction(this.function)) {
|
||||||
|
// TODO: this shouldn't be necessary
|
||||||
this.function = new FluxFunction(this.function);
|
this.function = new FluxFunction(this.function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,11 +76,16 @@ public class FunctionInitializer {
|
|||||||
|
|
||||||
protected Class<?> getInputType() {
|
protected Class<?> getInputType() {
|
||||||
if (inspector != null) {
|
if (inspector != null) {
|
||||||
return inspector.getInputType(this.properties.getName());
|
return inspector.getInputType(function());
|
||||||
}
|
}
|
||||||
return Object.class;
|
return Object.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object function() {
|
||||||
|
return this.function != null ? this.function
|
||||||
|
: (this.consumer != null ? this.consumer : this.supplier);
|
||||||
|
}
|
||||||
|
|
||||||
protected Flux<?> apply(Flux<?> input) {
|
protected Flux<?> apply(Flux<?> input) {
|
||||||
if (this.function != null) {
|
if (this.function != null) {
|
||||||
return function.apply(input);
|
return function.apply(input);
|
||||||
|
|||||||
@@ -110,33 +110,8 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMessage(String name) {
|
public boolean isMessage(Object function) {
|
||||||
return processor.isMessage(name);
|
return processor.isMessage(function);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getInputWrapper(String name) {
|
|
||||||
return processor.findInputWrapper(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getOutputWrapper(String name) {
|
|
||||||
return processor.findOutputWrapper(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getInputType(String name) {
|
|
||||||
return processor.findInputType(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getOutputType(String name) {
|
|
||||||
return processor.findOutputType(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object convert(String name, String value) {
|
|
||||||
return processor.convert(name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -178,13 +153,10 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
private Set<String> suppliers = new HashSet<>();
|
private Set<String> suppliers = new HashSet<>();
|
||||||
private Set<String> functions = new HashSet<>();
|
private Set<String> functions = new HashSet<>();
|
||||||
private Set<String> consumers = new HashSet<>();
|
private Set<String> consumers = new HashSet<>();
|
||||||
private Map<String, String> beans = new HashMap<>();
|
|
||||||
|
|
||||||
private BeanDefinitionRegistry registry;
|
private BeanDefinitionRegistry registry;
|
||||||
private ConversionService conversionService;
|
private ConversionService conversionService;
|
||||||
private Map<Object, String> registrations = new HashMap<>();
|
private Map<Object, String> registrations = new HashMap<>();
|
||||||
// TODO: keys are not unique
|
|
||||||
private Map<String, Object> reverse = new HashMap<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
||||||
@@ -210,10 +182,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
: value;
|
: value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object convert(String name, String value) {
|
|
||||||
return convert(reverse.get(name), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<FunctionRegistration<?>> merge(
|
public Set<FunctionRegistration<?>> merge(
|
||||||
Map<String, FunctionRegistration<?>> initial,
|
Map<String, FunctionRegistration<?>> initial,
|
||||||
Map<String, Consumer<?>> consumers, Map<String, Supplier<?>> suppliers,
|
Map<String, Consumer<?>> consumers, Map<String, Supplier<?>> suppliers,
|
||||||
@@ -281,11 +249,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
|
|
||||||
private void wrap(FunctionRegistration<Object> registration, String key) {
|
private void wrap(FunctionRegistration<Object> registration, String key) {
|
||||||
Object target = registration.getTarget();
|
Object target = registration.getTarget();
|
||||||
this.registrations.put(registration.getTarget(), key);
|
this.registrations.put(target, key);
|
||||||
for (String name : registration.getNames()) {
|
|
||||||
beans.put(name, key);
|
|
||||||
this.reverse.put(name, registration.getTarget());
|
|
||||||
}
|
|
||||||
if (target instanceof Supplier) {
|
if (target instanceof Supplier) {
|
||||||
registration.target(target((Supplier<?>) target, key));
|
registration.target(target((Supplier<?>) target, key));
|
||||||
}
|
}
|
||||||
@@ -295,9 +259,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
else if (target instanceof Function) {
|
else if (target instanceof Function) {
|
||||||
registration.target(target((Function<?, ?>) target, key));
|
registration.target(target((Function<?, ?>) target, key));
|
||||||
}
|
}
|
||||||
for (String name : registration.getNames()) {
|
registrations.remove(target);
|
||||||
this.reverse.put(name, registration.getTarget());
|
|
||||||
}
|
|
||||||
this.registrations.put(registration.getTarget(), key);
|
this.registrations.put(registration.getTarget(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,23 +346,23 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFluxFunction(String name, Function<?, ?> function) {
|
private boolean isFluxFunction(String name, Function<?, ?> function) {
|
||||||
boolean fluxTypes = this.hasFluxTypes(name);
|
boolean fluxTypes = this.hasFluxTypes(function);
|
||||||
return fluxTypes || FunctionUtils.isFluxFunction(function);
|
return fluxTypes || FunctionUtils.isFluxFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFluxConsumer(String name, Consumer<?> consumer) {
|
private boolean isFluxConsumer(String name, Consumer<?> consumer) {
|
||||||
boolean fluxTypes = this.hasFluxTypes(name);
|
boolean fluxTypes = this.hasFluxTypes(consumer);
|
||||||
return fluxTypes || FunctionUtils.isFluxConsumer(consumer);
|
return fluxTypes || FunctionUtils.isFluxConsumer(consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFluxSupplier(String name, Supplier<?> supplier) {
|
private boolean isFluxSupplier(String name, Supplier<?> supplier) {
|
||||||
boolean fluxTypes = this.hasFluxTypes(name);
|
boolean fluxTypes = this.hasFluxTypes(supplier);
|
||||||
return fluxTypes || FunctionUtils.isFluxSupplier(supplier);
|
return fluxTypes || FunctionUtils.isFluxSupplier(supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasFluxTypes(String name) {
|
private boolean hasFluxTypes(Object function) {
|
||||||
return FunctionInspector.isWrapper(findInputWrapper(name))
|
return FunctionInspector.isWrapper(findInputWrapper(function))
|
||||||
|| FunctionInspector.isWrapper(findOutputWrapper(name));
|
|| FunctionInspector.isWrapper(findOutputWrapper(function));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isGenericSupplier(ConfigurableListableBeanFactory factory,
|
private boolean isGenericSupplier(ConfigurableListableBeanFactory factory,
|
||||||
@@ -569,10 +531,8 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
return ReflectionUtils.getField(field, target);
|
return ReflectionUtils.getField(field, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMessage(String name) {
|
private boolean isMessage(Object function) {
|
||||||
if (name != null) {
|
String name = registrations.get(function);
|
||||||
name = beans.get(name);
|
|
||||||
}
|
|
||||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -582,7 +542,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
|| Message.class.isAssignableFrom(findType(name,
|
|| Message.class.isAssignableFrom(findType(name,
|
||||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||||
ParamType.OUTPUT_INNER_WRAPPER));
|
ParamType.OUTPUT_INNER_WRAPPER));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> findInputWrapper(Object function) {
|
private Class<?> findInputWrapper(Object function) {
|
||||||
@@ -595,14 +554,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
ParamType.INPUT_WRAPPER);
|
ParamType.INPUT_WRAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> findInputWrapper(String name) {
|
|
||||||
return findInputWrapper(function(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object function(String name) {
|
|
||||||
return reverse.containsKey(name) ? reverse.get(name) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> findOutputWrapper(Object function) {
|
private Class<?> findOutputWrapper(Object function) {
|
||||||
String name = registrations.get(function);
|
String name = registrations.get(function);
|
||||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||||
@@ -613,10 +564,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
ParamType.OUTPUT_WRAPPER);
|
ParamType.OUTPUT_WRAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> findOutputWrapper(String name) {
|
|
||||||
return findOutputWrapper(reverse.get(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> findInputType(Object function) {
|
private Class<?> findInputType(Object function) {
|
||||||
String name = registrations.get(function);
|
String name = registrations.get(function);
|
||||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||||
@@ -627,10 +574,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
ParamType.INPUT);
|
ParamType.INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> findInputType(String name) {
|
|
||||||
return findInputType(reverse.get(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> findOutputType(Object function) {
|
private Class<?> findOutputType(Object function) {
|
||||||
String name = registrations.get(function);
|
String name = registrations.get(function);
|
||||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||||
@@ -641,10 +584,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
ParamType.OUTPUT);
|
ParamType.OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> findOutputType(String name) {
|
|
||||||
return findOutputType(reverse.get(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum ParamType {
|
static enum ParamType {
|
||||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
||||||
|
|
||||||
|
|||||||
@@ -28,19 +28,7 @@ import reactor.core.publisher.Mono;
|
|||||||
*/
|
*/
|
||||||
public interface FunctionInspector {
|
public interface FunctionInspector {
|
||||||
|
|
||||||
boolean isMessage(String name);
|
boolean isMessage(Object function);
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Class<?> getInputType(String name);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Class<?> getOutputType(String name);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Class<?> getInputWrapper(String name);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Class<?> getOutputWrapper(String name);
|
|
||||||
|
|
||||||
Class<?> getInputType(Object function);
|
Class<?> getInputType(Object function);
|
||||||
|
|
||||||
@@ -50,9 +38,6 @@ public interface FunctionInspector {
|
|||||||
|
|
||||||
Class<?> getOutputWrapper(Object function);
|
Class<?> getOutputWrapper(Object function);
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Object convert(String name, String value);
|
|
||||||
|
|
||||||
Object convert(Object function, String value);
|
Object convert(Object function, String value);
|
||||||
|
|
||||||
String getName(Object function);
|
String getName(Object function);
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import java.util.function.Supplier;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -81,14 +80,15 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("see https://github.com/spring-cloud/spring-cloud-function/issues/81")
|
|
||||||
public void ambiguousFunction() {
|
public void ambiguousFunction() {
|
||||||
create(AmbiguousConfiguration.class);
|
create(AmbiguousConfiguration.class);
|
||||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
||||||
// Could be String or Foo
|
assertThat(inspector.getInputType(catalog.lookupFunction("foos")))
|
||||||
assertThat(inspector.getInputType("foos")).isEqualTo(Foo.class);
|
.isEqualTo(String.class);
|
||||||
|
assertThat(inspector.getInputType(catalog.lookupConsumer("foos")))
|
||||||
|
.isEqualTo(Foo.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +97,10 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(GenericConfiguration.class);
|
create(GenericConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(Map.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Map.class);
|
.isAssignableFrom(Map.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -106,9 +108,11 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(FluxMessageConfiguration.class);
|
create(FluxMessageConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.isMessage("function")).isTrue();
|
assertThat(inspector.isMessage(catalog.lookupFunction("function"))).isTrue();
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(String.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Flux.class);
|
.isAssignableFrom(String.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Flux.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -116,9 +120,11 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(MessageConfiguration.class);
|
create(MessageConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.isMessage("function")).isTrue();
|
assertThat(inspector.isMessage(catalog.lookupFunction("function"))).isTrue();
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(String.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(String.class);
|
.isAssignableFrom(String.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -126,8 +132,10 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(GenericFluxConfiguration.class);
|
create(GenericFluxConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(Map.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Flux.class);
|
.isAssignableFrom(Map.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Flux.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -135,8 +143,10 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(ExternalConfiguration.class);
|
create(ExternalConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(Map.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Map.class);
|
.isAssignableFrom(Map.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -144,8 +154,10 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(ComponentScanBeanConfiguration.class);
|
create(ComponentScanBeanConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(Map.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Map.class);
|
.isAssignableFrom(Map.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -153,8 +165,10 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create(ComponentScanConfiguration.class);
|
create(ComponentScanConfiguration.class);
|
||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("function")).isAssignableFrom(Map.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("function")))
|
||||||
assertThat(inspector.getInputWrapper("function")).isAssignableFrom(Map.class);
|
.isAssignableFrom(Map.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("function")))
|
||||||
|
.isAssignableFrom(Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -163,8 +177,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
create("greeter.jar", ComponentScanJarConfiguration.class);
|
create("greeter.jar", ComponentScanJarConfiguration.class);
|
||||||
assertThat(context.getBean("greeter")).isInstanceOf(Function.class);
|
assertThat(context.getBean("greeter")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("greeter")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("greeter")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("greeter")).isAssignableFrom(String.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("greeter")))
|
||||||
assertThat(inspector.getInputWrapper("greeter"))
|
.isAssignableFrom(String.class);
|
||||||
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("greeter")))
|
||||||
.isAssignableFrom(String.class);
|
.isAssignableFrom(String.class);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -207,7 +222,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("function")).isNull();
|
assertThat(catalog.lookupFunction("function")).isNull();
|
||||||
assertThat(catalog.lookupFunction("other")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("other")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputType("other")).isEqualTo(String.class);
|
assertThat(inspector.getInputType(catalog.lookupFunction("other")))
|
||||||
|
.isEqualTo(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -235,7 +251,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
"spring.cloud.function.compile.foos.outputType=String");
|
"spring.cloud.function.compile.foos.outputType=String");
|
||||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputWrapper("foos")).isEqualTo(String.class);
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("foos")))
|
||||||
|
.isEqualTo(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -249,7 +266,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
"spring.cloud.function.import.foos.location=file:./target/foos.fun");
|
"spring.cloud.function.import.foos.location=file:./target/foos.fun");
|
||||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
assertThat(catalog.lookupFunction("foos")).isInstanceOf(Function.class);
|
||||||
assertThat(inspector.getInputWrapper("foos")).isEqualTo(String.class);
|
assertThat(inspector.getInputWrapper(catalog.lookupFunction("foos")))
|
||||||
|
.isEqualTo(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -260,7 +278,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
"spring.cloud.function.compile.foos.type=consumer",
|
"spring.cloud.function.compile.foos.type=consumer",
|
||||||
"spring.cloud.function.compile.foos.inputType=String");
|
"spring.cloud.function.compile.foos.inputType=String");
|
||||||
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
||||||
assertThat(inspector.getInputWrapper("foos")).isEqualTo(String.class);
|
assertThat(inspector.getInputWrapper(catalog.lookupConsumer("foos")))
|
||||||
|
.isEqualTo(String.class);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Consumer<String> consumer = (Consumer<String>) context.getBean("foos");
|
Consumer<String> consumer = (Consumer<String>) context.getBean("foos");
|
||||||
consumer.accept("hello");
|
consumer.accept("hello");
|
||||||
@@ -274,7 +293,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
+ getClass().getName() + "::set)",
|
+ getClass().getName() + "::set)",
|
||||||
"spring.cloud.function.compile.foos.type=consumer");
|
"spring.cloud.function.compile.foos.type=consumer");
|
||||||
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
assertThat(catalog.lookupConsumer("foos")).isInstanceOf(Consumer.class);
|
||||||
assertThat(inspector.getInputWrapper("foos")).isEqualTo(Flux.class);
|
assertThat(inspector.getInputWrapper(catalog.lookupConsumer("foos")))
|
||||||
|
.isEqualTo(Flux.class);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Consumer<Flux<String>> consumer = (Consumer<Flux<String>>) context
|
Consumer<Flux<String>> consumer = (Consumer<Flux<String>>) context
|
||||||
.getBean("foos");
|
.getBean("foos");
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ public class FunctionExtractingFunctionCatalog
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMessage(String name) {
|
public boolean isMessage(Object function) {
|
||||||
return (Boolean) inspect(name, "isMessage");
|
return (Boolean) inspect(function, "isMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -138,31 +138,6 @@ public class FunctionExtractingFunctionCatalog
|
|||||||
return inspect(function, "convert");
|
return inspect(function, "convert");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getInputType(String name) {
|
|
||||||
return (Class<?>) inspect(name, "getInputType");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getOutputType(String name) {
|
|
||||||
return (Class<?>) inspect(name, "getOutputType");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getInputWrapper(String name) {
|
|
||||||
return (Class<?>) inspect(name, "getInputWrapper");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getOutputWrapper(String name) {
|
|
||||||
return (Class<?>) inspect(name, "getOutputWrapper");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object convert(String name, String value) {
|
|
||||||
return inspect(name, "convert");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName(Object function) {
|
public String getName(Object function) {
|
||||||
return (String) inspect(function, "getName");
|
return (String) inspect(function, "getName");
|
||||||
|
|||||||
@@ -87,13 +87,14 @@ public class StreamListeningConsumerInvoker implements SmartInitializingSingleto
|
|||||||
.containsKey(StreamConfigurationProperties.ROUTE_KEY)) {
|
.containsKey(StreamConfigurationProperties.ROUTE_KEY)) {
|
||||||
String key = (String) input.getHeaders()
|
String key = (String) input.getHeaders()
|
||||||
.get(StreamConfigurationProperties.ROUTE_KEY);
|
.get(StreamConfigurationProperties.ROUTE_KEY);
|
||||||
if (functionCatalog.lookupFunction(key) != null) {
|
if (functionCatalog.lookupConsumer(key) != null) {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (String candidate : names) {
|
for (String candidate : names) {
|
||||||
Class<?> inputType = functionInspector.getInputType(candidate);
|
Class<?> inputType = functionInspector
|
||||||
|
.getInputType(functionCatalog.lookupConsumer(candidate));
|
||||||
Object value = this.converter.fromMessage(input, inputType);
|
Object value = this.converter.fromMessage(input, inputType);
|
||||||
if (value != null && inputType.isInstance(value)) {
|
if (value != null && inputType.isInstance(value)) {
|
||||||
name = candidate;
|
name = candidate;
|
||||||
@@ -110,7 +111,8 @@ public class StreamListeningConsumerInvoker implements SmartInitializingSingleto
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Function<Message<?>, Object> convertInput(String name) {
|
private Function<Message<?>, Object> convertInput(String name) {
|
||||||
Class<?> inputType = functionInspector.getInputType(name);
|
Class<?> inputType = functionInspector
|
||||||
|
.getInputType(functionCatalog.lookupConsumer(name));
|
||||||
return m -> {
|
return m -> {
|
||||||
if (Message.class.isAssignableFrom(inputType)) {
|
if (Message.class.isAssignableFrom(inputType)) {
|
||||||
return m;
|
return m;
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ package org.springframework.cloud.function.stream;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
@@ -85,17 +84,21 @@ public class StreamListeningFunctionInvoker implements SmartInitializingSingleto
|
|||||||
input.groupBy(this::select).flatMap(group -> group.key().process(group)));
|
input.groupBy(this::select).flatMap(group -> group.key().process(group)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: the routing key could be added here, but really it should be added in
|
||||||
|
// Spring Cloud Stream
|
||||||
|
// (https://github.com/spring-cloud/spring-cloud-stream/issues/1010)
|
||||||
private Flux<Message<?>> function(String name, Flux<Message<?>> flux) {
|
private Flux<Message<?>> function(String name, Flux<Message<?>> flux) {
|
||||||
// TODO: the routing key could be added here, but really it should be added in
|
Function<Object, Flux<?>> function = functionCatalog.lookupFunction(name);
|
||||||
// Spring Cloud Stream
|
return flux.publish(values -> {
|
||||||
// (https://github.com/spring-cloud/spring-cloud-stream/issues/1010)
|
Flux<?> result = function
|
||||||
AtomicReference<Map<String, Object>> headers = new AtomicReference<Map<String, Object>>(
|
.apply(values.map(message -> convertInput(function).apply(message)));
|
||||||
new LinkedHashMap<>());
|
Flux<Map<String, Object>> aggregate = headers(values);
|
||||||
return ((Flux<?>) functionCatalog.lookupFunction(name).apply(flux.map(message -> {
|
return result.withLatestFrom(aggregate, (p, m) -> message(p, m));
|
||||||
Object applied = convertInput(name).apply(message);
|
});
|
||||||
headers.set(message.getHeaders());
|
}
|
||||||
return applied;
|
|
||||||
}))).map(result -> message(result, headers.get()));
|
private Flux<Map<String, Object>> headers(Flux<Message<?>> flux) {
|
||||||
|
return flux.map(message -> message.getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message<?> message(Object result, Map<String, Object> headers) {
|
private Message<?> message(Object result, Map<String, Object> headers) {
|
||||||
@@ -104,8 +107,8 @@ public class StreamListeningFunctionInvoker implements SmartInitializingSingleto
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Flux<Message<?>> consumer(String name, Flux<Message<?>> flux) {
|
private Flux<Message<?>> consumer(String name, Flux<Message<?>> flux) {
|
||||||
functionCatalog.lookupConsumer(name)
|
Consumer<Object> consumer = functionCatalog.lookupConsumer(name);
|
||||||
.accept(flux.map(message -> convertInput(name).apply(message)));
|
consumer.accept(flux.map(message -> convertInput(consumer).apply(message)));
|
||||||
return Flux.empty();
|
return Flux.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +152,8 @@ public class StreamListeningFunctionInvoker implements SmartInitializingSingleto
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (String candidate : names) {
|
for (String candidate : names) {
|
||||||
Class<?> inputType = functionInspector.getInputType(candidate);
|
Class<?> inputType = functionInspector
|
||||||
|
.getInputType(functionCatalog.lookupFunction(candidate));
|
||||||
Object value = this.converter.fromMessage(input, inputType);
|
Object value = this.converter.fromMessage(input, inputType);
|
||||||
if (value != null && inputType.isInstance(value)) {
|
if (value != null && inputType.isInstance(value)) {
|
||||||
matches.add(candidate);
|
matches.add(candidate);
|
||||||
@@ -185,20 +189,20 @@ public class StreamListeningFunctionInvoker implements SmartInitializingSingleto
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Function<Message<?>, Object> convertInput(String name) {
|
private Function<Message<?>, Object> convertInput(Object function) {
|
||||||
Class<?> inputType = functionInspector.getInputType(name);
|
Class<?> inputType = functionInspector.getInputType(function);
|
||||||
return m -> {
|
return m -> {
|
||||||
if (functionInspector.isMessage(name)) {
|
if (functionInspector.isMessage(function)) {
|
||||||
return MessageBuilder.withPayload(convertPayload(name, inputType, m))
|
return MessageBuilder.withPayload(convertPayload(inputType, m))
|
||||||
.copyHeaders(m.getHeaders()).build();
|
.copyHeaders(m.getHeaders()).build();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return convertPayload(name, inputType, m);
|
return convertPayload(inputType, m);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object convertPayload(String name, Class<?> inputType, Message<?> m) {
|
private Object convertPayload(Class<?> inputType, Message<?> m) {
|
||||||
if (inputType.isAssignableFrom(m.getPayload().getClass())) {
|
if (inputType.isAssignableFrom(m.getPayload().getClass())) {
|
||||||
return m.getPayload();
|
return m.getPayload();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class FunctionController {
|
|||||||
|
|
||||||
private Mono<?> value(Function<Flux<?>, Flux<?>> function,
|
private Mono<?> value(Function<Flux<?>, Flux<?>> function,
|
||||||
@PathVariable String value) {
|
@PathVariable String value) {
|
||||||
Object input = inspector.convert(inspector.getName(function), value);
|
Object input = inspector.convert(function, value);
|
||||||
Mono<?> result = Mono.from(function.apply(Flux.just(input)));
|
Mono<?> result = Mono.from(function.apply(Flux.just(input)));
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Handled GET with function");
|
logger.debug("Handled GET with function");
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public abstract class DelegateHandler<T> {
|
|||||||
|
|
||||||
private final ListableBeanFactory factory;
|
private final ListableBeanFactory factory;
|
||||||
private FunctionInspector processor;
|
private FunctionInspector processor;
|
||||||
|
private Object handler;
|
||||||
private final Object source;
|
private final Object source;
|
||||||
|
|
||||||
public DelegateHandler(ListableBeanFactory factory, Object source) {
|
public DelegateHandler(ListableBeanFactory factory, Object source) {
|
||||||
@@ -31,9 +32,15 @@ public abstract class DelegateHandler<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> type() {
|
public Class<?> type() {
|
||||||
String name = source instanceof String ? (String) source
|
return processor().getInputType(handler());
|
||||||
: processor().getName(source);
|
}
|
||||||
return (Class<?>) processor().getInputType(name);
|
|
||||||
|
private Object handler() {
|
||||||
|
if (handler == null) {
|
||||||
|
handler = source instanceof String ? factory.getBean((String) source)
|
||||||
|
: source;
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FunctionInspector processor() {
|
private FunctionInspector processor() {
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ public class FluxHandlerMethodArgumentResolver
|
|||||||
WebDataBinderFactory binderFactory) throws Exception {
|
WebDataBinderFactory binderFactory) throws Exception {
|
||||||
Object handler = webRequest.getAttribute(WebRequestConstants.HANDLER,
|
Object handler = webRequest.getAttribute(WebRequestConstants.HANDLER,
|
||||||
NativeWebRequest.SCOPE_REQUEST);
|
NativeWebRequest.SCOPE_REQUEST);
|
||||||
Class<?> type = inspector.getInputType(inspector.getName(handler));
|
Class<?> type = inspector.getInputType(handler);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
type = Object.class;
|
type = Object.class;
|
||||||
}
|
}
|
||||||
boolean message = inspector.isMessage(inspector.getName(handler));
|
boolean message = inspector.isMessage(handler);
|
||||||
List<Object> body;
|
List<Object> body;
|
||||||
ContentCachingRequestWrapper nativeRequest = new ContentCachingRequestWrapper(
|
ContentCachingRequestWrapper nativeRequest = new ContentCachingRequestWrapper(
|
||||||
webRequest.getNativeRequest(HttpServletRequest.class));
|
webRequest.getNativeRequest(HttpServletRequest.class));
|
||||||
@@ -107,8 +107,8 @@ public class FluxHandlerMethodArgumentResolver
|
|||||||
if (message) {
|
if (message) {
|
||||||
List<Object> messages = new ArrayList<>();
|
List<Object> messages = new ArrayList<>();
|
||||||
for (Object payload : body) {
|
for (Object payload : body) {
|
||||||
messages.add(MessageBuilder.withPayload(payload).copyHeaders(
|
messages.add(MessageBuilder.withPayload(payload)
|
||||||
HeaderUtils.fromHttp(new ServletServerHttpRequest(
|
.copyHeaders(HeaderUtils.fromHttp(new ServletServerHttpRequest(
|
||||||
webRequest.getNativeRequest(HttpServletRequest.class))
|
webRequest.getNativeRequest(HttpServletRequest.class))
|
||||||
.getHeaders()))
|
.getHeaders()))
|
||||||
.build());
|
.build());
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand
|
|||||||
|
|
||||||
Object handler = webRequest.getAttribute(WebRequestConstants.HANDLER,
|
Object handler = webRequest.getAttribute(WebRequestConstants.HANDLER,
|
||||||
NativeWebRequest.SCOPE_REQUEST);
|
NativeWebRequest.SCOPE_REQUEST);
|
||||||
Class<?> type = inspector.getOutputType(inspector.getName(handler));
|
Class<?> type = inspector.getOutputType(handler);
|
||||||
|
|
||||||
boolean inputSingle = isInputSingle(webRequest, handler);
|
boolean inputSingle = isInputSingle(webRequest, handler);
|
||||||
if (inputSingle && isOutputSingle(handler)) {
|
if (inputSingle && isOutputSingle(handler)) {
|
||||||
@@ -206,9 +206,8 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOutputSingle(Object handler) {
|
private boolean isOutputSingle(Object handler) {
|
||||||
String name = inspector.getName(handler);
|
Class<?> type = inspector.getOutputType(handler);
|
||||||
Class<?> type = inspector.getOutputType(name);
|
Class<?> wrapper = inspector.getOutputWrapper(handler);
|
||||||
Class<?> wrapper = inspector.getOutputWrapper(name);
|
|
||||||
if (Stream.class.isAssignableFrom(type)) {
|
if (Stream.class.isAssignableFrom(type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user