Add support for empty function.bean
If there is a unique function it should be unambiguous. This change
also supports multiple functions, but the naming is unhelpful then
("function[0,1,2,]").
This commit is contained in:
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.function.deployer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
@@ -144,6 +146,28 @@ public class ApplicationRunner {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the bean names in the application context for a given type (by its fully qualified name).
|
||||
*
|
||||
* @param type the name of the type (Class)
|
||||
* @return the bean names of that type
|
||||
*/
|
||||
public Set<String> getBeanNames(String type) {
|
||||
if (this.app != null) {
|
||||
Expression parsed = new SpelExpressionParser()
|
||||
.parseExpression("context.getBeansOfType(T(" + type + "))");
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> beans = (Map<String, Object>) parsed
|
||||
.getValue(this.app);
|
||||
return beans.keySet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Object evaluate(String expression, Object root, Object... attrs) {
|
||||
Expression parsed = new SpelExpressionParser(this.config)
|
||||
.parseExpression(expression);
|
||||
|
||||
@@ -25,7 +25,9 @@ import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
@@ -114,7 +116,7 @@ class FunctionCreatorConfiguration {
|
||||
"Locating function from " + Arrays.asList(properties.getLocation()));
|
||||
this.creator = new BeanCreator(urls);
|
||||
this.creator.run(properties.getMain());
|
||||
Arrays.stream(properties.getBean()).map(this.creator::create).sequential()
|
||||
Arrays.stream(functionNames()).map(this.creator::create).sequential()
|
||||
.forEach(this.creator::register);
|
||||
if (properties.getName().contains("|")) {
|
||||
// A composite function has to be explicitly registered before it is
|
||||
@@ -129,6 +131,13 @@ class FunctionCreatorConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private String[] functionNames() {
|
||||
if (properties.getBean() != null && properties.getBean().length > 0) {
|
||||
return properties.getBean();
|
||||
}
|
||||
return this.creator.getFunctionNames();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (this.creator != null) {
|
||||
@@ -375,6 +384,38 @@ class FunctionCreatorConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getFunctionNames() {
|
||||
Set<String> list = new LinkedHashSet<>();
|
||||
ClassLoader contextClassLoader = ClassUtils
|
||||
.overrideThreadContextClassLoader(functionClassLoader);
|
||||
try {
|
||||
if (this.runner.containsBean(FunctionCatalog.class.getName())) {
|
||||
Object catalog = this.runner.getBean(FunctionCatalog.class.getName());
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> functions = (Set<String>) this.runner
|
||||
.evaluate("getNames(#type)", catalog, "type", Function.class);
|
||||
list.addAll(functions);
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> consumers = (Set<String>) this.runner
|
||||
.evaluate("getNames(#type)", catalog, "type", Consumer.class);
|
||||
list.addAll(consumers);
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> suppliers = (Set<String>) this.runner
|
||||
.evaluate("getNames(#type)", catalog, "type", Supplier.class);
|
||||
list.addAll(suppliers);
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
list.addAll(this.runner.getBeanNames(Function.class.getName()));
|
||||
list.addAll(this.runner.getBeanNames(Consumer.class.getName()));
|
||||
list.addAll(this.runner.getBeanNames(Supplier.class.getName()));
|
||||
}
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
finally {
|
||||
ClassUtils.overrideThreadContextClassLoader(contextClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
public Object create(String type) {
|
||||
ClassLoader contextClassLoader = ClassUtils
|
||||
.overrideThreadContextClassLoader(functionClassLoader);
|
||||
|
||||
@@ -95,9 +95,5 @@ public class FunctionProperties {
|
||||
throw new IllegalStateException(
|
||||
"No archive location provided, please configure function.location as a jar or directory.");
|
||||
}
|
||||
if (bean.length == 0) {
|
||||
throw new IllegalStateException(
|
||||
"No function bean locator provided, please configure function.bean as a bean name or class name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.test.Doubler;
|
||||
import org.springframework.cloud.function.test.FunctionApp;
|
||||
import org.springframework.cloud.function.test.FunctionRegistrar;
|
||||
@@ -43,14 +44,13 @@ public class ApplicationRunnerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // related to boot 2.1 no bean override change
|
||||
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.containsBean(Doubler.class.getName())).isFalse();
|
||||
assertThat(runner.getBean(FunctionCatalog.class.getName())).isNotNull();
|
||||
assertThat(runner.getBeanNames(FunctionRegistration.class.getName())).hasSize(2);
|
||||
runner.close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user