Fix Build and upgrade fully to Boot 2.0

Some tests still ignored.

Also adds draft functional bean registration support. The AWS sample
is using that now (it starts up 4x faster in AWS). To activate the
functional beans user has to supply a main class of type
ApplicationContextInitializer.
This commit is contained in:
Dave Syer
2018-06-21 13:00:46 +01:00
parent 00e2b749d2
commit 4c9627aee3
23 changed files with 896 additions and 54 deletions

View File

@@ -33,9 +33,12 @@ import org.reactivestreams.Publisher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.cloud.function.context.FunctionCatalog;
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.util.ClassUtils;
@@ -87,8 +90,8 @@ public class SpringFunctionInitializer implements Closeable {
return;
}
logger.info("Initializing: " + configurationClass);
SpringApplicationBuilder builder = springApplication();
ConfigurableApplicationContext context = builder.web(false).run();
SpringApplication builder = springApplication();
ConfigurableApplicationContext context = builder.run();
context.getAutowireCapableBeanFactory().autowireBean(this);
String name = context.getEnvironment().getProperty("function.name");
boolean defaultName = false;
@@ -121,17 +124,27 @@ public class SpringFunctionInitializer implements Closeable {
}
private SpringApplicationBuilder springApplication() {
if (ClassUtils.hasConstructor(SpringApplicationBuilder.class, Object[].class)) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(
configurationClass);
return builder;
private SpringApplication springApplication() {
ApplicationContextInitializer<?> initializer = null;
Class<?> sourceClass = configurationClass;
if (ApplicationContextInitializer.class.isAssignableFrom(sourceClass)) {
initializer = BeanUtils.instantiateClass(configurationClass, ApplicationContextInitializer.class);
sourceClass = Object.class;
}
// Forward compatibility with Spring Boot 2.0 via reflection
return BeanUtils.instantiateClass(
ClassUtils.getConstructorIfAvailable(SpringApplicationBuilder.class,
Class[].class),
new Object[] { new Class<?>[] { configurationClass } });
SpringApplication application;
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 = new SpringApplication(sourceClass);
}
application.setWebApplicationType(WebApplicationType.NONE);
return application;
}
protected Class<?> getInputType() {

View File

@@ -24,10 +24,14 @@ import java.util.stream.Collectors;
import org.junit.After;
import org.junit.Test;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionType;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.GenericApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@@ -65,6 +69,14 @@ public class SpringFunctionInitializerTests {
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Test
public void functionRegistrar() {
initializer = new SpringFunctionInitializer(FunctionRegistrar.class);
initializer.initialize();
Flux<?> result = Flux.from(initializer.apply(Flux.just(new Foo())));
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Test
public void namedFunctionCatalog() {
initializer = new SpringFunctionInitializer(NamedFunctionConfig.class);
@@ -98,6 +110,23 @@ public class SpringFunctionInitializerTests {
}
}
protected static class FunctionRegistrar
implements ApplicationContextInitializer<GenericApplicationContext> {
public Function<Flux<Foo>, Flux<Bar>> function() {
return flux -> flux.map(foo -> new Bar());
}
@Override
public void initialize(GenericApplicationContext context) {
context.registerBean("function", FunctionRegistration.class,
() -> new FunctionRegistration<Function<Flux<Foo>, Flux<Bar>>>(
function()).name("function")
.type(FunctionType.from(Foo.class).to(Bar.class)
.wrap(Flux.class).getType()));
}
}
@Configuration
@Import(ContextFunctionCatalogAutoConfiguration.class)
protected static class FunctionConfig {