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 14a925855..4deab5f8c 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 @@ -38,10 +38,13 @@ 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.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.util.ClassUtils; /** @@ -135,22 +138,39 @@ public class AzureSpringFunctionInitializer implements Closeable { } private SpringApplication springApplication() { - ApplicationContextInitializer initializer = null; + ApplicationContextInitializer initializer = null; Class sourceClass = configurationClass; if (ApplicationContextInitializer.class.isAssignableFrom(sourceClass)) { - initializer = BeanUtils.instantiateClass(configurationClass, ApplicationContextInitializer.class); + @SuppressWarnings("unchecked") + ApplicationContextInitializer instance = BeanUtils + .instantiateClass(configurationClass, + ApplicationContextInitializer.class); + initializer = instance; + sourceClass = Object.class; + } + else if (Function.class.isAssignableFrom(sourceClass)) { + @SuppressWarnings("unchecked") + final Class> type = (Class>) sourceClass; + initializer = context -> { + context.registerBean(FunctionRegistration.class, + () -> new FunctionRegistration<>( + context.getAutowireCapableBeanFactory().createBean(type)) + .type(FunctionType.of(type))); + }; sourceClass = Object.class; } SpringApplication application; - if (initializer!=null) { + if (initializer != null) { application = new SpringApplication(sourceClass) { @Override protected void load(ApplicationContext context, Object[] sources) { } }; application.addInitializers(initializer); - application.setDefaultProperties(Collections.singletonMap("spring.functional.enabled", "true")); - } else { + application.setDefaultProperties( + Collections.singletonMap("spring.functional.enabled", "true")); + } + else { application = new SpringApplication(sourceClass); } application.setWebApplicationType(WebApplicationType.NONE); @@ -240,4 +260,16 @@ public class AzureSpringFunctionInitializer implements Closeable { } return null; } + + public Function, Publisher> getFunction() { + return function; + } + + public FunctionCatalog getCatalog() { + return catalog; + } + + public FunctionInspector getInspector() { + return inspector; + } } 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 new file mode 100644 index 000000000..d5e623cf0 --- /dev/null +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializerTests.java @@ -0,0 +1,117 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.function.adapter.azure; + +import java.io.IOException; +import java.util.function.Function; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +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.support.GenericApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +import reactor.core.publisher.Flux; + +/** + * @author Dave Syer + * + */ +public class AzureSpringFunctionInitializerTests { + + private AzureSpringFunctionInitializer handler = null; + + AzureSpringFunctionInitializer handler(Class config) { + AzureSpringFunctionInitializer handler = new AzureSpringFunctionInitializer( + config); + this.handler = handler; + return handler; + } + + @After + public void close() throws IOException { + if (handler != null) + handler.close(); + } + + @Test + public void bareConfig() { + AzureSpringFunctionInitializer handler = handler(BareConfig.class); + handler.initialize(new TestExecutionContext("uppercase")); + Bar bar = (Bar) Flux.from(handler.getFunction().apply(Flux.just(new Foo("bar")))) + .blockFirst(); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @Test + public void initializer() { + AzureSpringFunctionInitializer handler = handler(InitializerConfig.class); + handler.initialize(new TestExecutionContext("uppercase")); + Bar bar = (Bar) Flux.from(handler.getFunction().apply(Flux.just(new Foo("bar")))) + .blockFirst(); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @Test + public void function() { + AzureSpringFunctionInitializer handler = handler(FunctionConfig.class); + handler.initialize(new TestExecutionContext("uppercase")); + Bar bar = (Bar) Flux.from(handler.getFunction().apply(Flux.just(new Foo("bar")))) + .blockFirst(); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @SpringBootConfiguration + @EnableAutoConfiguration + protected static class BareConfig { + @Bean + public Function function() { + return foo -> new Bar(foo.getValue().toUpperCase()); + } + } + + @SpringBootConfiguration + protected static class FunctionConfig implements Function { + @Override + public Bar apply(Foo foo) { + return new Bar(foo.getValue().toUpperCase()); + } + } + + @SpringBootConfiguration + protected static class InitializerConfig + implements ApplicationContextInitializer { + + public Function function() { + return foo -> new Bar(foo.getValue().toUpperCase()); + } + + @Override + public void initialize(GenericApplicationContext context) { + context.registerBean(FunctionRegistration.class, + () -> new FunctionRegistration>(function(), + "uppercase") + .type(FunctionType.from(Foo.class).to(Bar.class))); + } + } +}