diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializer.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializer.java index 8d86e0877..5f70cf78b 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializer.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializer.java @@ -18,6 +18,7 @@ package org.springframework.cloud.function.adapter.aws; import java.io.Closeable; import java.io.InputStream; +import java.lang.reflect.Type; import java.net.URL; import java.util.Collections; import java.util.List; @@ -35,12 +36,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.cloud.function.context.FunctionRegistration; +import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.catalog.FunctionInspector; +import org.springframework.cloud.function.context.config.FunctionContextUtils; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.util.ClassUtils; /** * @author Dave Syer + * @author Oleg Zhurakousky */ public class SpringFunctionInitializer implements Closeable { @@ -121,14 +126,13 @@ public class SpringFunctionInitializer implements Closeable { } } - @SuppressWarnings("unchecked") protected void initialize() { if (!this.initialized.compareAndSet(false, true)) { return; } logger.info("Initializing: " + this.configurationClass); SpringApplication builder = springApplication(); - ConfigurableApplicationContext context = builder.run(); + this.context = builder.run(); context.getAutowireCapableBeanFactory().autowireBean(this); String name = context.getEnvironment().getProperty("function.name"); if (name == null) { @@ -136,7 +140,7 @@ public class SpringFunctionInitializer implements Closeable { } if (this.catalog == null) { if (context.containsBean(name)) { - this.function = context.getBean(name, Function.class); + this.function = getAndInstrumentFromContext(name); } } else { @@ -149,8 +153,16 @@ public class SpringFunctionInitializer implements Closeable { this.function = this.catalog.lookup(Function.class, name); } } - this.context = context; + } + @SuppressWarnings({ "unchecked", "rawtypes" }) + private T getAndInstrumentFromContext(String name) { + FunctionRegistration functionRegistration = new FunctionRegistration( + context.getBean(name), name); + + Type type = FunctionContextUtils.findType(name, this.context.getBeanFactory()); + FunctionType functionType = new FunctionType(type); + return (T) functionRegistration.type(functionType).wrap().getTarget(); } private SpringApplication springApplication() { diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializerTests.java index 96bbaba6d..c29d24d5c 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializerTests.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringFunctionInitializerTests.java @@ -60,6 +60,14 @@ public class SpringFunctionInitializerTests { assertThat(result.blockFirst()).isInstanceOf(Bar.class); } + @Test + public void functionNonFluxBean() { + this.initializer = new SpringFunctionInitializer(NonFluxFunctionConfig.class); + this.initializer.initialize(); + Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); + assertThat(result.blockFirst()).isInstanceOf(Bar.class); + } + @Test public void functionApp() { this.initializer = new SpringFunctionInitializer(FluxFunctionApp.class); @@ -112,6 +120,16 @@ public class SpringFunctionInitializerTests { } + @Configuration + protected static class NonFluxFunctionConfig { + + @Bean + public Function function() { + return foo -> new Bar(); + } + + } + protected static class FluxFunctionApp implements Function, Flux> { @Override diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java index 68f3ee808..d2b9efbd0 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java @@ -19,6 +19,7 @@ package org.springframework.cloud.function.adapter.azure; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Type; import java.net.URL; import java.util.Collection; import java.util.Collections; @@ -36,12 +37,16 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.cloud.function.context.FunctionRegistration; +import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.catalog.FunctionInspector; +import org.springframework.cloud.function.context.config.FunctionContextUtils; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.util.ClassUtils; /** * @author Soby Chacko + * @author Oleg Zhurakousky */ public class AzureSpringFunctionInitializer implements Closeable { @@ -125,7 +130,6 @@ public class AzureSpringFunctionInitializer implements Closeable { } } - @SuppressWarnings("unchecked") protected void initialize(ExecutionContext ctxt) { ConfigurableApplicationContext context = AzureSpringFunctionInitializer.context; @@ -164,7 +168,7 @@ public class AzureSpringFunctionInitializer implements Closeable { ctxt.getLogger() .info("No catalog. Looking for Function bean name=" + name); } - this.function = context.getBean(name, Function.class); + this.function = getAndInstrumentFromContext(context, name); } } else { @@ -179,6 +183,18 @@ public class AzureSpringFunctionInitializer implements Closeable { } } + @SuppressWarnings({ "unchecked", "rawtypes" }) + private T getAndInstrumentFromContext( + ConfigurableApplicationContext applicationContext, String name) { + FunctionRegistration functionRegistration = new FunctionRegistration( + applicationContext.getBean(name), name); + + Type type = FunctionContextUtils.findType(name, + applicationContext.getBeanFactory()); + FunctionType functionType = new FunctionType(type); + return (T) functionRegistration.type(functionType).wrap().getTarget(); + } + private SpringApplication springApplication() { Class sourceClass = this.configurationClass; SpringApplication application = new org.springframework.cloud.function.context.FunctionalSpringApplication( diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializerTests.java index 3303490ed..5c398dbaf 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializerTests.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializerTests.java @@ -29,6 +29,7 @@ import org.springframework.cloud.function.context.FunctionRegistration; import org.springframework.cloud.function.context.FunctionType; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.support.GenericApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -82,6 +83,14 @@ public class AzureSpringFunctionInitializerTests { assertThat(bar.getValue()).isEqualTo("BAR"); } + @Test + public void functionNonFluxBean() { + AzureSpringFunctionInitializer handler = handler(NonFluxFunctionConfig.class); + handler.initialize(new TestExecutionContext("function")); + Flux result = Flux.from(handler.getFunction().apply(Flux.just(new Foo()))); + assertThat(result.blockFirst()).isInstanceOf(Bar.class); + } + @SpringBootConfiguration @EnableAutoConfiguration protected static class BareConfig { @@ -121,4 +130,14 @@ public class AzureSpringFunctionInitializerTests { } + @Configuration + protected static class NonFluxFunctionConfig { + + @Bean + public Function function() { + return foo -> new Bar(); + } + + } + } diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java index aad4d043b..cfbae2e0c 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java @@ -40,7 +40,7 @@ import org.springframework.util.ReflectionUtils; * @author Oleg Zhurakousky * @since 2.0 */ -abstract class FunctionContextUtils { +public abstract class FunctionContextUtils { public static Type findType(String name, ConfigurableListableBeanFactory registry) { AbstractBeanDefinition definition = (AbstractBeanDefinition) registry