diff --git a/docs/src/main/asciidoc/adapters/gcp-intro.adoc b/docs/src/main/asciidoc/adapters/gcp-intro.adoc
index 101af96d5..d95221a2a 100644
--- a/docs/src/main/asciidoc/adapters/gcp-intro.adoc
+++ b/docs/src/main/asciidoc/adapters/gcp-intro.adoc
@@ -36,7 +36,7 @@ Start by adding the Maven plugin provided as part of the Google Functions Framew
function-maven-plugin
0.9.1
- org.springframework.cloud.function.adapter.gcloud.GcfSpringBootHttpRequestHandler
+ org.springframework.cloud.function.adapter.gcloud.FunctionInvoker
8080
@@ -118,7 +118,7 @@ From the project base directory run the following command to deploy.
----
gcloud alpha functions deploy function-sample-gcp \
---entry-point org.springframework.cloud.function.adapter.gcloud.GcfSpringBootHttpRequestHandler \
+--entry-point org.springframework.cloud.function.adapter.gcloud.FunctionInvoker \
--runtime java11 \
--trigger-http \
--source deploy \
diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml
index 3992f19fd..2c2bd5734 100644
--- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml
+++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml
@@ -18,7 +18,6 @@
UTF-8
UTF-8
1.0.0-alpha-2-rc3
- 2.8.5
@@ -31,17 +30,11 @@
com.google.code.gson
gson
- ${gson.version}
org.springframework.cloud
spring-cloud-function-context
-
- org.springframework.cloud
- spring-cloud-starter-function-web
-
-
org.springframework.boot
diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvoker.java
new file mode 100644
index 000000000..9d2d087bf
--- /dev/null
+++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvoker.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020-2020 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.adapter.gcloud;
+
+import java.io.BufferedReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Map.Entry;
+import java.util.function.Function;
+
+import com.google.cloud.functions.HttpFunction;
+import com.google.cloud.functions.HttpRequest;
+import com.google.cloud.functions.HttpResponse;
+
+import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.util.Assert;
+import org.springframework.util.MimeTypeUtils;
+
+/**
+ * Implementation of {@link HttpFunction} for Google Cloud Function (GCF).
+ * This is the Spring Cloud Function adapter for GCF HTTP function.
+ *
+ * @author Dmitry Solomakha
+ * @author Mike Eltsufin
+ * @author Oleg Zhurakousky
+ *
+ * @since 3.0.4
+ */
+public class FunctionInvoker
+ extends AbstractSpringFunctionAdapterInitializer implements HttpFunction {
+
+ public FunctionInvoker() {
+ super();
+ }
+
+ public FunctionInvoker(Class> configurationClass) {
+ super(configurationClass);
+ System.setProperty("spring.http.converters.preferred-json-mapper", "gson");
+ Thread.currentThread() //TODO investigate if it is necessary
+ .setContextClassLoader(FunctionInvoker.class.getClassLoader());
+ initialize(null);
+ }
+
+ /**
+ * The implementation of a GCF {@link HttpFunction} that will be used as the entry point from GCF.
+ */
+ @Override
+ public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception {
+ try {
+ String functionName = System.getenv().containsKey("spring.cloud.function.definition")
+ ? System.getenv("spring.cloud.function.definition") : "";
+
+ Function, Message> function =
+ this.catalog.lookup(functionName, MimeTypeUtils.APPLICATION_JSON.toString());
+ Assert.notNull(function, "'function' with name '" + functionName + "' must not be null");
+
+ Message message = getInputType() == Void.class
+ ? null : MessageBuilder.withPayload(httpRequest.getReader())
+ .copyHeaders(httpRequest.getHeaders())
+ .build();
+ Message result = function.apply(message);
+
+ if (result != null) {
+ httpResponse.getWriter().write(new String(result.getPayload(), StandardCharsets.UTF_8));
+ for (Entry header : result.getHeaders().entrySet()) {
+ httpResponse.appendHeader(header.getKey(), header.getValue().toString());
+ }
+ }
+ }
+ finally {
+ httpResponse.getWriter().close();
+ }
+ }
+}
diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandler.java
deleted file mode 100644
index 37b05b29d..000000000
--- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandler.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2020-2020 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.adapter.gcloud;
-
-import com.google.cloud.functions.HttpFunction;
-import com.google.cloud.functions.HttpRequest;
-import com.google.cloud.functions.HttpResponse;
-import com.google.gson.Gson;
-import org.reactivestreams.Publisher;
-import reactor.core.publisher.Mono;
-
-import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer;
-
-/**
- * Implementation of {@link HttpFunction} for Google Cloud Function (GCF).
- * This is the Spring Cloud Function adapter for GCF HTTP function.
- *
- * @author Dmitry Solomakha
- * @author Mike Eltsufin
- */
-public class GcfSpringBootHttpRequestHandler
- extends AbstractSpringFunctionAdapterInitializer implements HttpFunction {
-
- private final Gson gson = new Gson();
-
- public GcfSpringBootHttpRequestHandler() {
- super();
- }
-
- public GcfSpringBootHttpRequestHandler(Class> configurationClass) {
- super(configurationClass);
- }
-
- /**
- * The implementation of a GCF {@link HttpFunction} that will be used as the entrypoint from GCF.
- */
- @Override
- public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception {
- Thread.currentThread()
- .setContextClassLoader(GcfSpringBootHttpRequestHandler.class.getClassLoader());
-
- initialize(httpRequest);
-
- Publisher> input;
- if (getInputType() == Void.class) {
- input = Mono.empty();
- }
- else {
- input = Mono.just(gson.fromJson(httpRequest.getReader(), getInputType()));
- }
-
- Publisher> output = this.apply(input);
-
- Object result = this.result(input, output);
-
- httpResponse.getWriter().write(gson.toJson(result));
- httpResponse.getWriter().close();
- }
-}
diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvokerTests.java
similarity index 78%
rename from spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandlerTests.java
rename to spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvokerTests.java
index 92292ac53..3ea8ed9fc 100644
--- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/GcfSpringBootHttpRequestHandlerTests.java
+++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcloud/FunctionInvokerTests.java
@@ -34,6 +34,8 @@ import org.springframework.cloud.function.context.config.ContextFunctionCatalogA
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
@@ -44,7 +46,7 @@ import static org.mockito.Mockito.when;
* @author Dmitry Solomakha
* @author Mike Eltsufin
*/
-public class GcfSpringBootHttpRequestHandlerTests {
+public class FunctionInvokerTests {
private static final Gson gson = new Gson();
@@ -71,21 +73,23 @@ public class GcfSpringBootHttpRequestHandlerTests {
}
private void testFunction(Class> configurationClass, I input, O expectedOutput) throws Exception {
- GcfSpringBootHttpRequestHandler handler = new GcfSpringBootHttpRequestHandler(configurationClass);
+ try (FunctionInvoker handler = new FunctionInvoker(configurationClass);) {
- HttpRequest request = Mockito.mock(HttpRequest.class);
+ HttpRequest request = Mockito.mock(HttpRequest.class);
- if (input != null) {
- when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input))));
+ if (input != null) {
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input))));
+ }
+
+ HttpResponse response = Mockito.mock(HttpResponse.class);
+ StringWriter writer = new StringWriter();
+ when(response.getWriter()).thenReturn(new BufferedWriter(writer));
+
+ handler.service(request, response);
+ if (expectedOutput != null) {
+ assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput));
+ }
}
-
- HttpResponse response = Mockito.mock(HttpResponse.class);
- StringWriter writer = new StringWriter();
- when(response.getWriter()).thenReturn(new BufferedWriter(writer));
-
- handler.service(request, response);
-
- assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput));
}
@Configuration
@@ -110,8 +114,11 @@ public class GcfSpringBootHttpRequestHandlerTests {
@Import({ ContextFunctionCatalogAutoConfiguration.class })
protected static class JsonInputOutputFunction {
@Bean
- public Function function() {
- return (in) -> new OutgoingResponse("Thank you for sending the message: " + in.message);
+ public Function> function() {
+ return (in) -> {
+ return MessageBuilder.withPayload(new OutgoingResponse("Thank you for sending the message: " + in.message))
+ .setHeader("foo", "bar").build();
+ };
}
}
diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java
index 494777067..eb385b905 100644
--- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java
+++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java
@@ -33,7 +33,6 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.cloud.function.context.catalog.FunctionInspector;
@@ -79,7 +78,7 @@ public abstract class AbstractSpringFunctionAdapterInitializer implements Clo
private FunctionInspector inspector;
@Autowired(required = false)
- private FunctionCatalog catalog;
+ protected FunctionCatalog catalog;
private ConfigurableApplicationContext context;
@@ -266,7 +265,7 @@ public abstract class AbstractSpringFunctionAdapterInitializer implements Clo
new FunctionRegistration(context.getBean(name), name);
Type type = FunctionContextUtils.
- findType(name, (ConfigurableListableBeanFactory) this.context.getBeanFactory());
+ findType(name, this.context.getBeanFactory());
this.functionRegistration = functionRegistration.type(new FunctionType(type)).wrap();