From ca470760835e390f2d4cdfaad9d0072b67fa110e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 11 Sep 2018 11:39:24 +0200 Subject: [PATCH] GH-205 Added initial Kotlin support documentation polished tests and test configuration Resolves #205 --- .../main/asciidoc/spring-cloud-function.adoc | 53 ++++++++++++++----- ...FunctionCatalogAutoConfigurationTests.java | 2 + .../kotlin/KotlinLambdasConfiguration.kt | 2 +- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-function.adoc b/docs/src/main/asciidoc/spring-cloud-function.adoc index b513f5b1d..970808eb7 100644 --- a/docs/src/main/asciidoc/spring-cloud-function.adoc +++ b/docs/src/main/asciidoc/spring-cloud-function.adoc @@ -21,14 +21,21 @@ include::getting-started.adoc[] == Function Catalog and Flexible Function Signatures -One of the main features of Spring Cloud Function is to adapt and -support a range of type signatures for user-defined functions. So -users can supply a bean of type `Function`, for -instance, and the `FunctionCatalog` will wrap it into a -`Function,Flux>`. Users don't normally have to -care about the `FunctionCatalog` at all, but it is useful to know what +One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions, +while providing a consistent execution model. +That's why all user defined functions are transformed into a canonical representation by `FunctionCatalog`, using primitives +defined by the https://projectreactor.io/[Project Reactor] (i.e., `Flux` and `Mono`). +Users can supply a bean of type `Function`, for instance, and the `FunctionCatalog` will wrap it into a +`Function,Flux>`. + +Using Reactor based primitives not only helps with the canonical representation of user defined functions, but it also +facilitates a more robust and flexible(reactive) execution model. + +While users don't normally have to care about the `FunctionCatalog` at all, it is useful to know what kind of functions are supported in user code. +=== Java 8 function support + Generally speaking users can expect that if they write a function for a plain old Java type (or primitive wrapper), then the function catalog will wrap it to a `Flux` of the same type. If the user writes @@ -58,13 +65,33 @@ of a non publisher type (which is normal), it will be converted to a function that returns a publisher, so that it can be subscribed to in a controlled way. -A function catalog can contain a `Supplier` and a `Function` (or -`Consumer`) with the same name (like a GET and a POST to the same -resource). It can even contain a `Consumer>` with the same name -as a `Function`, but it cannot contain a `Consumer` and a -`Function` with the same name when `T` is not a `Publisher` -because the consumer would be converted to a `Function` and only one -of them can be registered. +=== Kotlin Lambda support + +We also provide support for Kotlin lambdas (since v2.0). +Consider the following: + +[source, java] +---- +@Bean +open fun kotlinSupplier(): () -> String { + return { "Hello from Kotlin" } +} + +@Bean +open fun kotlinFunction(): (String) -> String { + return { it.toUpperCase() } +} + +@Bean +open fun kotlinConsumer(): (String) -> Unit { + return { println(it) } +} + +---- +The above represents Kotlin lambdas configured as Spring beans. The signature of each maps to a Java equivalent of +`Supplier`, `Function` and `Consumer`, and thus supported/recognized signatures by the framework. +While mechanics of Kotlin-to-Java mapping are outside of the scope of this documentation, it is important to understand that the +same rules for signature transformation outlined in "Java 8 function support" section are applied here as well. == Standalone Web Applications diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java index c4ae9fc65..f83303d68 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java @@ -397,6 +397,8 @@ public class ContextFunctionCatalogAutoConfigurationTests { assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Supplier.class); assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Function0.class); + Supplier> supplier = catalog.lookup(Supplier.class, "kotlinSupplier"); + supplier.get().subscribe(System.out::println); assertThat(catalog.lookup(Supplier.class, "kotlinSupplier")) .isInstanceOf(Supplier.class); assertThat(inspector.getOutputType(catalog.lookup(Supplier.class, "kotlinSupplier"))) diff --git a/spring-cloud-function-context/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt b/spring-cloud-function-context/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt index 3c9e7d2c1..db53c8305 100644 --- a/spring-cloud-function-context/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt +++ b/spring-cloud-function-context/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt @@ -34,7 +34,7 @@ open class KotlinLambdasConfiguration { @Bean open fun kotlinConsumer(): (String) -> Unit { - return { } + return { println(it) } } @Bean