diff --git a/spring-cloud-function-deployer-new/pom.xml b/spring-cloud-function-deployer-new/pom.xml
index 295d2c5d1..ad178f090 100644
--- a/spring-cloud-function-deployer-new/pom.xml
+++ b/spring-cloud-function-deployer-new/pom.xml
@@ -30,6 +30,11 @@
org.springframework.cloud
spring-cloud-function-context
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
org.springframework.boot
spring-boot-configuration-processor
@@ -37,6 +42,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-invoker-plugin
+ 3.0.1
+
+ ${project.build.directory}/local-repo
+
+
+
+
+ prepare-test
+ test-compile
+
+ run
+
+
+ ${project.build.directory}/it
+
+ src/it/settings.xml
+ true
+ true
+
+
+
+
+
+
+
spring-milestones
diff --git a/spring-cloud-function-deployer-new/src/it/bootapp/pom.xml b/spring-cloud-function-deployer-new/src/it/bootapp/pom.xml
new file mode 100644
index 000000000..e319a8cf8
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootapp/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+ function.example
+ bootapp
+ 0.0.1.BUILD-SNAPSHOT
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.0.BUILD-SNAPSHOT
+
+
+
+
+ 1.8
+ 3.0.0.BUILD-SNAPSHOT
+ 1.0.17.RELEASE
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ exec
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack
+ package
+
+ unpack
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ exec
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java
new file mode 100644
index 000000000..ed8f694ef
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java
@@ -0,0 +1,57 @@
+package function.example;
+
+import java.util.function.Function;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class SimpleFunctionAppApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SimpleFunctionAppApplication.class, args);
+ }
+
+ @Bean
+ public Function uppercase() {
+ System.out.println("==> CREATING 'uppercase' FUNCTION bean");
+ return new UpperCaseFunction();
+ }
+
+ @Bean
+ public Function uppercasePerson() {
+ System.out.println("==> CREATING 'uppercasePerson' FUNCTION bean");
+ return person -> {
+ Person p = new Person();
+ p.setId(person.getId());
+ p.setName(person.getName().toUpperCase());
+ return p;
+ };
+ }
+
+
+
+ public static class Person {
+ private String name;
+
+ private int id;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ }
+}
diff --git a/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java
new file mode 100644
index 000000000..859a54a58
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java
@@ -0,0 +1,13 @@
+package function.example;
+
+import java.util.function.Function;
+
+public class UpperCaseFunction implements Function {
+
+ @Override
+ public String apply(String value) {
+ System.out.println("Uppercasing " + value);
+ return value.toUpperCase();
+ }
+
+}
diff --git a/spring-cloud-function-deployer-new/src/it/bootjar/pom.xml b/spring-cloud-function-deployer-new/src/it/bootjar/pom.xml
new file mode 100644
index 000000000..e6b3d767e
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootjar/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+ function.example
+ bootjar
+ 0.0.1.BUILD-SNAPSHOT
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.0.BUILD-SNAPSHOT
+
+
+
+
+ 1.8
+ 3.0.0.BUILD-SNAPSHOT
+ 1.0.17.RELEASE
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ exec
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack
+ package
+
+ unpack
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ exec
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java
new file mode 100644
index 000000000..4327b2cbe
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java
@@ -0,0 +1,38 @@
+package function.example;
+
+import java.util.function.Function;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+public class SimpleFunctionAppApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SimpleFunctionAppApplication.class, args);
+ }
+
+ public static class Person {
+ private String name;
+
+ private int id;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ }
+}
diff --git a/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java
new file mode 100644
index 000000000..859a54a58
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java
@@ -0,0 +1,13 @@
+package function.example;
+
+import java.util.function.Function;
+
+public class UpperCaseFunction implements Function {
+
+ @Override
+ public String apply(String value) {
+ System.out.println("Uppercasing " + value);
+ return value.toUpperCase();
+ }
+
+}
diff --git a/spring-cloud-function-deployer-new/src/it/settings.xml b/spring-cloud-function-deployer-new/src/it/settings.xml
new file mode 100644
index 000000000..e1e0ace34
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/it/settings.xml
@@ -0,0 +1,35 @@
+
+
+
+
+ it-repo
+
+ true
+
+
+
+ local.central
+ @localRepositoryUrl@
+
+ true
+
+
+ true
+
+
+
+
+
+ local.central
+ @localRepositoryUrl@
+
+ true
+
+
+ true
+
+
+
+
+
+
diff --git a/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/ApplicationContainer.java b/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/ApplicationContainer.java
index 5bf6cecf6..887234311 100644
--- a/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/ApplicationContainer.java
+++ b/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/ApplicationContainer.java
@@ -32,14 +32,11 @@ public abstract class ApplicationContainer {
private final FunctionProperties functionProperties;
- private final Object function;
-
public ApplicationContainer(FunctionCatalog functionCatalog,
FunctionInspector functionInspector, FunctionProperties functionProperties) {
this.functionCatalog = functionCatalog;
this.functionInspector = functionInspector;
this.functionProperties = functionProperties;
- this.function = this.functionCatalog.lookup(this.functionProperties.getFunctionName());
}
protected FunctionCatalog getFunctionCatalog() {
@@ -56,6 +53,11 @@ public abstract class ApplicationContainer {
@SuppressWarnings("unchecked")
public T getFunction() {
- return (T) this.function;
+ return (T) this.functionCatalog.lookup(this.functionProperties.getFunctionName());
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getFunction(String... acceptedOutputMimeTypes) {
+ return (T) this.functionCatalog.lookup(this.functionProperties.getFunctionName(), acceptedOutputMimeTypes);
}
}
diff --git a/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/FunctionProperties.java b/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/FunctionProperties.java
index d399a6563..c6c612dba 100644
--- a/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/FunctionProperties.java
+++ b/spring-cloud-function-deployer-new/src/main/java/org/springframework/cloud/function/deployer/FunctionProperties.java
@@ -31,12 +31,19 @@ import org.springframework.util.StringUtils;
public class FunctionProperties {
/**
- * Location(s) of jar archives containing the supplier/function/consumer class to run.
+ * Location of jar archive containing the supplier/function/consumer class or bean to run.
*/
private String location;
+ /**
+ * The name of the function to be looked up from the FunctionCatalog (e.g., bean name).
+ */
private String functionName;
+ /**
+ * The name of the function class tyo be instantiated and loaded into FunctionCatalog. The name of the
+ * function will be decapitalized simple name of this class.
+ */
private String functionClass;
public void setFunctionClass(String functionClass) {
diff --git a/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/ApplicationContainerTests.java b/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/ApplicationContainerTests.java
new file mode 100644
index 000000000..bff4eb402
--- /dev/null
+++ b/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/ApplicationContainerTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017-2019 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
+ *
+ * https://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.
+ */
+
+package org.springframework.cloud.function.deployer;
+
+import java.nio.charset.StandardCharsets;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.springframework.cloud.function.context.FunctionCatalog;
+import org.springframework.cloud.function.context.catalog.FunctionInspector;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+/**
+ *
+ * @author Oleg Zhurakousky
+ * @since 3.0
+ */
+public class ApplicationContainerTests {
+
+ @Test
+ public void testCustomApplicationContainerWithBootJar() throws Exception {
+ String[] args = new String[] {"--spring.cloud.function.location=target/it/bootjar/target/bootjar-0.0.1.BUILD-SNAPSHOT-exec.jar",
+ "--spring.cloud.function.function-class=function.example.UpperCaseFunction"};
+
+ JavaInvoker invokerByClass =
+ FunctionDeployerBootstrap.instance(args).run(JavaInvoker.class, args);
+
+ assertThat(invokerByClass.uppercaseSimple("bob")).isEqualTo("BOB");
+ assertThat(invokerByClass.uppercaseSimple("stacy")).isEqualTo("STACY");
+ }
+
+ @Test
+ public void testCustomApplicationContainerWithBootAppSimpleTypes() throws Exception {
+
+ String[] args = new String[] {"--spring.cloud.function.location=target/it/bootapp/target/bootapp-0.0.1.BUILD-SNAPSHOT-exec.jar",
+ "--spring.cloud.function.function-name=uppercase"};
+ JavaInvoker invokerByBean =
+ FunctionDeployerBootstrap.instance(args).run(JavaInvoker.class, args);
+
+ Message result = invokerByBean.uppercase(MessageBuilder.withPayload("\"bob\"".getBytes(StandardCharsets.UTF_8)).build());
+ assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("\"BOB\"");
+ }
+
+ @Test
+ public void testCustomApplicationContainerWithBootAppWithTypeConversion() throws Exception {
+
+ String[] args = new String[] {"--spring.cloud.function.location=target/it/bootapp/target/bootapp-0.0.1.BUILD-SNAPSHOT-exec.jar",
+ "--spring.cloud.function.function-name=uppercasePerson"};
+
+ JavaInvoker invokerByBean =
+ FunctionDeployerBootstrap.instance(args).run(JavaInvoker.class, args);
+
+ Message result = invokerByBean.uppercase(MessageBuilder.withPayload("{\"name\":\"bob\",\"id\":1}".getBytes(StandardCharsets.UTF_8)).build());
+ assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("{\"name\":\"BOB\",\"id\":1}");
+ }
+
+ private static class JavaInvoker extends ApplicationContainer {
+
+ JavaInvoker(FunctionCatalog functionCatalog, FunctionInspector functionInspector,
+ FunctionProperties functionProperties) {
+ super(functionCatalog, functionInspector, functionProperties);
+ }
+
+ public Message uppercase(Message input) {
+ Function, Message> functon = this.getFunction("application/json");
+ return functon.apply(input);
+ }
+
+ public String uppercaseSimple(String input) {
+ Function functon = this.getFunction();
+ return functon.apply(input);
+ }
+ }
+}
diff --git a/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/sample/SampleInvoker.java b/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/sample/SampleInvoker.java
deleted file mode 100644
index 4aa562b7b..000000000
--- a/spring-cloud-function-deployer-new/src/test/java/org/springframework/cloud/function/deployer/sample/SampleInvoker.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2017-2019 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
- *
- * https://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.
- */
-
-package org.springframework.cloud.function.deployer.sample;
-
-import java.util.function.Function;
-
-import org.springframework.cloud.function.context.FunctionCatalog;
-import org.springframework.cloud.function.context.catalog.FunctionInspector;
-import org.springframework.cloud.function.deployer.ApplicationContainer;
-import org.springframework.cloud.function.deployer.FunctionDeployerBootstrap;
-import org.springframework.cloud.function.deployer.FunctionProperties;
-
-/**
- *
- * @author Oleg Zhurakousky
- * @since 3.0
- */
-public class SampleInvoker extends ApplicationContainer {
-
- public static void main(String[] args) throws Exception {
- SampleInvoker invokerByClass = FunctionDeployerBootstrap.instance(
- "--spring.cloud.function.location=/Users/olegz/Downloads/simple-function-app/jars/simple-function-jar-0.0.1-SNAPSHOT.jar",
- "--spring.cloud.function.function-class=oz.function.simplefunctionapp.UpperCaseFunction")
- .run(SampleInvoker.class, args);
-
- System.out.println(invokerByClass.uppercase("eric"));
- System.out.println(invokerByClass.uppercase("oleg"));
-
- SampleInvoker invokerByBean = FunctionDeployerBootstrap.instance(
- "--spring.cloud.function.location=/Users/olegz/Downloads/simple-function-app/jars/simple-function-app-0.0.1-SNAPSHOT.jar",
- "--spring.cloud.function.function-name=uppercase")
- .run(SampleInvoker.class, args);
-
- System.out.println(invokerByBean.uppercase("eric"));
- System.out.println(invokerByBean.uppercase("oleg"));
- }
-
- public SampleInvoker(FunctionCatalog functionCatalog, FunctionInspector functionInspector,
- FunctionProperties functionProperties) {
- super(functionCatalog, functionInspector, functionProperties);
- }
-
- public String uppercase(String value) {
- Function functon = this.getFunction();
- return functon.apply(value);
- }
-
-}