diff --git a/docs/src/main/asciidoc/spring-cloud-function.adoc b/docs/src/main/asciidoc/spring-cloud-function.adoc index e201ed0d7..b628076d5 100644 --- a/docs/src/main/asciidoc/spring-cloud-function.adoc +++ b/docs/src/main/asciidoc/spring-cloud-function.adoc @@ -50,6 +50,23 @@ and available to us since Java 8. - Function - Consumer +In a nutshell, any bean in your Application Context that is of type `Supplier`, `Function` or `Consumer` could be registered with `FunctionCatalog`. +This means that it could benefit from all the features described in this reference manual. + +==== Filtering ineligible functions +A typical Application Context may include beans that are valid java functions, but not intended to be candidates to be registered with `FunctionCatalog`. +Such beans could be auto-configurations from other projects or any other beans that qualify to be Java functions. +The framework provides default filtering of known beans that should not be candidates for registration with function catalog. +You can also add to this list additional beans by providing coma delimited list of bean definition names using +`spring.cloud.function.ineligible-definitions` property + +For example, + +[source, test] +---- +spring.cloud.function.ineligible-definitions=foo,bar +---- + ==== Supplier Supplier can be _reactive_ - `Supplier>` or _imperative_ - `Supplier`. From the invocation standpoint this should make no difference diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java index 74702bbd6..db6ba6feb 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java @@ -16,7 +16,10 @@ package org.springframework.cloud.function.context; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -65,6 +68,11 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA */ private String definition; + /** + * List of functions that are not eligible to be registered in Function Catalog. + */ + private final List ineligibleDefinitions; + private Map configuration; private String expectedContentType; @@ -73,6 +81,23 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA private ApplicationContext applicationContext; + public FunctionProperties() { + ineligibleDefinitions = new ArrayList<>(); + String[] definitions = new String[] { + "org.springframework.boot", + "org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration", + "org.springframework.cloud.function.context.config.FunctionsEndpointAutoConfiguration", + "classLoaderMetrics", + "jvmMemoryMetrics", + "jvmInfoMetrics", + "jvmCompilationMetrics", + "uptimeMetrics", + "kotlinToFunctionTransformer", + "CloudEventsMessageConverterConfiguration" + }; + ineligibleDefinitions.addAll(Arrays.asList(definitions)); + } + public Map getConfiguration() { return configuration; } @@ -164,6 +189,14 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA this.environment = environment; } + public List getIneligibleDefinitions() { + return new ArrayList<>(this.ineligibleDefinitions); + } + + public void setIneligibleDefinitions(List definitions) { + this.ineligibleDefinitions.addAll(definitions); + } + public static class FunctionConfigurationProperties { private Map inputHeaderMappingExpression; diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java index bfabe304f..f2ec54dd1 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java @@ -163,6 +163,9 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect @Override public void register(FunctionRegistration registration) { + if (!isRegistrationEligible(registration)) { + return; + } Assert.notNull(registration, "'registration' must not be null"); if (logger.isDebugEnabled()) { logger.debug("Registering function " + registration.getNames()); @@ -170,6 +173,21 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect this.functionRegistrations.add(registration); } + @SuppressWarnings("rawtypes") + private boolean isRegistrationEligible(FunctionRegistration registration) { + if (this.functionProperties != null) { + for (String definition : this.functionProperties.getIneligibleDefinitions()) { + if (registration.getTarget().getClass().getName().equals(definition)) { + return false; + } + else if (registration.getNames().contains(definition) || registration.getTarget().getClass().getName().contains(definition)) { + return false; + } + } + } + return true; + } + //----- @Override diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java index 9487a85b5..1e38359e9 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java @@ -140,7 +140,7 @@ public class ContextFunctionCatalogAutoConfiguration { } @Bean(RoutingFunction.FUNCTION_NAME) - RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties, + public RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties, BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) { return new RoutingFunction(functionCatalog, functionProperties, new BeanFactoryResolver(beanFactory), routingCallback); } diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java index f3bb17dec..97e5d904d 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java @@ -105,6 +105,27 @@ public class BeanFactoryAwareFunctionRegistryTests { System.clearProperty("spring.cloud.function.definition"); } + @Test + public void testFunctionEligibilityFiltering() { + System.setProperty("spring.cloud.function.ineligible-definitions", "asJsonNode"); + Collection registeredFunction = new ArrayList(); + FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class); + for (String beanName : context.getBeanDefinitionNames()) { + try { + FunctionInvocationWrapper function = catalog.lookup(beanName); + if (function != null) { + registeredFunction.add(function); + } + } + catch (Exception e) { + // ignore + } + } + System.out.println(registeredFunction); + assertThat(registeredFunction.size()).isEqualTo(2); + assertThat((FunctionInvocationWrapper) catalog.lookup("asJsonNode")).isNull(); + } + @Test public void testJsonNodeAsInput() throws Exception { FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class);