@@ -1,5 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
|
<<<<<<< HEAD
|
||||||
* Copyright 2016-2019 the original author or authors.
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
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.ComponentScan.Filter;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.FilterType;
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
import org.springframework.core.convert.converter.GenericConverter;
|
||||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||||
import org.springframework.messaging.converter.ByteArrayMessageConverter;
|
import org.springframework.messaging.converter.ByteArrayMessageConverter;
|
||||||
@@ -119,8 +125,10 @@ public class ContextFunctionCatalogAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean(RoutingFunction.FUNCTION_NAME)
|
@Bean(RoutingFunction.FUNCTION_NAME)
|
||||||
RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionInspector functionInspector, FunctionProperties functionProperties) {
|
RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionInspector functionInspector,
|
||||||
return new RoutingFunction(functionCatalog, functionInspector, functionProperties);
|
FunctionProperties functionProperties, BeanFactory beanFactory) {
|
||||||
|
|
||||||
|
return new RoutingFunction(functionCatalog, functionProperties, functionInspector, new BeanFactoryResolver(beanFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isConverterEligible(Object messageConverter) {
|
private boolean isConverterEligible(Object messageConverter) {
|
||||||
|
|||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.FunctionInspector;
|
||||||
import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
|
import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
|
||||||
import org.springframework.context.expression.MapAccessor;
|
import org.springframework.context.expression.MapAccessor;
|
||||||
|
import org.springframework.expression.BeanResolver;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
@@ -65,11 +66,20 @@ public class RoutingFunction implements Function<Object, Object> {
|
|||||||
|
|
||||||
private final FunctionInspector functionInspector;
|
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.functionCatalog = functionCatalog;
|
||||||
this.functionProperties = functionProperties;
|
this.functionProperties = functionProperties;
|
||||||
this.functionInspector = functionInspector;
|
this.functionInspector = functionInspector;
|
||||||
this.evalContext.addPropertyAccessor(new MapAccessor());
|
this.evalContext.addPropertyAccessor(new MapAccessor());
|
||||||
|
this.evalContext.setBeanResolver(beanResolver);
|
||||||
|
evalContext.setBeanResolver(beanResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -170,6 +180,7 @@ public class RoutingFunction implements Function<Object, Object> {
|
|||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private Function functionFromExpression(String routingExpression, Object input) {
|
private Function functionFromExpression(String routingExpression, Object input) {
|
||||||
Expression expression = spelParser.parseExpression(routingExpression);
|
Expression expression = spelParser.parseExpression(routingExpression);
|
||||||
|
|
||||||
String functionName = expression.getValue(this.evalContext, input, String.class);
|
String functionName = expression.getValue(this.evalContext, input, String.class);
|
||||||
Assert.hasText(functionName, "Failed to resolve function name based on routing expression '" + functionProperties.getRoutingExpression() + "'");
|
Assert.hasText(functionName, "Failed to resolve function name based on routing expression '" + functionProperties.getRoutingExpression() + "'");
|
||||||
Function function = functionCatalog.lookup(functionName);
|
Function function = functionCatalog.lookup(functionName);
|
||||||
|
|||||||
@@ -127,6 +127,17 @@ public class RoutingFunctionTests {
|
|||||||
assertThat(function.apply(message)).isEqualTo("olleh");
|
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<String> message = MessageBuilder.withPayload("hello").setHeader("func", "esacreppu").build();
|
||||||
|
assertThat(function.apply(message)).isEqualTo("HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Test
|
@Test
|
||||||
public void testOtherExpectedFailures() {
|
public void testOtherExpectedFailures() {
|
||||||
@@ -169,6 +180,11 @@ public class RoutingFunctionTests {
|
|||||||
@Configuration
|
@Configuration
|
||||||
protected static class RoutingFunctionConfiguration {
|
protected static class RoutingFunctionConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String functionName() {
|
||||||
|
return "reverse";
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Function<String, String> reverse() {
|
public Function<String, String> reverse() {
|
||||||
return v -> new StringBuilder(v).reverse().toString();
|
return v -> new StringBuilder(v).reverse().toString();
|
||||||
|
|||||||
Reference in New Issue
Block a user