GH-205 Added initial Kotlin support documentation

polished tests and test configuration

Resolves #205
This commit is contained in:
Oleg Zhurakousky
2018-09-11 11:39:24 +02:00
parent 87c67427df
commit ca47076083
3 changed files with 43 additions and 14 deletions

View File

@@ -21,14 +21,21 @@ include::getting-started.adoc[]
== Function Catalog and Flexible Function Signatures == Function Catalog and Flexible Function Signatures
One of the main features of Spring Cloud Function is to adapt and One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions,
support a range of type signatures for user-defined functions. So while providing a consistent execution model.
users can supply a bean of type `Function<String,String>`, for That's why all user defined functions are transformed into a canonical representation by `FunctionCatalog`, using primitives
instance, and the `FunctionCatalog` will wrap it into a defined by the https://projectreactor.io/[Project Reactor] (i.e., `Flux<T>` and `Mono<T>`).
`Function<Flux<String>,Flux<String>>`. Users don't normally have to Users can supply a bean of type `Function<String,String>`, for instance, and the `FunctionCatalog` will wrap it into a
care about the `FunctionCatalog` at all, but it is useful to know what `Function<Flux<String>,Flux<String>>`.
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. kind of functions are supported in user code.
=== Java 8 function support
Generally speaking users can expect that if they write a function for Generally speaking users can expect that if they write a function for
a plain old Java type (or primitive wrapper), then the function 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 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 function that returns a publisher, so that it can be subscribed to in
a controlled way. a controlled way.
A function catalog can contain a `Supplier` and a `Function` (or === Kotlin Lambda support
`Consumer`) with the same name (like a GET and a POST to the same
resource). It can even contain a `Consumer<Flux<>>` with the same name We also provide support for Kotlin lambdas (since v2.0).
as a `Function`, but it cannot contain a `Consumer<T>` and a Consider the following:
`Function<T,S>` with the same name when `T` is not a `Publisher`
because the consumer would be converted to a `Function` and only one [source, java]
of them can be registered. ----
@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 == Standalone Web Applications

View File

@@ -397,6 +397,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Supplier.class); assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Supplier.class);
assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Function0.class); assertThat(context.getBean("kotlinSupplier")).isInstanceOf(Function0.class);
Supplier<Flux<String>> supplier = catalog.lookup(Supplier.class, "kotlinSupplier");
supplier.get().subscribe(System.out::println);
assertThat(catalog.lookup(Supplier.class, "kotlinSupplier")) assertThat(catalog.lookup(Supplier.class, "kotlinSupplier"))
.isInstanceOf(Supplier.class); .isInstanceOf(Supplier.class);
assertThat(inspector.getOutputType(catalog.lookup(Supplier.class, "kotlinSupplier"))) assertThat(inspector.getOutputType(catalog.lookup(Supplier.class, "kotlinSupplier")))

View File

@@ -34,7 +34,7 @@ open class KotlinLambdasConfiguration {
@Bean @Bean
open fun kotlinConsumer(): (String) -> Unit { open fun kotlinConsumer(): (String) -> Unit {
return { } return { println(it) }
} }
@Bean @Bean