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 161d6cae3..00cc54cdd 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; +import org.springframework.beans.factory.BeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -46,6 +47,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; +import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.lang.Nullable; @@ -113,8 +115,9 @@ public class ContextFunctionCatalogAutoConfiguration { } @Bean(RoutingFunction.FUNCTION_NAME) - RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties) { - return new RoutingFunction(functionCatalog, functionProperties); + RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties, + BeanFactory beanFactory) { + return new RoutingFunction(functionCatalog, functionProperties, new BeanFactoryResolver(beanFactory)); } private boolean isConverterEligible(Object messageConverter) { diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java index b67b8d60e..7c8b77b31 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2019 the original author or authors. + * Copyright 2019-2021 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. @@ -28,6 +28,7 @@ import org.springframework.cloud.function.context.FunctionCatalog; import org.springframework.cloud.function.context.FunctionProperties; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; import org.springframework.context.expression.MapAccessor; +import org.springframework.expression.BeanResolver; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -63,9 +64,15 @@ public class RoutingFunction implements Function { private final FunctionProperties functionProperties; public RoutingFunction(FunctionCatalog functionCatalog, FunctionProperties functionProperties) { + this(functionCatalog, functionProperties, null); + } + + public RoutingFunction(FunctionCatalog functionCatalog, FunctionProperties functionProperties, + BeanResolver beanResolver) { this.functionCatalog = functionCatalog; this.functionProperties = functionProperties; this.evalContext.addPropertyAccessor(new MapAccessor()); + evalContext.setBeanResolver(beanResolver); } @Override diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java index 8a71e9663..cb9267b91 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java @@ -134,6 +134,17 @@ public class RoutingFunctionTests { assertThat(function.apply(message)).isEqualTo("olleh"); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Test + public void testInvocationWithRoutingBeanExpression() { + System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "@reverse.apply(#root.getHeaders().get('func'))"); + FunctionCatalog functionCatalog = this.configureCatalog(); + Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); + assertThat(function).isNotNull(); + Message message = MessageBuilder.withPayload("hello").setHeader("func", "esacreppu").build(); + assertThat(function.apply(message)).isEqualTo("HELLO"); + } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void testOtherExpectedFailures() {