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:
@@ -11,15 +11,14 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.12.RELEASE</version>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud-function.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-function.version>
|
||||
<wrapper.version>1.0.10.RELEASE</wrapper.version>
|
||||
<reactor.version>3.2.0.M1</reactor.version>
|
||||
<wrapper.version>1.0.12.RELEASE</wrapper.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -18,10 +18,13 @@ package org.springframework.cloud.function.deployer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
@@ -55,10 +58,20 @@ public class ContextRunner {
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
|
||||
new MapPropertySource("appDeployer", properties));
|
||||
running = true;
|
||||
SpringApplicationBuilder builder = builder(
|
||||
ClassUtils.resolveClassName(source, null));
|
||||
context = builder.environment(environment).registerShutdownHook(false)
|
||||
.run(args);
|
||||
Class<?> sourceClass = ClassUtils.resolveClassName(source, null);
|
||||
ApplicationContextInitializer<?> initializer = null;
|
||||
if (ApplicationContextInitializer.class.isAssignableFrom(sourceClass)) {
|
||||
initializer = BeanUtils.instantiateClass(sourceClass, ApplicationContextInitializer.class);
|
||||
sourceClass = Dummy.class;
|
||||
}
|
||||
SpringApplication builder = builder(sourceClass);
|
||||
if (initializer!=null) {
|
||||
builder.addInitializers(initializer);
|
||||
builder.setDefaultProperties(Collections.singletonMap("spring.functional.enabled", "true"));
|
||||
}
|
||||
builder.setEnvironment(environment);
|
||||
builder.setRegisterShutdownHook(false);
|
||||
context = builder.run(args);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
error = ex;
|
||||
@@ -117,20 +130,20 @@ public class ContextRunner {
|
||||
return this.error;
|
||||
}
|
||||
|
||||
public static SpringApplicationBuilder builder(Class<?> type) {
|
||||
// Defensive reflective builder to work with Boot 1.5 and 2.0
|
||||
if (ClassUtils.hasConstructor(SpringApplicationBuilder.class, Class[].class)) {
|
||||
return BeanUtils
|
||||
.instantiateClass(
|
||||
ClassUtils.getConstructorIfAvailable(
|
||||
SpringApplicationBuilder.class, Class[].class),
|
||||
(Object) new Class<?>[] { type });
|
||||
private static SpringApplication builder(Class<?> type) {
|
||||
if (type==Dummy.class) {
|
||||
SpringApplication application = new SpringApplication() {
|
||||
@Override
|
||||
protected void load(ApplicationContext context, Object[] sources) {
|
||||
}
|
||||
};
|
||||
// Boot doesn't allow null sources
|
||||
application.setSources(Collections.singleton(Dummy.class.getName()));
|
||||
return application;
|
||||
}
|
||||
return BeanUtils
|
||||
.instantiateClass(
|
||||
ClassUtils.getConstructorIfAvailable(
|
||||
SpringApplicationBuilder.class, Object[].class),
|
||||
(Object) new Object[] { type.getName() });
|
||||
return new SpringApplication(type);
|
||||
}
|
||||
|
||||
private class Dummy {}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ package org.springframework.cloud.function.deployer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||
import org.springframework.cloud.function.test.Doubler;
|
||||
import org.springframework.cloud.function.test.FunctionApp;
|
||||
import org.springframework.cloud.function.test.FunctionRegistrar;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -37,4 +39,15 @@ public class ApplicationRunnerTests {
|
||||
assertThat(runner.getBean(Doubler.class.getName())).isNotNull();
|
||||
runner.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void functional() {
|
||||
ApplicationRunner runner = new ApplicationRunner(getClass().getClassLoader(),
|
||||
FunctionRegistrar.class.getName());
|
||||
runner.run();
|
||||
assertThat(runner.containsBean(Doubler.class.getName())).isTrue();
|
||||
assertThat(runner.getBean(Doubler.class.getName())).isNotNull();
|
||||
assertThat(runner.getBean(FunctionCatalog.class.getName())).isNotNull();
|
||||
runner.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,38 @@ public abstract class FunctionCreatorConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@TestPropertySource(properties = {
|
||||
"function.location=app:classpath,file:target/test-classes,file:target/test-classes/app",
|
||||
"function.bean=myDoubler",
|
||||
"function.main=org.springframework.cloud.function.test.FunctionApp"})
|
||||
public static class SingleFunctionWithMainTests
|
||||
extends FunctionCreatorConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testDouble() {
|
||||
Function<Flux<Integer>, Flux<Integer>> function = catalog
|
||||
.lookup(Function.class, "function0");
|
||||
assertThat(function.apply(Flux.just(2)).blockFirst()).isEqualTo(4);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@TestPropertySource(properties = {
|
||||
"function.location=app:classpath,file:target/test-classes,file:target/test-classes/app",
|
||||
"function.bean=myDoubler",
|
||||
"function.main=org.springframework.cloud.function.test.FunctionRegistrar"})
|
||||
public static class SingleFunctionWithRegistrarTests
|
||||
extends FunctionCreatorConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testDouble() {
|
||||
Function<Flux<Integer>, Flux<Integer>> function = catalog
|
||||
.lookup(Function.class, "function0");
|
||||
assertThat(function.apply(Flux.just(2)).blockFirst()).isEqualTo(4);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@TestPropertySource(properties = { "function.location=app:classpath",
|
||||
"function.bean=org.springframework.cloud.function.test.SpringDoubler" })
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 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.test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class FunctionRegistrar
|
||||
implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||
|
||||
@Bean
|
||||
public Doubler myDoubler() {
|
||||
return new Doubler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Frenchizer myFrenchizer() {
|
||||
return new Frenchizer();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication application = new SpringApplication(Object.class) {
|
||||
@Override
|
||||
protected void load(ApplicationContext context, Object[] sources) {
|
||||
}
|
||||
};
|
||||
application.addInitializers(new FunctionRegistrar());
|
||||
application.setDefaultProperties(
|
||||
Collections.singletonMap("spring.functional.enabled", "true"));
|
||||
application.run(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(GenericApplicationContext context) {
|
||||
// TODO: support for FunctionRegistration
|
||||
context.registerBean("myDoubler", Doubler.class, () -> myDoubler());
|
||||
context.registerBean("myFrenchizer", Frenchizer.class, () -> myFrenchizer());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user