From 77ca7f450f7fef5615eb6653e68cc89e3f37fff1 Mon Sep 17 00:00:00 2001 From: Matthew Gilliard Date: Wed, 6 Dec 2017 00:02:32 +0000 Subject: [PATCH] Adds Spring Cloud Function example (#566) --- .gitignore | 3 + .../apps/fn-spring-cloud-functions/README.md | 86 +++++++++++++++++++ .../apps/fn-spring-cloud-functions/func.yaml | 7 ++ .../apps/fn-spring-cloud-functions/pom.xml | 58 +++++++++++++ .../com/fnproject/fn/examples/SCFExample.java | 53 ++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 examples/apps/fn-spring-cloud-functions/README.md create mode 100644 examples/apps/fn-spring-cloud-functions/func.yaml create mode 100644 examples/apps/fn-spring-cloud-functions/pom.xml create mode 100644 examples/apps/fn-spring-cloud-functions/src/main/java/com/fnproject/fn/examples/SCFExample.java diff --git a/.gitignore b/.gitignore index e822a20ce..1be3b2dc0 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ fnlb/fnlb /fn .DS_Store /fnserver +.idea/ +*iml +target/ diff --git a/examples/apps/fn-spring-cloud-functions/README.md b/examples/apps/fn-spring-cloud-functions/README.md new file mode 100644 index 000000000..bb8c3699d --- /dev/null +++ b/examples/apps/fn-spring-cloud-functions/README.md @@ -0,0 +1,86 @@ +# Example Spring Cloud Function + +This is an example [spring cloud function](https://github.com/spring-cloud/spring-cloud-function) +project running on Fn using the +[`SpringCloudFunctionInvoker`](/runtime/src/main/java/com/fnproject/fn/runtime/spring/SpringCloudFunctionInvoker.java). + +Firstly, if you have used `fn` before you'll want to make sure you have the latest runtime image which includes the Spring support: + +```bash +$ docker pull fnproject/fdk-java:latest +``` + +Then you can build and deploy the app + +```bash +fn build +fn deploy --local --app spring-cloud-fn + +# Set up a couple of routes for different functions +fn routes create spring-cloud-fn /upper +fn routes config set spring-cloud-fn /upper FN_SPRING_FUNCTION upperCase + +fn routes create spring-cloud-fn /lower +fn routes config set spring-cloud-fn /lower FN_SPRING_FUNCTION lowerCase +``` + +Now you can call those functions using `fn call` or curl: + +```bash +$ echo "Hi there" | fn call spring-cloud-fn /upper +HI THERE + +$ curl -d "Hi There" http://localhost:8080/r/spring-cloud-fn/lower +hi there +``` + + +## Code walkthrough + +```java +@Configuration +``` +Defines that the class is a +[Spring configuration class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html) +with `@Bean` definitions inside of it. + +```java +@Import(ContextFunctionCatalogAutoConfiguration.class) +``` +Specifies that this configuration uses a [`InMemoryFunctionCatalog`](https://github.com/spring-cloud/spring-cloud-function/blob/a973b678f1d4d6f703a530e2d9e071b6d650567f/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/InMemoryFunctionCatalog.java) +that provides the beans necessary +for the `SpringCloudFunctionInvoker`. + +```java + ... + @FnConfiguration + public static void configure(RuntimeContext ctx) { + ctx.setInvoker(new SpringCloudFunctionInvoker(SCFExample.class)); + } +``` + +Sets up the Fn Java FDK to use the SpringCloudFunctionInvoker which performs function discovery and invocation. + +```java + // Unused - see https://github.com/fnproject/fdk-java/issues/113 + public void handleRequest() { } +``` + +Currently the runtime expects a method to invoke, however this isn't used in the SpringCloudFunctionInvoker so we declare an empty method simply to keep the runtime happy. This will not be necessary for long - see the linked issue on GitHub. + + +```java + @Bean + public Function upperCase(){ + return String::toUpperCase; + } + + @Bean + public Function lowerCase(){ + return String::toLowerCase; + } +``` + +Finally the heart of the configuration; the bean definitions of the functions to invoke. + +Note that these methods are not the functions themselves. They are factory methods which *return* the functions. As the Beans are constructed by Spring it is possible to use `@Autowired` dependency injection. diff --git a/examples/apps/fn-spring-cloud-functions/func.yaml b/examples/apps/fn-spring-cloud-functions/func.yaml new file mode 100644 index 000000000..74544f519 --- /dev/null +++ b/examples/apps/fn-spring-cloud-functions/func.yaml @@ -0,0 +1,7 @@ +name: fn-example/spring-cloud-fn +version: 0.0.1 +runtime: java8 +cmd: com.fnproject.fn.examples.SCFExample::handleRequest +format: http +timeout: 30 +path: /fn diff --git a/examples/apps/fn-spring-cloud-functions/pom.xml b/examples/apps/fn-spring-cloud-functions/pom.xml new file mode 100644 index 000000000..dd60304a2 --- /dev/null +++ b/examples/apps/fn-spring-cloud-functions/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + + + UTF-8 + 1.0.52 + + + com.fnproject.fn.examples + spring-fn + 1.0.0-SNAPSHOT + + + + com.fnproject.fn + api + ${fdk.version} + + + com.fnproject.fn + fn-spring-cloud-function + ${fdk.version} + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + + + + fn-maven-releases + https://dl.bintray.com/fnproject/fnproject + + + + diff --git a/examples/apps/fn-spring-cloud-functions/src/main/java/com/fnproject/fn/examples/SCFExample.java b/examples/apps/fn-spring-cloud-functions/src/main/java/com/fnproject/fn/examples/SCFExample.java new file mode 100644 index 000000000..4b8ade25e --- /dev/null +++ b/examples/apps/fn-spring-cloud-functions/src/main/java/com/fnproject/fn/examples/SCFExample.java @@ -0,0 +1,53 @@ +package com.fnproject.fn.examples; + +import com.fnproject.fn.api.FnConfiguration; +import com.fnproject.fn.api.RuntimeContext; +import com.fnproject.springframework.function.SpringCloudFunctionInvoker; +import org.springframework.cloud.function.context.ContextFunctionCatalogAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import reactor.core.publisher.Flux; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +@Configuration +@Import(ContextFunctionCatalogAutoConfiguration.class) +public class SCFExample { + @FnConfiguration + public static void configure(RuntimeContext ctx) { + ctx.setInvoker(new SpringCloudFunctionInvoker(SCFExample.class)); + } + + // Unused - see https://github.com/fnproject/fdk-java/issues/113 + public void handleRequest() { } + + public static class B{ + private String xxx; + public B() {} + + public B(String xxx) { + this.xxx = xxx; + } + + public String getXxx() { + return xxx; + } + + public void setXxx(String xxx) { + this.xxx = xxx; + } + } + + @Bean + public Function consumer(){ + return B::getXxx; + } + +}