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 97c8d6a19..6edabdf8c 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,9 @@ /* +<<<<<<< HEAD * Copyright 2016-2019 the original author or authors. +======= + * Copyright 2016-2021 the original author or authors. +>>>>>>> 3a3fd4a6... GH-620 Add BeanResolver support for RoutingFunction * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +31,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; @@ -45,6 +50,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.messaging.converter.ByteArrayMessageConverter; @@ -119,8 +125,10 @@ public class ContextFunctionCatalogAutoConfiguration { } @Bean(RoutingFunction.FUNCTION_NAME) - RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionInspector functionInspector, FunctionProperties functionProperties) { - return new RoutingFunction(functionCatalog, functionInspector, functionProperties); + RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionInspector functionInspector, + FunctionProperties functionProperties, BeanFactory beanFactory) { + + return new RoutingFunction(functionCatalog, functionProperties, functionInspector, 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 27dc9e316..7239d5bcb 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. @@ -30,6 +30,7 @@ import org.springframework.cloud.function.context.FunctionProperties; import org.springframework.cloud.function.context.catalog.FunctionInspector; import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; 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; @@ -65,11 +66,20 @@ public class RoutingFunction implements Function { private final FunctionInspector functionInspector; - public RoutingFunction(FunctionCatalog functionCatalog, FunctionInspector functionInspector, FunctionProperties functionProperties) { + public RoutingFunction(FunctionCatalog functionCatalog, FunctionInspector functionInspector, + FunctionProperties functionProperties) { + + this(functionCatalog, functionProperties, functionInspector, null); + } + + public RoutingFunction(FunctionCatalog functionCatalog, FunctionProperties functionProperties, + FunctionInspector functionInspector, BeanResolver beanResolver) { this.functionCatalog = functionCatalog; this.functionProperties = functionProperties; this.functionInspector = functionInspector; this.evalContext.addPropertyAccessor(new MapAccessor()); + this.evalContext.setBeanResolver(beanResolver); + evalContext.setBeanResolver(beanResolver); } @Override @@ -170,6 +180,7 @@ public class RoutingFunction implements Function { @SuppressWarnings("rawtypes") private Function functionFromExpression(String routingExpression, Object input) { Expression expression = spelParser.parseExpression(routingExpression); + String functionName = expression.getValue(this.evalContext, input, String.class); Assert.hasText(functionName, "Failed to resolve function name based on routing expression '" + functionProperties.getRoutingExpression() + "'"); Function function = functionCatalog.lookup(functionName); 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 ed7b758a6..3bf67cd99 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 @@ -127,6 +127,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() { @@ -169,6 +180,11 @@ public class RoutingFunctionTests { @Configuration protected static class RoutingFunctionConfiguration { + @Bean + public String functionName() { + return "reverse"; + } + @Bean public Function reverse() { return v -> new StringBuilder(v).reverse().toString();