diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/README.md b/spring-cloud-function-samples/function-sample-supplier-exporter/README.md
new file mode 100644
index 000000000..560073481
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/README.md
@@ -0,0 +1,16 @@
+AWS Lambda custom runtime.
+
+```
+$ ./build.sh
+$ ./mvnw package -P native
+```
+
+builds a native-zip ZIP file in target. Upload it to AWS and set the handler to "foobar".
+
+To test locally, run the `TestServer` and then the `DemoApplication` (either in a JVM or natively). Then POST some data into the test server:
+
+```
+$ curl localhost:8000/add -d world -H "Content-Type: text/plain"
+```
+
+There is a unit test that does the same thing. Also the `build.sh` script orchestrates the same test for the native image.
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/application.properties b/spring-cloud-function-samples/function-sample-supplier-exporter/application.properties
new file mode 100644
index 000000000..175231985
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/application.properties
@@ -0,0 +1,5 @@
+# Useful for running locally (hence not in src/main/resources)
+spring.cloud.function.web.export.source.url=http://localhost:8000/home
+spring.cloud.function.web.export.sink.url=http://localhost:8000/echo
+spring.cloud.function.web.export.debug=true
+logging.level.org.springframework=DEBUG
\ No newline at end of file
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/build.sh b/spring-cloud-function-samples/function-sample-supplier-exporter/build.sh
new file mode 100644
index 000000000..6b4a373a2
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/build.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+printf "=== ${BLUE}Building %s sample${NC} ===\n" "${PWD##*/}"
+
+./compile.sh || exit 1
+
+JARDIR=target/native-image
+java -cp $JARDIR/BOOT-INF/lib/*:$JARDIR/BOOT-INF/classes:$JARDIR:target/test-classes com.example.test.TestServer &
+SPID=$!
+sleep 5
+
+${PWD%/*samples/*}/scripts/test.sh --spring.cloud.function.web.export.source.url=http://localhost:8000/home --spring.cloud.function.web.export.sink.url=http://localhost:8000/echo
+
+kill $SPID
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh b/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh
new file mode 100644
index 000000000..ec45e4d25
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+ARTIFACT=function-aws
+MAINCLASS=com.example.demo.DemoApplication
+VERSION=0.0.1-SNAPSHOT
+FEATURE=../../../../spring-graal-native/target/spring-graal-native-0.7.0.BUILD-SNAPSHOT.jar
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+rm -rf target
+mkdir -p target/native-image
+
+echo "Packaging $ARTIFACT with Maven"
+mvn -DskipTests package > target/native-image/output.txt
+
+JAR="$ARTIFACT-$VERSION.jar"
+rm -f $ARTIFACT
+echo "Unpacking $JAR"
+cd target/native-image
+jar -xvf ../$JAR >/dev/null 2>&1
+cp -R META-INF BOOT-INF/classes
+
+LIBPATH=`find BOOT-INF/lib | tr '\n' ':'`
+CP=BOOT-INF/classes:$LIBPATH:$FEATURE
+
+if [ ! -f "$FEATURE" ]; then
+ printf "${RED}FAILURE${NC}: $FEATURE does not exist, please build the root project before building this sample.\n"
+ exit 1
+fi
+
+GRAALVM_VERSION=`native-image --version`
+echo "Compiling $ARTIFACT with $GRAALVM_VERSION"
+{ time native-image \
+ --verbose \
+ --no-server \
+ --no-fallback \
+ --initialize-at-build-time \
+ -H:+PrintMethodHistogram \
+ -H:+TraceClassInitialization \
+ -H:Name=$ARTIFACT \
+ -H:+ReportExceptionStackTraces \
+ -Dspring.graal.remove-unused-autoconfig=true \
+ -Dspring.graal.remove-yaml-support=true \
+ -cp $CP $MAINCLASS >> output.txt ; } 2>> output.txt
+
+if [[ -f $ARTIFACT ]]
+then
+ printf "${GREEN}SUCCESS${NC}\n"
+ mv ./$ARTIFACT ..
+ exit 0
+else
+ cat output.txt
+ printf "${RED}FAILURE${NC}: an error occurred when compiling the native-image.\n"
+ exit 1
+fi
+
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml b/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml
new file mode 100644
index 000000000..6ae6d240e
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml
@@ -0,0 +1,144 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.0.M4
+
+
+ com.example
+ function-sample-aws-supplier-exporter
+ 1.0.0.RELEASE
+ function-sample-aws-supplier-exporter
+ Demo project for Spring Boot
+
+
+ 1.8
+ 3.1.0.BUILD-SNAPSHOT
+ Dysprosium-SR6
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ io.netty
+ netty-transport-native-epoll
+
+
+ io.netty
+ netty-codec-http2
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-web
+
+
+ org.springframework.cloud
+ spring-cloud-function-adapter-aws
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-dependencies
+ ${spring-cloud-function.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+
+
+ central
+ https://repo.maven.apache.org/maven2
+
+ false
+
+
+
+ spring-release
+ Spring release
+ https://repo.spring.io/release
+
+ false
+
+
+
+ spring-snapshot
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestone
+ Spring Milestone
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ central
+ https://repo.maven.apache.org/maven2
+
+ false
+
+
+
+ spring-release
+ Spring release
+ https://repo.spring.io/release
+
+ false
+
+
+
+ spring-snapshot
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestone
+ Spring Milestone
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java
new file mode 100644
index 000000000..d41f097c4
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java
@@ -0,0 +1,55 @@
+package com.example.demo;
+
+import java.util.function.Function;
+
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.cloud.function.context.FunctionRegistration;
+import org.springframework.cloud.function.context.FunctionType;
+import org.springframework.cloud.function.context.FunctionalSpringApplication;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.support.GenericApplicationContext;
+
+@SpringBootConfiguration(proxyBeanMethods = false)
+public class DemoApplication
+ implements ApplicationContextInitializer {
+
+ public static void main(String[] args) {
+ FunctionalSpringApplication.run(DemoApplication.class, args);
+ }
+
+ @Override
+ public void initialize(GenericApplicationContext context) {
+ context.registerBean("foobar", FunctionRegistration.class,
+ () -> new FunctionRegistration<>(new Foobar())
+ .type(FunctionType.from(Foo.class).to(Foo.class)));
+ }
+
+}
+
+class Foo {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Foo(String name) {
+ this.name = name;
+ }
+
+ Foo() {
+ }
+}
+
+class Foobar implements Function {
+
+ @Override
+ public Foo apply(Foo input) {
+ System.err.println("HI: " + input.getName());
+ return new Foo("hi " + input.getName() + "!");
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json
new file mode 100644
index 000000000..c5f6007b7
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json
@@ -0,0 +1,7 @@
+[
+ {
+ "name": "com.example.demo.Foo",
+ "allDeclaredConstructors": true,
+ "allDeclaredMethods": true
+ }
+]
\ No newline at end of file
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties
new file mode 100644
index 000000000..9e8695a2c
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+spring.cloud.function.web.export.enabled=true
+spring.cloud.function.web.export.debug=true
+spring.main.web-application-type=none
+logging.level.org.springframework.cloud=DEBUG
\ No newline at end of file
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/DemoApplicationTests.java b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/DemoApplicationTests.java
new file mode 100644
index 000000000..5cce20b94
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/DemoApplicationTests.java
@@ -0,0 +1,55 @@
+package com.example.demo;
+
+import com.example.test.TestServer;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.function.context.test.FunctionalSpringBootTest;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.util.SocketUtils;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@FunctionalSpringBootTest({"spring.cloud.function.web.export.source.url=http://localhost:${export.port}/home",
+ "spring.cloud.function.web.export.sink.url=http://localhost:${export.port}/echo",
+ "logging.level.reactor=OFF",
+ "logging.level.io.netty=OFF"})
+public class DemoApplicationTests {
+
+ static ConfigurableApplicationContext context;
+
+ @Value("${export.port}")
+ private int port;
+
+ @Autowired
+ private WebClient.Builder builder;
+
+ @Test
+ public void contextLoads() throws Exception {
+ WebClient client = builder.baseUrl("http://localhost:" + port).build();
+ client.post().uri("/add").bodyValue("{\"name\":\"Fred\"}").exchange().block();
+ Thread.sleep(1000L);
+ String response = client.get().uri("/take").exchange().block().bodyToMono(String.class).block();
+ assertThat(response).isEqualTo("{\"name\":\"hi Fred!\"}");
+ }
+
+ @AfterAll
+ static void after() {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ @BeforeAll
+ static void before() {
+ int port = SocketUtils.findAvailableTcpPort();
+ System.setProperty("export.port", "" + port);
+ context = SpringApplication.run(TestServer.class, "--server.port="+port, "--spring.cloud.function.web.export.enabled=false", "--spring.main.web-application-type=reactive");
+ }
+
+}
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/test/TestServer.java b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/test/TestServer.java
new file mode 100644
index 000000000..7af07eb6d
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/test/TestServer.java
@@ -0,0 +1,85 @@
+package com.example.test;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.function.json.JsonMapper;
+import org.springframework.context.annotation.Bean;
+
+import reactor.core.publisher.Mono;
+import reactor.core.publisher.MonoProcessor;
+
+@SpringBootApplication(proxyBeanMethods = false)
+public class TestServer {
+
+ private MonoProcessor output = MonoProcessor.create();
+
+ private String response = "";
+
+ public static void main(String[] args) {
+ Set list = new LinkedHashSet<>(Arrays.asList(args));
+ list.addAll(Arrays.asList("--server.port=8000", "--spring.cloud.function.web.export.enabled=false", "--spring.main.web-application-type=reactive"));
+ SpringApplication.run(TestServer.class, list.toArray(new String[0]));
+ }
+
+ @Bean
+ public Supplier> home() {
+ return () -> output;
+ }
+
+// @Bean
+// public Function echo(JsonMapper mapper) {
+// return input -> {
+// response = input;
+// return "Echo: " + response;
+// };
+// }
+
+ @Bean
+ public Function echo(JsonMapper mapper) {
+ return input -> {
+ System.out.println("===> POJO " + input);
+ response = new String(mapper.toJson(input));
+ return "Echo: " + response;
+ };
+ }
+
+ @Bean
+ public Function add() {
+ return input -> {
+ System.err.println("Add: " + input);
+ output.onNext(input);
+ output = MonoProcessor.create();
+ return "Added: " + input;
+ };
+ }
+
+ @Bean
+ public Supplier take() {
+ return () -> response;
+ }
+
+}
+
+class Foo {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Foo(String name) {
+ this.name = name;
+ }
+
+ Foo() {}
+}
diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/verify.sh b/spring-cloud-function-samples/function-sample-supplier-exporter/verify.sh
new file mode 100644
index 000000000..3d4560817
--- /dev/null
+++ b/spring-cloud-function-samples/function-sample-supplier-exporter/verify.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+curl -s localhost:8000/add -d '{"name":"world"}' -H "Content-Type: text/plain"
+echo
+echo Waiting...
+sleep 1
+RESPONSE=`curl -s localhost:8000/take`
+echo Got response: $RESPONSE
+if [[ "$RESPONSE" == '{"name":"hi world!"}' ]]; then
+ exit 0
+else
+ exit 1
+fi
diff --git a/spring-cloud-function-samples/pom.xml b/spring-cloud-function-samples/pom.xml
index 9bad96a2a..f98633316 100644
--- a/spring-cloud-function-samples/pom.xml
+++ b/spring-cloud-function-samples/pom.xml
@@ -22,6 +22,7 @@
function-sample-task
function-sample-aws
function-sample-aws-custom
+ function-sample-supplier-exporter
function-sample-azure
function-sample-spring-integration
function-sample-gcp