diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java index 3b64b7131..2edc0a31f 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java @@ -474,6 +474,7 @@ public class ContextFunctionCatalogAutoConfiguration { type = Function.class; findType(target, ParamType.INPUT); findType(target, ParamType.OUTPUT); + isMessage(target); // cache wrapper types registration.target(target((Function) target, key)); for (String name : registration.getNames()) { this.functions.put(name, (Function) registration.getTarget()); @@ -559,10 +560,11 @@ public class ContextFunctionCatalogAutoConfiguration { return FunctionInspector .isWrapper(findType(function, ParamType.INPUT_WRAPPER)) || FunctionInspector - .isWrapper(findType(function, ParamType.OUTPUT_WRAPPER)); + .isWrapper(findType(function, ParamType.OUTPUT_WRAPPER)); } - private Class findType(String name, AbstractBeanDefinition definition, ParamType paramType) { + private Class findType(String name, AbstractBeanDefinition definition, + ParamType paramType) { Object source = definition.getSource(); Type param = null; // Start by assuming output -> Function @@ -710,10 +712,12 @@ public class ContextFunctionCatalogAutoConfiguration { } private boolean isMessage(Object function) { - return Message.class - .isAssignableFrom(findType(function, ParamType.INPUT_INNER_WRAPPER)) - || Message.class.isAssignableFrom( - findType(function, ParamType.OUTPUT_INNER_WRAPPER)); + Class inputType = findType(function, ParamType.INPUT_INNER_WRAPPER); + Class outputType = findType(function, ParamType.OUTPUT_INNER_WRAPPER); + return inputType.getName().startsWith(Message.class.getName()) + || Message.class.isAssignableFrom(inputType) + || outputType.getName().startsWith(Message.class.getName()) + || Message.class.isAssignableFrom(outputType); } private Class findType(Object function, ParamType type) { diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java index 6391abb44..5d93b6df2 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java @@ -233,6 +233,18 @@ public class ContextFunctionCatalogAutoConfigurationTests { .isAssignableFrom(Integer.class); } + @Test + public void singletonMessageFunction() { + create(SingletonMessageConfiguration.class); + assertThat(context.getBean("function")).isInstanceOf(Function.class); + assertThat(catalog.lookupFunction("function")).isInstanceOf(Function.class); + assertThat(inspector.getInputType(catalog.lookupFunction("function"))) + .isAssignableFrom(Integer.class); + assertThat(inspector.getInputWrapper(catalog.lookupFunction("function"))) + .isAssignableFrom(Integer.class); + assertThat(inspector.isMessage(catalog.lookupFunction("function"))).isTrue(); + } + @Test public void nonParametericTypeFunction() { create(NonParametricTypeSingletonConfiguration.class); @@ -529,6 +541,17 @@ public class ContextFunctionCatalogAutoConfigurationTests { } } + @EnableAutoConfiguration + @Configuration + protected static class SingletonMessageConfiguration implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { + beanFactory.registerSingleton("function", new SingletonMessageFunction()); + } + } + @EnableAutoConfiguration @Configuration protected static class NonParametricTypeSingletonConfiguration { @@ -547,6 +570,15 @@ public class ContextFunctionCatalogAutoConfigurationTests { } + protected static class SingletonMessageFunction implements Function, Message> { + + @Override + public Message apply(Message input) { + return MessageBuilder.withPayload("value=" + input.getPayload()).build(); + } + + } + @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = GenericFunction.class)