The sample @SpringBootApplication above has a function that can be
+decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
+or a Stream processor, for instance with RabbitMQ, Apache Kafka or
+JMS.
The @Beans can be Function, Consumer or Supplier (all from
+java.util), and their parametric types can be String or POJO. A
+Function is exposed as a Spring Cloud Stream Processor if
+spring-cloud-function-stream is on the classpath.
+A Consumer is also exposed as a Stream
+Sink and a Supplier translates to a Stream Source.
+HTTP endpoints are exposed if the Stream binder is spring-cloud-stream-binder-servlet.
Functions can be of Flux<String> or Flux<Pojo> and Spring Cloud
+Function takes care of converting the data to and from the desired
+types, as long as it comes in as plain text or (in the case of the
+POJO) JSON. TBD: support for Flux<Message<Pojo>> and maybe plain
+Pojo types (Fluxes implied and implemented by the framework).
Functions can be grouped together in a single application, or deployed
+one-per-jar. It’s up to the developer to choose. An app with multiple
+functions can be deployed multiple times in different "personalities",
+exposing different functions over different physical transports.
\ No newline at end of file
diff --git a/multi/multi__deploying_a_packaged_function.html b/multi/multi__deploying_a_packaged_function.html
new file mode 100644
index 000000000..fe7fe76c0
--- /dev/null
+++ b/multi/multi__deploying_a_packaged_function.html
@@ -0,0 +1,3 @@
+
+
+ 9. Deploying a Packaged Function
Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the Riff Java function invoker uses this library).
The standard entry point of the API is the Spring configuration annotation @EnableFunctionDeployer. If that is used in a Spring Boot application the deployer kicks in and looks for some configuration to tell it where to find the function jar. At a minimum the user has to provide a function.location which is a URL or resource location for the archive containing the functions. It can optionally use a maven: prefix to locate the artifact via a dependency lookup (see FunctionProperties for complete details). A Spring Boot application is bootstrapped from the jar file, using the MANIFEST.MF to locate a start class, so that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function registered in the main application’s FunctionCatalog. The registered function can be applied by code in the main application, even though it was created in an isolated class loader (by default).
\ No newline at end of file
diff --git a/multi/multi__dynamic_compilation.html b/multi/multi__dynamic_compilation.html
new file mode 100644
index 000000000..364dce615
--- /dev/null
+++ b/multi/multi__dynamic_compilation.html
@@ -0,0 +1,23 @@
+
+
+ 4. Dynamic Compilation
There is a sample app that uses the function compiler to create a
+function from a configuration property. The vanilla "function-sample"
+also has that feature. And there are some examples that you can run to
+see the compilation happening at run time. To run these examples,
+change into the scripts directory:
cd scripts
Also, start a RabbitMQ server locally (e.g. execute rabbitmq-server).
\ No newline at end of file
diff --git a/multi/multi__function_catalog_and_flexible_function_signatures.html b/multi/multi__function_catalog_and_flexible_function_signatures.html
new file mode 100644
index 000000000..61b7387ea
--- /dev/null
+++ b/multi/multi__function_catalog_and_flexible_function_signatures.html
@@ -0,0 +1,26 @@
+
+
+ 5. Function Catalog and Flexible Function Signatures
5. Function Catalog and Flexible Function Signatures
5. 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<String,String>, for
+instance, and the FunctionCatalog will wrap it into a
+Function<Flux<String>,Flux<String>>. Users don’t normally have to
+care about the FunctionCatalog at all, but it is useful to know what
+kind of functions are supported in user code.
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
+a function using Message (from spring-messaging) it will receive and
+transmit headers from any adapter that supports key-value metadata
+(e.g. HTTP headers). Here are the details.
User Function
Catalog Registration
Function<S,T>
Function<Flux<S>, Flux<T>>
Function<Message<S>,Message<T>>
Function<Flux<Message<S>>, Flux<Message<T>>>
Function<Flux<S>, Flux<T>>
Function<Flux<S>, Flux<T>> (pass through)
Supplier<T>
Supplier<Flux<T>>
Supplier<Flux<T>>
Supplier<Flux<T>>
Consumer<T>
Function<Flux<T>, Mono<Void>>
Consumer<Message<T>>
Function<Flux<Message<T>>, Mono<Void>>
Consumer<Flux<T>>
Consumer<Flux<T>>
Consumer is a little bit special because it has a void return type,
+which implies blocking, at least potentially. Most likely you will not
+need to write Consumer<Flux<?>>, but if you do need to do that,
+remember to subscribe to the input flux. If you declare a Consumer
+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<Flux<>> with the same name
+as a Function, but it cannot contain a Consumer<T> and a
+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
+of them can be registered.
\ No newline at end of file
diff --git a/multi/multi__getting_started.html b/multi/multi__getting_started.html
new file mode 100644
index 000000000..eb4e3bef5
--- /dev/null
+++ b/multi/multi__getting_started.html
@@ -0,0 +1,9 @@
+
+
+ 2. Getting Started
(You can use QJ in a terminal to insert a new line in a literal
+string like that.)
\ No newline at end of file
diff --git a/multi/multi__introduction.html b/multi/multi__introduction.html
new file mode 100644
index 000000000..1a3f5cb63
--- /dev/null
+++ b/multi/multi__introduction.html
@@ -0,0 +1,27 @@
+
+
+ 1. Introduction
Spring Cloud Function is a project with the following high-level goals:
Promote the implementation of business logic via functions.
Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.
Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).
Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.
It abstracts away all of the transport details and
+infrastructure, allowing the developer to keep all the familiar tools
+and processes, and focus firmly on business logic.
Here’s a complete, executable, testable Spring Boot application
+(implementing a simple string manipulation):
It’s just a Spring Boot application, so it can be built, run and
+tested, locally and in a CI build, the same way as any other Spring
+Boot application. The Function is from java.util and Flux is a
+Reactive StreamsPublisher from
+Project Reactor. The function can be
+accessed over HTTP or messaging.
Spring Cloud Function has 4 main features:
Wrappers for @Beans of type Function, Consumer and
+Supplier, exposing them to the outside world as either HTTP
+endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.
Compiling strings which are Java function bodies into bytecode, and
+then turning them into @Beans that can be wrapped as above.
Deploying a JAR file containing such an application context with an
+isolated classloader, so that you can pack them together in a single
+JVM.
Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.
\ No newline at end of file
diff --git a/multi/multi__serverless_platform_adapters.html b/multi/multi__serverless_platform_adapters.html
new file mode 100644
index 000000000..3bb77b75c
--- /dev/null
+++ b/multi/multi__serverless_platform_adapters.html
@@ -0,0 +1,11 @@
+
+
+ 8. Serverless Platform Adapters
As well as being able to run as a standalone process, a Spring Cloud
+Function application can be adapted to run one of the existing
+servlerless platforms. In the project there are adapters for
+AWS
+Lambda,
+Azure,
+and
+Apache
+OpenWhisk. The Oracle Fn platform has its own Spring Cloud Function adapter.
\ No newline at end of file
diff --git a/multi/multi__standalone_streaming_applications.html b/multi/multi__standalone_streaming_applications.html
new file mode 100644
index 000000000..a95b3741a
--- /dev/null
+++ b/multi/multi__standalone_streaming_applications.html
@@ -0,0 +1,3 @@
+
+
+ 7. Standalone Streaming Applications
To send or receive messages from a broker (such as RabbitMQ or Kafka) you can use the spring-cloud-function-stream adapter. Add the adapter to your classpath along with the appropriate binder from Spring Cloud Stream. The adapter will bind to the message broker as a Processor (input and output streams) unless the user explicitly disables one or the other using spring.cloud.function.stream.{source,sink}.enabled=false.
An incoming message is routed to a function (or consumer). If there is only one, then the choice is obvious. If there are multiple functions that can accept an incoming message, the message is inspected to see if there is a stream_routekey header containing the name of a function. Routing headers or function names can be composed using a comma- or pipe-separated name. The header is also added to outgoing messages from a supplier. Messages with no route key can be routed exclusively to a function or consumer by specifying spring.cloud.function.stream.{processor,sink}.name. If a single function cannot be identified to process an incoming message there will be an error, unless you set spring.cloud.function.stream.shared=true, in which case such messages will be sent to all compatible functions. A single supplier can be chosen for output messages from a supplier (if more than one is available) using the spring.cloud.function.stream.source.name.
Note
some binders will fail on startup if the message broker is not available and the function catalog contains suppliers that immediately produce messages when accessed. You can switch off the automatic publishing from suppliers on startup using the spring.cloud.function.strean.supplier.enabled=false flag.
\ No newline at end of file
diff --git a/multi/multi__standalone_web_applications.html b/multi/multi__standalone_web_applications.html
new file mode 100644
index 000000000..65d14d571
--- /dev/null
+++ b/multi/multi__standalone_web_applications.html
@@ -0,0 +1,11 @@
+
+
+ 6. Standalone Web Applications
The spring-cloud-function-web module has autoconfiguration that
+activates when it is included in a Spring Boot web application (with
+MVC support). There is also a spring-cloud-starter-function-web to
+collect all the optional dependnecies in case you just want a simple
+getting started experience.
With the web configurations activated your app will have an MVC
+endpoint (on "/" by default, but configurable with
+spring.cloud.function.web.path) that can be used to access the
+functions in the application context. The supported content types are
+plain text and JSON.
Method
Path
Request
Response
Status
GET
/{supplier}
-
Items from the named supplier
200 OK
POST
/{consumer}
JSON object or text
Mirrors input and pushes request body into consumer
202 Accepted
POST
/{consumer}
JSON array or text with new lines
Mirrors input and pushes body into consumer one by one
202 Accepted
POST
/{function}
JSON object or text
The result of applying the named function
200 OK
POST
/{function}
JSON array or text with new lines
The result of applying the named function
200 OK
GET
/{function}/{item}
-
Convert the item into an object and return the result of applying the function
200 OK
As the table above shows the behaviour of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or Flux), then the response will also contain a single value. For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream". If there is only one function (consumer etc.) then the name in the path is optional. Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line).
Functions and consumers that are declared with input and output in Message<?> will see the request headers on the input messages, and the output message headers will be converted to HTTP headers.
When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accpt headers for the best results).
\ No newline at end of file
diff --git a/multi/multi_pr01.html b/multi/multi_pr01.html
new file mode 100644
index 000000000..bb3193e1f
--- /dev/null
+++ b/multi/multi_pr01.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/multi/multi_spring-cloud-function.html b/multi/multi_spring-cloud-function.html
new file mode 100644
index 000000000..ebab20a5c
--- /dev/null
+++ b/multi/multi_spring-cloud-function.html
@@ -0,0 +1,3 @@
+
+
+ Spring Cloud Function
Spring Cloud Function is a project with the following high-level goals:
Promote the implementation of business logic via functions.
Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.
Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).
Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.
It abstracts away all of the transport details and
+infrastructure, allowing the developer to keep all the familiar tools
+and processes, and focus firmly on business logic.
Here’s a complete, executable, testable Spring Boot application
+(implementing a simple string manipulation):
It’s just a Spring Boot application, so it can be built, run and
+tested, locally and in a CI build, the same way as any other Spring
+Boot application. The Function is from java.util and Flux is a
+Reactive StreamsPublisher from
+Project Reactor. The function can be
+accessed over HTTP or messaging.
Spring Cloud Function has 4 main features:
Wrappers for @Beans of type Function, Consumer and
+Supplier, exposing them to the outside world as either HTTP
+endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.
Compiling strings which are Java function bodies into bytecode, and
+then turning them into @Beans that can be wrapped as above.
Deploying a JAR file containing such an application context with an
+isolated classloader, so that you can pack them together in a single
+JVM.
Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.
2. Getting Started
Build from the command line (and "install" the samples):
(You can use QJ in a terminal to insert a new line in a literal
+string like that.)
3. Building and Running a Function
The sample @SpringBootApplication above has a function that can be
+decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
+or a Stream processor, for instance with RabbitMQ, Apache Kafka or
+JMS.
The @Beans can be Function, Consumer or Supplier (all from
+java.util), and their parametric types can be String or POJO. A
+Function is exposed as a Spring Cloud Stream Processor if
+spring-cloud-function-stream is on the classpath.
+A Consumer is also exposed as a Stream
+Sink and a Supplier translates to a Stream Source.
+HTTP endpoints are exposed if the Stream binder is spring-cloud-stream-binder-servlet.
Functions can be of Flux<String> or Flux<Pojo> and Spring Cloud
+Function takes care of converting the data to and from the desired
+types, as long as it comes in as plain text or (in the case of the
+POJO) JSON. TBD: support for Flux<Message<Pojo>> and maybe plain
+Pojo types (Fluxes implied and implemented by the framework).
Functions can be grouped together in a single application, or deployed
+one-per-jar. It’s up to the developer to choose. An app with multiple
+functions can be deployed multiple times in different "personalities",
+exposing different functions over different physical transports.
4. Dynamic Compilation
There is a sample app that uses the function compiler to create a
+function from a configuration property. The vanilla "function-sample"
+also has that feature. And there are some examples that you can run to
+see the compilation happening at run time. To run these examples,
+change into the scripts directory:
cd scripts
Also, start a RabbitMQ server locally (e.g. execute rabbitmq-server).
5. 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<String,String>, for
+instance, and the FunctionCatalog will wrap it into a
+Function<Flux<String>,Flux<String>>. Users don’t normally have to
+care about the FunctionCatalog at all, but it is useful to know what
+kind of functions are supported in user code.
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
+a function using Message (from spring-messaging) it will receive and
+transmit headers from any adapter that supports key-value metadata
+(e.g. HTTP headers). Here are the details.
User Function
Catalog Registration
Function<S,T>
Function<Flux<S>, Flux<T>>
Function<Message<S>,Message<T>>
Function<Flux<Message<S>>, Flux<Message<T>>>
Function<Flux<S>, Flux<T>>
Function<Flux<S>, Flux<T>> (pass through)
Supplier<T>
Supplier<Flux<T>>
Supplier<Flux<T>>
Supplier<Flux<T>>
Consumer<T>
Function<Flux<T>, Mono<Void>>
Consumer<Message<T>>
Function<Flux<Message<T>>, Mono<Void>>
Consumer<Flux<T>>
Consumer<Flux<T>>
Consumer is a little bit special because it has a void return type,
+which implies blocking, at least potentially. Most likely you will not
+need to write Consumer<Flux<?>>, but if you do need to do that,
+remember to subscribe to the input flux. If you declare a Consumer
+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<Flux<>> with the same name
+as a Function, but it cannot contain a Consumer<T> and a
+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
+of them can be registered.
6. Standalone Web Applications
The spring-cloud-function-web module has autoconfiguration that
+activates when it is included in a Spring Boot web application (with
+MVC support). There is also a spring-cloud-starter-function-web to
+collect all the optional dependnecies in case you just want a simple
+getting started experience.
With the web configurations activated your app will have an MVC
+endpoint (on "/" by default, but configurable with
+spring.cloud.function.web.path) that can be used to access the
+functions in the application context. The supported content types are
+plain text and JSON.
Method
Path
Request
Response
Status
GET
/{supplier}
-
Items from the named supplier
200 OK
POST
/{consumer}
JSON object or text
Mirrors input and pushes request body into consumer
202 Accepted
POST
/{consumer}
JSON array or text with new lines
Mirrors input and pushes body into consumer one by one
202 Accepted
POST
/{function}
JSON object or text
The result of applying the named function
200 OK
POST
/{function}
JSON array or text with new lines
The result of applying the named function
200 OK
GET
/{function}/{item}
-
Convert the item into an object and return the result of applying the function
200 OK
As the table above shows the behaviour of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or Flux), then the response will also contain a single value. For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream". If there is only one function (consumer etc.) then the name in the path is optional. Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line).
Functions and consumers that are declared with input and output in Message<?> will see the request headers on the input messages, and the output message headers will be converted to HTTP headers.
When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accpt headers for the best results).
7. Standalone Streaming Applications
To send or receive messages from a broker (such as RabbitMQ or Kafka) you can use the spring-cloud-function-stream adapter. Add the adapter to your classpath along with the appropriate binder from Spring Cloud Stream. The adapter will bind to the message broker as a Processor (input and output streams) unless the user explicitly disables one or the other using spring.cloud.function.stream.{source,sink}.enabled=false.
An incoming message is routed to a function (or consumer). If there is only one, then the choice is obvious. If there are multiple functions that can accept an incoming message, the message is inspected to see if there is a stream_routekey header containing the name of a function. Routing headers or function names can be composed using a comma- or pipe-separated name. The header is also added to outgoing messages from a supplier. Messages with no route key can be routed exclusively to a function or consumer by specifying spring.cloud.function.stream.{processor,sink}.name. If a single function cannot be identified to process an incoming message there will be an error, unless you set spring.cloud.function.stream.shared=true, in which case such messages will be sent to all compatible functions. A single supplier can be chosen for output messages from a supplier (if more than one is available) using the spring.cloud.function.stream.source.name.
Note
some binders will fail on startup if the message broker is not available and the function catalog contains suppliers that immediately produce messages when accessed. You can switch off the automatic publishing from suppliers on startup using the spring.cloud.function.strean.supplier.enabled=false flag.
8. Serverless Platform Adapters
As well as being able to run as a standalone process, a Spring Cloud
+Function application can be adapted to run one of the existing
+servlerless platforms. In the project there are adapters for
+AWS
+Lambda,
+Azure,
+and
+Apache
+OpenWhisk. The Oracle Fn platform has its own Spring Cloud Function adapter.
9. Deploying a Packaged Function
Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the Riff Java function invoker uses this library).
The standard entry point of the API is the Spring configuration annotation @EnableFunctionDeployer. If that is used in a Spring Boot application the deployer kicks in and looks for some configuration to tell it where to find the function jar. At a minimum the user has to provide a function.location which is a URL or resource location for the archive containing the functions. It can optionally use a maven: prefix to locate the artifact via a dependency lookup (see FunctionProperties for complete details). A Spring Boot application is bootstrapped from the jar file, using the MANIFEST.MF to locate a start class, so that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function registered in the main application’s FunctionCatalog. The registered function can be applied by code in the main application, even though it was created in an isolated class loader (by default).
\ No newline at end of file
diff --git a/spring-cloud-function.html b/spring-cloud-function.html
index b3a5fd166..d1e4f3b89 100644
--- a/spring-cloud-function.html
+++ b/spring-cloud-function.html
@@ -4,729 +4,109 @@
-
-Spring Cloud Function
-
+
+spring-cloud-function
+
+
+
+
-
Spring Cloud Function
+
spring-cloud-function
-
Mark Fisher, Dave Syer
+
1.0.0.BUILD-SNAPSHOT
-
-
Introduction
+
Pick The Documentation Option
-
-
Spring Cloud Function is a project with the following high-level goals:
-
-
Promote the implementation of business logic via functions.
Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.
-
-
-
Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).
-
-
-
Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.
It abstracts away all of the transport details and
-infrastructure, allowing the developer to keep all the familiar tools
-and processes, and focus firmly on business logic.
-
-
-
Here’s a complete, executable, testable Spring Boot application
-(implementing a simple string manipulation):
It’s just a Spring Boot application, so it can be built, run and
-tested, locally and in a CI build, the same way as any other Spring
-Boot application. The Function is from java.util and Flux is a
-Reactive StreamsPublisher from
-Project Reactor. The function can be
-accessed over HTTP or messaging.
-
-
-
Spring Cloud Function has 4 main features:
-
-
-
-
-
Wrappers for @Beans of type Function, Consumer and
-Supplier, exposing them to the outside world as either HTTP
-endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.
-
-
-
Compiling strings which are Java function bodies into bytecode, and
-then turning them into @Beans that can be wrapped as above.
-
-
-
Deploying a JAR file containing such an application context with an
-isolated classloader, so that you can pack them together in a single
-JVM.
-Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.
-
-
-
-
-
-
-
-
Getting Started
-
-
-
Build from the command line (and "install" the samples):
(You can use QJ in a terminal to insert a new line in a literal
-string like that.)
-
-
-
-
-
Building and Running a Function
-
-
-
The sample @SpringBootApplication above has a function that can be
-decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
-or a Stream processor, for instance with RabbitMQ, Apache Kafka or
-JMS.
-
-
-
The @Beans can be Function, Consumer or Supplier (all from
-java.util), and their parametric types can be String or POJO. A
-Function is exposed as an HTTP POST if spring-cloud-function-web
-is on the classpath, and as a Spring Cloud Stream Processor if
-spring-cloud-function-stream is on the classpath and a
-spring.cloud.function.stream.endpoint property is configured in the Spring
-environment. A Consumer is also exposed as an HTTP POST, or as a Stream
-Sink. A Supplier translates to an HTTP GET, or a Stream Source.
-
-
-
Functions can be of Flux<String> or Flux<Pojo> and Spring Cloud
-Function takes care of converting the data to and from the desired
-types, as long as it comes in as plain text or (in the case of the
-POJO) JSON. TBD: support for Flux<Message<Pojo>> and maybe plain
-Pojo types (Fluxes implied and implemented by the framework).
-
-
-
Functions can be grouped together in a single application, or deployed
-one-per-jar. It’s up to the developer to choose. An app with multiple
-functions can be deployed multiple times in different "personalities",
-exposing different functions over different physical transports.
-
-
-
-
-
Deploying a Packaged Function
-
-
-
TBD: describe the deployer app.
-
-
-
-
-
Dynamic Compilation
-
-
-
To run these examples, change into the scripts directory:
-
-
-
-
cd scripts
-
-
-
-
Also, start a RabbitMQ server locally (e.g. execute rabbitmq-server).
diff --git a/spring-cloud-function.xml b/spring-cloud-function.xml
new file mode 100644
index 000000000..557491a96
--- /dev/null
+++ b/spring-cloud-function.xml
@@ -0,0 +1,372 @@
+
+
+
+
+
+Spring Cloud Function
+2018-05-25
+
+
+
+Mark Fisher, Dave Syer
+
+
+
+Introduction
+Spring Cloud Function is a project with the following high-level goals:
+
+
+Promote the implementation of business logic via functions.
+
+
+Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.
+
+
+Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).
+
+
+Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.
+
+
+It abstracts away all of the transport details and
+infrastructure, allowing the developer to keep all the familiar tools
+and processes, and focus firmly on business logic.
+Here’s a complete, executable, testable Spring Boot application
+(implementing a simple string manipulation):
+@SpringBootApplication
+public class Application {
+
+ @Bean
+ public Function<Flux<String>, Flux<String>> uppercase() {
+ return flux -> flux.map(value -> value.toUpperCase());
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
+It’s just a Spring Boot application, so it can be built, run and
+tested, locally and in a CI build, the same way as any other Spring
+Boot application. The Function is from java.util and Flux is a
+Reactive Streams Publisher from
+Project Reactor. The function can be
+accessed over HTTP or messaging.
+Spring Cloud Function has 4 main features:
+
+
+Wrappers for @Beans of type Function, Consumer and
+Supplier, exposing them to the outside world as either HTTP
+endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.
+
+
+Compiling strings which are Java function bodies into bytecode, and
+then turning them into @Beans that can be wrapped as above.
+
+
+Deploying a JAR file containing such an application context with an
+isolated classloader, so that you can pack them together in a single
+JVM.
+
+
+Adapters for AWS Lambda, Azure, Apache OpenWhisk and possibly other "serverless" service providers.
+
+
+
+Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.
+
+
+
+Getting Started
+Build from the command line (and "install" the samples):
+$ ./mvnw clean install
+(If you like to YOLO add -DskipTests.)
+Run one of the samples, e.g.
+$ java -jar spring-cloud-function-samples/function-sample/target/*.jar
+This runs the app and exposes its functions over HTTP, so you can
+convert a string to uppercase, like this:
+$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello
+HELLO
+You can convert multiple strings (a Flux<String>) by separating them
+with new lines
+$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello
+> World'
+HELLOWORLD
+(You can use QJ in a terminal to insert a new line in a literal
+string like that.)
+
+
+Building and Running a Function
+The sample @SpringBootApplication above has a function that can be
+decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
+or a Stream processor, for instance with RabbitMQ, Apache Kafka or
+JMS.
+The @Beans can be Function, Consumer or Supplier (all from
+java.util), and their parametric types can be String or POJO. A
+Function is exposed as a Spring Cloud Stream Processor if
+spring-cloud-function-stream is on the classpath.
+A Consumer is also exposed as a Stream
+Sink and a Supplier translates to a Stream Source.
+HTTP endpoints are exposed if the Stream binder is spring-cloud-stream-binder-servlet.
+Functions can be of Flux<String> or Flux<Pojo> and Spring Cloud
+Function takes care of converting the data to and from the desired
+types, as long as it comes in as plain text or (in the case of the
+POJO) JSON. TBD: support for Flux<Message<Pojo>> and maybe plain
+Pojo types (Fluxes implied and implemented by the framework).
+Functions can be grouped together in a single application, or deployed
+one-per-jar. It’s up to the developer to choose. An app with multiple
+functions can be deployed multiple times in different "personalities",
+exposing different functions over different physical transports.
+
+
+Dynamic Compilation
+There is a sample app that uses the function compiler to create a
+function from a configuration property. The vanilla "function-sample"
+also has that feature. And there are some examples that you can run to
+see the compilation happening at run time. To run these examples,
+change into the scripts directory:
+cd scripts
+Also, start a RabbitMQ server locally (e.g. execute rabbitmq-server).
+
+Start the Function Registry Service:
+./function-registry.sh
+
+
+Register a Function:
+./registerFunction.sh -n uppercase -f "f->f.map(s->s.toString().toUpperCase())"
+
+
+Run a REST Microservice using that Function:
+./web.sh -f uppercase -p 9000
+curl -H "Content-Type: text/plain" -H "Accept: text/plain" localhost:9000/uppercase -d foo
+
+
+Register a Supplier:
+./registerSupplier.sh -n words -f "()->Flux.just(\"foo\",\"bar\")"
+
+
+Run a REST Microservice using that Supplier:
+./web.sh -s words -p 9001
+curl -H "Accept: application/json" localhost:9001/words
+
+
+Register a Consumer:
+./registerConsumer.sh -n print -t String -f "System.out::println"
+
+
+Run a REST Microservice using that Consumer:
+./web.sh -c print -p 9002
+curl -X POST -H "Content-Type: text/plain" -d foo localhost:9002/print
+
+
+Run Stream Processing Microservices:
+First register a streaming words supplier:
+./registerSupplier.sh -n wordstream -f "()->Flux.interval(Duration.ofMillis(1000)).map(i->\"message-\"+i)"
+Then start the source (supplier), processor (function), and sink (consumer) apps
+(in reverse order):
+./stream.sh -p 9103 -i uppercaseWords -c print
+./stream.sh -p 9102 -i words -f uppercase -o uppercaseWords
+./stream.sh -p 9101 -s wordstream -o words
+The output will appear in the console of the sink app (one message per second, converted to uppercase):
+MESSAGE-0
+MESSAGE-1
+MESSAGE-2
+MESSAGE-3
+MESSAGE-4
+MESSAGE-5
+MESSAGE-6
+MESSAGE-7
+MESSAGE-8
+MESSAGE-9
+...
+
+
+
+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<String,String>, for
+instance, and the FunctionCatalog will wrap it into a
+Function<Flux<String>,Flux<String>>. Users don’t normally have to
+care about the FunctionCatalog at all, but it is useful to know what
+kind of functions are supported in user code.
+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
+a function using Message (from spring-messaging) it will receive and
+transmit headers from any adapter that supports key-value metadata
+(e.g. HTTP headers). Here are the details.
+
+
+
+
+
+
+
+User Function
+Catalog Registration
+
+
+
+
+
+Function<S,T>
+Function<Flux<S>, Flux<T>>
+
+
+
+Function<Message<S>,Message<T>>
+Function<Flux<Message<S>>, Flux<Message<T>>>
+
+
+
+Function<Flux<S>, Flux<T>>
+Function<Flux<S>, Flux<T>> (pass through)
+
+
+
+Supplier<T>
+Supplier<Flux<T>>
+
+
+
+Supplier<Flux<T>>
+Supplier<Flux<T>>
+
+
+
+Consumer<T>
+Function<Flux<T>, Mono<Void>>
+
+
+
+Consumer<Message<T>>
+Function<Flux<Message<T>>, Mono<Void>>
+
+
+
+Consumer<Flux<T>>
+Consumer<Flux<T>>
+
+
+
+
+
+Consumer is a little bit special because it has a void return type,
+which implies blocking, at least potentially. Most likely you will not
+need to write Consumer<Flux<?>>, but if you do need to do that,
+remember to subscribe to the input flux. If you declare a Consumer
+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<Flux<>> with the same name
+as a Function, but it cannot contain a Consumer<T> and a
+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
+of them can be registered.
+
+
+Standalone Web Applications
+The spring-cloud-function-web module has autoconfiguration that
+activates when it is included in a Spring Boot web application (with
+MVC support). There is also a spring-cloud-starter-function-web to
+collect all the optional dependnecies in case you just want a simple
+getting started experience.
+With the web configurations activated your app will have an MVC
+endpoint (on "/" by default, but configurable with
+spring.cloud.function.web.path) that can be used to access the
+functions in the application context. The supported content types are
+plain text and JSON.
+
+
+
+
+
+
+
+
+
+Method
+Path
+Request
+Response
+Status
+
+
+
+
+GET
+/{supplier}
+-
+Items from the named supplier
+200 OK
+
+
+POST
+/{consumer}
+JSON object or text
+Mirrors input and pushes request body into consumer
+202 Accepted
+
+
+POST
+/{consumer}
+JSON array or text with new lines
+Mirrors input and pushes body into consumer one by one
+202 Accepted
+
+
+POST
+/{function}
+JSON object or text
+The result of applying the named function
+200 OK
+
+
+POST
+/{function}
+JSON array or text with new lines
+The result of applying the named function
+200 OK
+
+
+GET
+/{function}/{item}
+-
+Convert the item into an object and return the result of applying the function
+200 OK
+
+
+
+
+As the table above shows the behaviour of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or Flux), then the response will also contain a single value. For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream". If there is only one function (consumer etc.) then the name in the path is optional. Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line).
+Functions and consumers that are declared with input and output in Message<?> will see the request headers on the input messages, and the output message headers will be converted to HTTP headers.
+When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accpt headers for the best results).
+
+
+Standalone Streaming Applications
+To send or receive messages from a broker (such as RabbitMQ or Kafka) you can use the spring-cloud-function-stream adapter. Add the adapter to your classpath along with the appropriate binder from Spring Cloud Stream. The adapter will bind to the message broker as a Processor (input and output streams) unless the user explicitly disables one or the other using spring.cloud.function.stream.{source,sink}.enabled=false.
+An incoming message is routed to a function (or consumer). If there is only one, then the choice is obvious. If there are multiple functions that can accept an incoming message, the message is inspected to see if there is a stream_routekey header containing the name of a function. Routing headers or function names can be composed using a comma- or pipe-separated name. The header is also added to outgoing messages from a supplier. Messages with no route key can be routed exclusively to a function or consumer by specifying spring.cloud.function.stream.{processor,sink}.name. If a single function cannot be identified to process an incoming message there will be an error, unless you set spring.cloud.function.stream.shared=true, in which case such messages will be sent to all compatible functions. A single supplier can be chosen for output messages from a supplier (if more than one is available) using the spring.cloud.function.stream.source.name.
+
+some binders will fail on startup if the message broker is not available and the function catalog contains suppliers that immediately produce messages when accessed. You can switch off the automatic publishing from suppliers on startup using the spring.cloud.function.strean.supplier.enabled=false flag.
+
+
+
+Serverless Platform Adapters
+As well as being able to run as a standalone process, a Spring Cloud
+Function application can be adapted to run one of the existing
+servlerless platforms. In the project there are adapters for
+AWS
+Lambda,
+Azure,
+and
+Apache
+OpenWhisk. The Oracle Fn platform has its own Spring Cloud Function adapter.
+
+
+Deploying a Packaged Function
+Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the Riff Java function invoker uses this library).
+The standard entry point of the API is the Spring configuration annotation @EnableFunctionDeployer. If that is used in a Spring Boot application the deployer kicks in and looks for some configuration to tell it where to find the function jar. At a minimum the user has to provide a function.location which is a URL or resource location for the archive containing the functions. It can optionally use a maven: prefix to locate the artifact via a dependency lookup (see FunctionProperties for complete details). A Spring Boot application is bootstrapped from the jar file, using the MANIFEST.MF to locate a start class, so that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function registered in the main application’s FunctionCatalog. The registered function can be applied by code in the main application, even though it was created in an isolated class loader (by default).
+
+
\ No newline at end of file
diff --git a/spring-cloud-starter-function-web/.flattened-pom.xml b/spring-cloud-starter-function-web/.flattened-pom.xml
new file mode 100644
index 000000000..47285611b
--- /dev/null
+++ b/spring-cloud-starter-function-web/.flattened-pom.xml
@@ -0,0 +1,114 @@
+
+
+ 4.0.0
+ org.springframework.cloud
+ spring-cloud-starter-function-web
+ 1.0.0.BUILD-SNAPSHOT
+ spring-cloud-starter-starter-function-web
+ Spring Cloud Starter
+ https://projects.spring.io/spring-cloud
+
+ Pivotal Software, Inc.
+ https://www.spring.io
+
+
+
+ Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0
+ Copyright 2014-2015 the original author or authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+
+ dsyer
+ Dave Syer
+ dsyer at pivotal.io
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+ lead
+
+
+
+ sgibb
+ Spencer Gibb
+ sgibb at pivotal.io
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+ lead
+
+
+
+ mgrzejszczak
+ Marcin Grzejszczak
+ mgrzejszczak at pivotal.io
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+ developer
+
+
+
+ rbaxter
+ Ryan Baxter
+ rbaxter at pivotal.io
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+ developer
+
+
+
+
+ scm:git:git://github.com/spring-cloud/spring-cloud-build.git/spring-cloud-function-parent/spring-cloud-starter-function-web
+ scm:git:ssh://git@github.com/spring-cloud/spring-cloud-build.git/spring-cloud-function-parent/spring-cloud-starter-function-web
+ https://github.com/spring-cloud/spring-cloud-build/spring-cloud-function-parent/spring-cloud-starter-function-web
+
+
+
+ sonatype-nexus-staging
+ Nexus Release Repository
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+ repo.spring.io
+ Spring Snapshot Repository
+ https://repo.spring.io/libs-snapshot-local
+
+
+ spring-docs
+ scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-cloud/docs/spring-cloud-starter-function-web/1.0.0.BUILD-SNAPSHOT/spring-cloud-function-parent/spring-cloud-starter-function-web
+
+ https://github.com/spring-cloud
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-web
+ 1.0.0.BUILD-SNAPSHOT
+ compile
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 1.5.12.RELEASE
+ compile
+
+
+