diff --git a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java index d436b417b..5683eb667 100644 --- a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java +++ b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java @@ -23,6 +23,7 @@ import java.util.function.Function; import java.util.function.Supplier; import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.util.Assert; /** * The helper class to lookup functions from the catalog in lazy manner and cache their instances. @@ -55,7 +56,13 @@ public class FunctionLookupHelper { } private Supplier lazyLookup(Class functionType, String functionDefinition) { - return memoize(() -> this.functionCatalog.lookup(functionType, functionDefinition)); + return memoize(() -> requireNonNull(functionType, functionDefinition)); + } + + private T requireNonNull(Class functionType, String functionDefinition) { + T function = this.functionCatalog.lookup(functionType, functionDefinition); + Assert.notNull(function, () -> "No '" + functionDefinition + "' in the catalog"); + return function; } /** @@ -72,7 +79,7 @@ public class FunctionLookupHelper { synchronized (value) { val = value.get(); if (val == null) { - val = Objects.requireNonNull(delegate.get()); + val = delegate.get(); value.set(val); } } diff --git a/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java b/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java index eb5eb0f40..f07711942 100644 --- a/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java +++ b/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java @@ -36,16 +36,19 @@ import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.dsl.PollerSpec; import org.springframework.integration.dsl.Pollers; +import org.springframework.integration.dsl.context.IntegrationFlowContext; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; import org.springframework.integration.handler.LoggingHandler; import org.springframework.integration.scheduling.PollerMetadata; import org.springframework.integration.test.util.OnlyOnceTrigger; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.annotation.DirtiesContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.verify; /** @@ -98,6 +101,27 @@ public class FunctionFlowTests { verify(this.functionCatalog).lookup(Consumer.class, "upperCaseFunction|simpleStringConsumer"); } + @Test + void noFunctionInCatalogException(@Autowired FunctionFlowBuilder functionFlowBuilder, + @Autowired IntegrationFlowContext integrationFlowContext) { + + IntegrationFlow wrongFlow = + functionFlowBuilder.from("inputChannel") + .accept("nonExistingConsumer"); + + IntegrationFlowContext.IntegrationFlowRegistration registration = + integrationFlowContext.registration(wrongFlow) + .register(); + + assertThatExceptionOfType(MessageDeliveryException.class) + .isThrownBy(() -> registration.getInputChannel().send(new GenericMessage<>("test"))) + .withRootCauseInstanceOf(IllegalArgumentException.class) + .withStackTraceContaining("No 'nonExistingConsumer' in the catalog"); + + registration.destroy(); + } + + @EnableAutoConfiguration @Configuration(proxyBeanMethods = false) static class TestIntegrationConfiguration {