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 2931ac7d6..5c74d8596 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 @@ -283,9 +283,8 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect FunctionInvocationWrapper andThenFunction = invocationWrapperInstance(functionName, function.getTarget(), function.inputType, function.outputType); composedFunction = (FunctionInvocationWrapper) composedFunction.andThen((Function) andThenFunction); - composedFunction = this.enrichInputIfNecessary(composedFunction); - } + composedFunction = this.enrichInputIfNecessary(composedFunction); this.wrappedFunctionDefinitions.put(composedFunction.functionDefinition, composedFunction); } } @@ -304,17 +303,18 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect if (!CollectionUtils.isEmpty(configurationProperties)) { FunctionConfigurationProperties configuration = configurationProperties .get(functionDefinition.replace("|", "").replace(",", "")); - if (!CollectionUtils.isEmpty(configuration.getInputHeaderMappingExpression())) { - BeanFactoryResolver beanResolver = this.functionProperties.getApplicationContext() != null - ? new BeanFactoryResolver(this.functionProperties.getApplicationContext()) - : null; - InputEnricher enricher = new InputEnricher(configuration.getInputHeaderMappingExpression(), beanResolver); - FunctionInvocationWrapper w = new FunctionInvocationWrapper("headerEnricher", enricher, Message.class, Message.class); - composedFunction = (FunctionInvocationWrapper) w.andThen((Function) composedFunction); - composedFunction.functionDefinition = functionDefinition; + if (configuration != null) { + if (!CollectionUtils.isEmpty(configuration.getInputHeaderMappingExpression())) { + BeanFactoryResolver beanResolver = this.functionProperties.getApplicationContext() != null + ? new BeanFactoryResolver(this.functionProperties.getApplicationContext()) + : null; + InputEnricher enricher = new InputEnricher(configuration.getInputHeaderMappingExpression(), beanResolver); + FunctionInvocationWrapper w = new FunctionInvocationWrapper("headerEnricher", enricher, Message.class, Message.class); + composedFunction = (FunctionInvocationWrapper) w.andThen((Function) composedFunction); + composedFunction.functionDefinition = functionDefinition; + } } } - return composedFunction; } diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java index 6168b7a50..5afe8953f 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java @@ -22,7 +22,7 @@ import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; /** - * An example POJO that represents cloud event data + * An example POJO that represents cloud event data. * * @author Oleg Zhurakousky * diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionPropertiesTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionPropertiesTests.java index 64a8043f1..2f00f09ec 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionPropertiesTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionPropertiesTests.java @@ -16,7 +16,6 @@ package org.springframework.cloud.function.context; -import java.util.Map; import java.util.function.Function; import org.junit.jupiter.api.Test; @@ -24,13 +23,17 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionProperties.FunctionConfigurationProperties; +import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.support.MessageBuilder; import static org.assertj.core.api.Assertions.assertThat; +//NOTE!!! assertions for all tests are in 'echo' function since we're validating what's coming into it. public class FunctionPropertiesTests { @Test @@ -39,16 +42,14 @@ public class FunctionPropertiesTests { SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( "--logging.level.org.springframework.cloud.function=DEBUG", "--spring.main.lazy-initialization=true", - "--spring.cloud.function.definition=echo", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1=hello1", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key2=hello2", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[1].key12=hello12")) { - FunctionProperties functionProperties = context - .getBean(FunctionProperties.class); - FunctionConfigurationProperties configuration = functionProperties - .getConfiguration().get("echo"); - assertThat(configuration.getInputHeaderMappingExpression()).containsKey("0"); - assertThat(configuration.getInputHeaderMappingExpression()).containsKey("1"); + "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1='hello1'", + "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key2='hello2'", + "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].foo=headers.contentType")) { + + FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); + FunctionInvocationWrapper function = functionCatalog.lookup("echo"); + function.apply(MessageBuilder.withPayload("helo") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); } } @@ -58,74 +59,86 @@ public class FunctionPropertiesTests { SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( "--logging.level.org.springframework.cloud.function=DEBUG", "--spring.main.lazy-initialization=true", - "--spring.cloud.function.definition=echo", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key1=hello1", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key2=hello2")) { - FunctionProperties functionProperties = context - .getBean(FunctionProperties.class); - FunctionConfigurationProperties configuration = functionProperties - .getConfiguration().get("echo"); - assertThat(configuration.getInputHeaderMappingExpression()).containsKey("0"); + "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key1='hello1'", + "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key2='hello2'", + "--spring.cloud.function.configuration.echo.input-header-mapping-expression.foo=headers.contentType")) { + + FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); + FunctionInvocationWrapper function = functionCatalog.lookup("echo"); + function.apply(MessageBuilder.withPayload("helo") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); } } @Test - public void testInputHeaderMappingPropertyWithCompositionWithIndex() throws Exception { + public void testInputHeaderMappingExpressionWithCompositionWithIndex() throws Exception { try (ConfigurableApplicationContext context = new SpringApplicationBuilder( SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( "--logging.level.org.springframework.cloud.function=DEBUG", "--spring.main.lazy-initialization=true", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key1='hello1'", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key2='hello2'", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].foo=headers.contentType")) { + + FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); + FunctionInvocationWrapper function = functionCatalog.lookup("echo|foo"); + function.apply(MessageBuilder.withPayload("helo") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); + } + } + + @Test + public void testInputHeaderMappingExpressionWithCompositionWithoutIndex() throws Exception { + try (ConfigurableApplicationContext context = new SpringApplicationBuilder( + SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( + "--logging.level.org.springframework.cloud.function=DEBUG", + "--spring.main.lazy-initialization=true", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key1='hello1'", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key2='hello2'", + "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.foo=headers.contentType")) { + + FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); + FunctionInvocationWrapper function = functionCatalog.lookup("echo|foo"); + function.apply(MessageBuilder.withPayload("helo") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); + + //assertions are in 'echo' function since we're validating what's coming into it. + } + } + +// @Test +// public void testInputHeaderMappingPropertyWithCompositionWithoutIndex() throws Exception { +// try (ConfigurableApplicationContext context = new SpringApplicationBuilder( +// SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( +// "--logging.level.org.springframework.cloud.function=DEBUG", +// "--spring.main.lazy-initialization=true", // "--spring.cloud.function.definition=echo|foo", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key1=hello1", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key2=hello2", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[1].key12=hello12")) { - FunctionProperties functionProperties = context - .getBean(FunctionProperties.class); - FunctionConfigurationProperties configuration = functionProperties - .getConfiguration().get("echofoo"); - Map keyValueExpression = (Map) configuration.getInputHeaderMappingExpression().get("0"); - - -// FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); -// FunctionInvocationWrapper function = functionCatalog.lookup("echo|foo"); -// System.out.println(function.apply(new GenericMessage("helo"))); - - - -// System.out.println(keyValueExpression.get("key1")); +// "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key1=hello1", +// "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key2=hello2")) { +// FunctionProperties functionProperties = context +// .getBean(FunctionProperties.class); +// FunctionConfigurationProperties configuration = functionProperties +// .getConfiguration().get("echofoo"); // assertThat(configuration.getInputHeaderMappingExpression()).containsKey("0"); -// assertThat(configuration.getInputHeaderMappingExpression()).containsKey("1"); - } - } - - @Test - public void testInputHeaderMappingPropertyWithCompositionWithoutIndex() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.definition=echo|foo", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key1=hello1", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key2=hello2")) { - FunctionProperties functionProperties = context - .getBean(FunctionProperties.class); - FunctionConfigurationProperties configuration = functionProperties - .getConfiguration().get("echofoo"); - assertThat(configuration.getInputHeaderMappingExpression()).containsKey("0"); - } - } +// } +// } @EnableAutoConfiguration @Configuration protected static class SampleFunctionConfiguration { @Bean - public Function echo() { - return x -> x; + public Function, Message> echo() { + return m -> { + assertThat(m.getHeaders().get("key1")).isEqualTo("hello1"); + assertThat(m.getHeaders().get("key2")).isEqualTo("hello2"); + assertThat(m.getHeaders().get("foo")).isEqualTo("application/json"); + return m; + }; } @Bean - public Function foo() { + public Function, Message> foo() { return x -> x; } }