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;
|
package org.springframework.cloud.function.deployer;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
@@ -144,6 +146,28 @@ public class ApplicationRunner {
|
|||||||
return false;
|
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) {
|
public Object evaluate(String expression, Object root, Object... attrs) {
|
||||||
Expression parsed = new SpelExpressionParser(this.config)
|
Expression parsed = new SpelExpressionParser(this.config)
|
||||||
.parseExpression(expression);
|
.parseExpression(expression);
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ import java.net.URLClassLoader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -114,7 +116,7 @@ class FunctionCreatorConfiguration {
|
|||||||
"Locating function from " + Arrays.asList(properties.getLocation()));
|
"Locating function from " + Arrays.asList(properties.getLocation()));
|
||||||
this.creator = new BeanCreator(urls);
|
this.creator = new BeanCreator(urls);
|
||||||
this.creator.run(properties.getMain());
|
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);
|
.forEach(this.creator::register);
|
||||||
if (properties.getName().contains("|")) {
|
if (properties.getName().contains("|")) {
|
||||||
// A composite function has to be explicitly registered before it is
|
// 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
|
@PreDestroy
|
||||||
public void close() {
|
public void close() {
|
||||||
if (this.creator != null) {
|
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) {
|
public Object create(String type) {
|
||||||
ClassLoader contextClassLoader = ClassUtils
|
ClassLoader contextClassLoader = ClassUtils
|
||||||
.overrideThreadContextClassLoader(functionClassLoader);
|
.overrideThreadContextClassLoader(functionClassLoader);
|
||||||
|
|||||||
@@ -95,9 +95,5 @@ public class FunctionProperties {
|
|||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No archive location provided, please configure function.location as a jar or directory.");
|
"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.junit.Test;
|
||||||
|
|
||||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
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.Doubler;
|
||||||
import org.springframework.cloud.function.test.FunctionApp;
|
import org.springframework.cloud.function.test.FunctionApp;
|
||||||
import org.springframework.cloud.function.test.FunctionRegistrar;
|
import org.springframework.cloud.function.test.FunctionRegistrar;
|
||||||
@@ -43,14 +44,13 @@ public class ApplicationRunnerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore // related to boot 2.1 no bean override change
|
|
||||||
public void functional() {
|
public void functional() {
|
||||||
ApplicationRunner runner = new ApplicationRunner(getClass().getClassLoader(),
|
ApplicationRunner runner = new ApplicationRunner(getClass().getClassLoader(),
|
||||||
FunctionRegistrar.class.getName());
|
FunctionRegistrar.class.getName());
|
||||||
runner.run();
|
runner.run();
|
||||||
assertThat(runner.containsBean(Doubler.class.getName())).isTrue();
|
assertThat(runner.containsBean(Doubler.class.getName())).isFalse();
|
||||||
assertThat(runner.getBean(Doubler.class.getName())).isNotNull();
|
|
||||||
assertThat(runner.getBean(FunctionCatalog.class.getName())).isNotNull();
|
assertThat(runner.getBean(FunctionCatalog.class.getName())).isNotNull();
|
||||||
|
assertThat(runner.getBeanNames(FunctionRegistration.class.getName())).hasSize(2);
|
||||||
runner.close();
|
runner.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user