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