Google Cloud Functions (Serverless)

quarkus-google-cloud-functions 扩展允许您使用 Quarkus 构建 Google Cloud Functions。您的功能可以使用来自 CDI 或 Spring 以及其他您需要的 Quarkus 工具的注入批注。

The quarkus-google-cloud-functions extension allows you to use Quarkus to build your Google Cloud Functions. Your functions can use injection annotations from CDI or Spring and other Quarkus facilities as you need them. Unresolved directive in gcp-functions.adoc - include::{includes}/extension-status.adoc[]

Prerequisites

Unresolved directive in gcp-functions.adoc - include::{includes}/prerequisites.adoc[]* A Google Cloud Account免费帐号有用。* Cloud SDK CLI Installed

Unresolved directive in gcp-functions.adoc - include::{includes}/prerequisites.adoc[] * A Google Cloud Account. Free accounts work. * Cloud SDK CLI Installed

Solution

本指南将引导您生成一个示例项目,然后创建多个功能,展示如何在 Quarkus 中实现 HttpFunctionBackgroundFunctionRawBackgroundFunction。构建完成后,您将能够将项目部署到 Google Cloud。

This guide walks you through generating a sample project followed by creating multiple functions showing how to implement HttpFunction, BackgroundFunction and RawBackgroundFunction in Quarkus. Once built, you will be able to deploy the project to Google Cloud.

如果您不想执行上述所有步骤,您可以直接转到完成的示例。

If you don’t want to follow all these steps, you can go right to the completed example.

克隆 Git 存储库: git clone {quickstarts-clone-url},或下载 {quickstarts-archive-url}[存档]。

Clone the Git repository: git clone {quickstarts-clone-url}, or download an {quickstarts-archive-url}[archive].

解决方案位于 google-cloud-functions-quickstart directory

The solution is located in the google-cloud-functions-quickstart directory.

Creating the Maven Deployment Project

使用 quarkus-google-cloud-functions 扩展创建一个应用程序。您可以使用以下 Maven 命令来创建它:

Create an application with the quarkus-google-cloud-functions extension. You can use the following Maven command to create it:

Unresolved directive in gcp-functions.adoc - include::{includes}/devtools/create-app.adoc[]

Login to Google Cloud

部署应用程序需要登录 Google Cloud。可以按以下方式进行操作:

Login to Google Cloud is necessary for deploying the application. It can be done as follows:

gcloud auth login

Creating the functions

对于此示例项目,我们将创建四个函数,一个 HttpFunction、一个 BackgroundFunction(Storage 事件)、一个 RawBackgroundFunction(PubSub 事件)和一个 CloudEventsFunction(使用 Cloud Events 规范的 Storage 事件)。

For this example project, we will create four functions, one HttpFunction, one BackgroundFunction (Storage event), one RawBackgroundFunction (PubSub event) and one CloudEventsFunction (storage event using the Cloud Events specification).

Quarkus 支持 Cloud Functions gen 1 和 gen 2。有关 Cloud Functions gen 2 的概述,请参阅 Google Cloud Functions 文档上的 this page。要使用 gen 2,您必须添加 --gen2 参数。

Quarkus supports Cloud Functions gen 1 and gen 2. For an overview of Cloud Functions gen 2 see this page on the Google Cloud Functions documentation. To use gen 2 you must add the --gen2 parameter.

Choose Your Function

quarkus-google-cloud-functions 扩展将在您的项目中扫描直接实现 Google Cloud HttpFunctionBackgroundFunctionRawBackgroundFunctionCloudEventsFunction 接口的类。它必须在您的项目中找到实现这些接口之一的类,否则将会抛出构建时故障。如果它找到多个函数类,也将抛出构建时异常。

The quarkus-google-cloud-functions extension scans your project for a class that directly implements the Google Cloud HttpFunction, BackgroundFunction, RawBackgroundFunction or CloudEventsFunction interface. It must find a class in your project that implements one of these interfaces, or it will throw a build time failure. If it finds more than one function classes, a build time exception will also be thrown.

不过,有时您可能有一些共享代码的相关函数,而创建多个 Maven 模块只是您不想进行的额外开销。此扩展允许您在一个项目中捆绑多个函数,并使用配置或环境变量来选择您要部署的函数。

Sometimes, though, you might have a few related functions that share code and creating multiple maven modules is just an overhead you don’t want to do. The extension allows you to bundle multiple functions in one project and use configuration or an environment variable to pick the function you want to deploy.

要配置函数的名称,可以使用以下配置属性:

To configure the name of the function, you can use the following configuration property:

quarkus.google-cloud-functions.function=test

quarkus.google-cloud-functions.function 属性告诉 Quarkus 要部署哪个函数。它还可以被环境变量覆盖。

The quarkus.google-cloud-functions.function property tells Quarkus which function to deploy. This can be overridden with an environment variable too.

函数类的 CDI 名称必须与 quarkus.google-cloud-functions.function 属性中指定的值匹配。必须使用 @Named 注释完成此操作。

The CDI name of the function class must match the value specified within the quarkus.google-cloud-functions.function property. This must be done using the @Named annotation.

@Named("test")
public class TestHttpFunction implements HttpFunction {
}

The HttpFunction

import java.io.Writer;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import io.quarkus.gcp.function.test.service.GreetingService;

@Named("httpFunction") (1)
@ApplicationScoped (2)
public class HttpFunctionTest implements HttpFunction { (3)
    @Inject GreetingService greetingService; (4)

    @Override
    public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { (5)
        Writer writer = httpResponse.getWriter();
        writer.write(greetingService.hello());
    }
}
1 The @Named annotation allows to name the CDI bean to be used by the quarkus.google-cloud-functions.function property, this is optional.
2 The function must be a CDI bean
3 This is a regular Google Cloud Function implementation, so it needs to implement com.google.cloud.functions.HttpFunction.
4 Injection works inside your function.
5 This is standard Google Cloud Function implementation, nothing fancy here.

The BackgroundFunction

这个 BackgroundFunction 由存储事件触发,您可以改为使用 Google Cloud 支持的任何事件。

This BackgroundFunction is triggered by a Storage event, you can use any events supported by Google Cloud instead.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import io.quarkus.gcp.function.test.service.GreetingService;


@Named("storageTest") (1)
@ApplicationScoped (2)
public class BackgroundFunctionStorageTest implements BackgroundFunction<BackgroundFunctionStorageTest.StorageEvent> { (3)
    @Inject GreetingService greetingService;  (4)

    @Override
    public void accept(StorageEvent event, Context context) throws Exception { (5)
        System.out.println("Receive event: " + event);
        System.out.println("Be polite, say " + greetingService.hello());
    }

    //
    public static class StorageEvent { (6)
        public String name;
    }
}
1 The @Named annotation allows to name the CDI bean to be used by the quarkus.google-cloud-functions.function property, this is optional.
2 The function must be a CDI bean
3 This is a regular Google Cloud Function implementation, so it needs to implement com.google.cloud.functions.BackgroundFunction.
4 Injection works inside your function.
5 This is standard Google Cloud Function implementation, nothing fancy here.
6 This is the class the event will be deserialized to.

The RawBackgroundFunction

这个 RawBackgroundFunction 由 PubSub 事件触发,您可以改为使用 Google Cloud 支持的任何事件。

This RawBackgroundFunction is triggered by a PubSub event, you can use any events supported by Google Cloud instead.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import com.google.cloud.functions.Context;
import com.google.cloud.functions.RawBackgroundFunction;
import io.quarkus.gcp.function.test.service.GreetingService;

@Named("rawPubSubTest") (1)
@ApplicationScoped (2)
public class RawBackgroundFunctionPubSubTest implements RawBackgroundFunction { (3)
    @Inject GreetingService greetingService; (4)

    @Override
    public void accept(String event, Context context) throws Exception { (5)
        System.out.println("PubSub event: " + event);
        System.out.println("Be polite, say " + greetingService.hello());
    }
}
1 The @Named annotation allows to name the CDI bean to be used by the quarkus.google-cloud-functions.function property, this is optional.
2 The function must be a CDI bean
3 This is a regular Google Cloud Function implementation, so it needs to implement com.google.cloud.functions.RawBackgroundFunction.
4 Injection works inside your function.
5 This is standard Google Cloud Function implementation, nothing fancy here.

The CloudEventsFunction

CloudEventsFunction 仅是 Cloud Functions Gen 2 的功能。

CloudEventsFunction is a feature of Cloud Functions gen 2 only.

这个 CloudEventsFunction 由 Cloud Events Storage 事件触发,您可以改为使用 Google Cloud 支持的任何 Cloud Events。

This CloudEventsFunction is triggered by a Cloud Events Storage event, you can use any Cloud Events supported by Google Cloud instead.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;

import com.google.cloud.functions.CloudEventsFunction;

import io.cloudevents.CloudEvent;
import io.quarkus.gcp.function.test.service.GreetingService;

@Named("cloudEventTest") (1)
@ApplicationScoped (2)
public class CloudEventStorageTest implements CloudEventsFunction { (3)
    @Inject
    GreetingService greetingService;  (4)

    @Override
    public void accept(CloudEvent cloudEvent) throws Exception { (5)
        System.out.println("Receive event Id: " + cloudEvent.getId());
        System.out.println("Receive event Subject: " + cloudEvent.getSubject());
        System.out.println("Receive event Type: " + cloudEvent.getType());
        System.out.println("Receive event Data: " + new String(cloudEvent.getData().toBytes())); (6)
        System.out.println("Be polite, say " + greetingService.hello());
    }
}
1 The @Named annotation allows to name the CDI bean to be used by the quarkus.google-cloud-functions.function property, this is optional.
2 The function must be a CDI bean
3 This is a regular Google Cloud Function implementation, so it needs to implement com.google.cloud.functions.CloudEventsFunction.
4 Injection works inside your function.
5 This is standard Google Cloud Function implementation, nothing fancy here except that it receives a io.cloudevents.CloudEvent.
6 This is the storage event inside the Cloud Events.

Build and Deploy to Google Cloud

若要构建您的应用程序,您可以使用标准命令对其进行打包:

To build your application, you can package it using the standard command:

Unresolved directive in gcp-functions.adoc - include::{includes}/devtools/build.adoc[]

前一个命令的结果是 target/deployment 存储库中的单个 JAR 文件,其中包含项目类和依赖性。

The result of the previous command is a single JAR file inside the target/deployment repository that contains classes and dependencies of the project.

然后,您将可以使用 gcloud 将您的函数部署到 Google Cloud。gcloud 命令将根据触发函数的事件而有所不同。

Then you will be able to use gcloud to deploy your function to Google Cloud. The gcloud command will be different depending on which event triggers your function.

我们将使用 Java 17 运行时,但你可以通过在部署命令中使用 --runtime=java21`来切换到 Java 21 运行时,而不是使用 `--runtime=java17

We will use the Java 17 runtime but you can switch to the Java 21 runtime by using --runtime=java21 instead of --runtime=java17 on the deploy commands.

当你第一次启动此命令时,会出现以下错误信息:

The first time you launch this command, you can have the following error message:

ERROR: (gcloud.functions.deploy) OperationError: code=7, message=Build Failed: Cloud Build has not been used in project <project_name> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=<my-project> then retry.

这意味着 Cloud Build 尚未激活。要解决此错误,请打开错误中显示的网址,按照说明操作,然后等待几分钟再重试该命令。

This means that Cloud Build is not activated yet. To overcome this error, open the URL shown in the error, follow the instructions and then wait a few minutes before retrying the command.

The HttpFunction

以下是一个将 `HttpFunction`部署到 Google Cloud 的示例命令:

This is an example command to deploy your HttpFunction to Google Cloud:

gcloud functions deploy quarkus-example-http \
  --entry-point=io.quarkus.gcp.functions.QuarkusHttpFunction \
  --runtime=java17 --trigger-http --allow-unauthenticated --source=target/deployment

入口点必须始终设置为 io.quarkus.gcp.functions.QuarkusHttpFunction,因为它是将 Cloud Functions 与 Quarkus 集成的类。

The entry point must always be set to io.quarkus.gcp.functions.QuarkusHttpFunction as this is the class that integrates Cloud Functions with Quarkus.

此命令将生成一个 httpsTrigger.url,指向你的函数。

This command will give you as output a httpsTrigger.url that points to your function.

The BackgroundFunction

在部署函数之前,你需要创建一个存储存储区。

Before deploying your function, you need to create a bucket.

gsutil mb gs://quarkus-hello

以下是一个将 `BackgroundFunction`部署到 Google Cloud 的示例命令,因为该函数是由存储事件触发的,因此需要使用 `--trigger-event google.storage.object.finalize`和 `--trigger-resource`参数,其中包含之前创建的存储存储区的名称:

This is an example command to deploy your BackgroundFunction to Google Cloud, as the function is triggered by a Storage event, it needs to use --trigger-event google.storage.object.finalize and the --trigger-resource parameter with the name of a previously created bucket:

gcloud functions deploy quarkus-example-storage \
    --entry-point=io.quarkus.gcp.functions.QuarkusBackgroundFunction \
    --trigger-resource quarkus-hello --trigger-event google.storage.object.finalize \
    --runtime=java17 --source=target/deployment

入口点必须始终设置为 io.quarkus.gcp.functions.QuarkusBackgroundFunction,因为它是将 Cloud Functions 与 Quarkus 集成的类。

The entry point must always be set to io.quarkus.gcp.functions.QuarkusBackgroundFunction as this is the class that integrates Cloud Functions with Quarkus.

要触发事件,你可以向 GCS `quarkus-hello`存储存储区发送一个文件,或者你可以使用 gcloud 模拟一个:

To trigger the event, you can send a file to the GCS quarkus-hello bucket, or you can use gcloud to simulate one:

gcloud functions call quarkus-example-storage  --data '{"name":"test.txt"}'

`--data`包含 GCS 事件,它是一个 JSON 文档,其中包含添加到存储存储区的的文件的名称。

--data contains the GCS event, it is a JSON document with the name of the file added to the bucket.

The RawBackgroundFunction

以下是一个将 `RawBackgroundFunction`部署到 Google Cloud 的示例命令,因为该函数是由 PubSub 事件触发的,因此需要使用 `--trigger-event google.pubsub.topic.publish`和 `--trigger-resource`参数,其中包含之前创建的主题的名称:

This is an example command to deploy your RawBackgroundFunction to Google Cloud, as the function is triggered by a PubSub event, it needs to use --trigger-event google.pubsub.topic.publish and the --trigger-resource parameter with the name of a previously created topic:

gcloud functions deploy quarkus-example-pubsub \
  --entry-point=io.quarkus.gcp.functions.QuarkusBackgroundFunction \
  --runtime=java17 --trigger-resource hello_topic --trigger-event google.pubsub.topic.publish --source=target/deployment

入口点必须始终设置为 io.quarkus.gcp.functions.QuarkusBackgroundFunction,因为它是将 Cloud Functions 与 Quarkus 集成的类。

The entry point must always be set to io.quarkus.gcp.functions.QuarkusBackgroundFunction as this is the class that integrates Cloud Functions with Quarkus.

要触发事件,你可以向 `hello_topic`主题发送一个文件,或者你可以使用 gcloud 模拟一个:

To trigger the event, you can send a file to the hello_topic topic, or you can use gcloud to simulate one:

gcloud functions call quarkus-example-pubsub --data '{"data":{"greeting":"world"}}'

The CloudEventsFunction

CloudEventsFunction 仅是 Cloud Functions Gen 2 的功能。

CloudEventsFunction is a feature of Cloud Functions gen 2 only.

以下是一个将 `CloudEventsFunction`部署到 Google Cloud 的示例命令,因为该函数是由存储事件触发的,因此需要使用 `--trigger-bucket`参数,其中包含之前创建的存储存储区的名称:

This is an example command to deploy your CloudEventsFunction to Google Cloud, as the function is triggered by a Storage event, it needs to use --trigger-bucket parameter with the name of a previously created bucket:

gcloud functions deploy quarkus-example-cloud-event --gen2 \
  --entry-point=io.quarkus.gcp.functions.QuarkusCloudEventsFunction \
  --runtime=java17 --trigger-bucket=example-cloud-event --source=target/deployment

入口点必须始终设置为 io.quarkus.gcp.functions.QuarkusCloudEventsFunction,因为它是将 Cloud Functions 与 Quarkus 集成的类。

The entry point must always be set to io.quarkus.gcp.functions.QuarkusCloudEventsFunction as this is the class that integrates Cloud Functions with Quarkus.

要触发事件,你可以向 GCS `example-cloud-event`存储存储区发送一个文件。

To trigger the event, you can send a file to the GCS example-cloud-event bucket.

Running locally

本地运行函数的最简单方法是使用 Cloud Function Invoker JAR。

The easiest way to locally run your function is using the Cloud Function invoker JAR.

你可以使用以下命令通过 Maven 下载它:

You can download it via Maven using the following command:

mvn dependency:copy \
  -Dartifact='com.google.cloud.functions.invoker:java-function-invoker:{gcf-invoker-version}' \
  -DoutputDirectory=.

使用 invoker 之前,您首先需要通过以下方式构建您的函数:

Before using the invoker, you first need to build your function via:

Unresolved directive in gcp-functions.adoc - include::{includes}/devtools/build.adoc[]

The HttpFunction

对于 HttpFunction,您可以使用此命令在本地启动您的函数。

For an HttpFunction, you can use this command to launch your function locally.

java -jar java-function-invoker-{gcf-invoker-version}.jar \
  --classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.gcp.functions.QuarkusHttpFunction

`--classpath`参数需要设置为先前打包的 JAR,其中包含您的函数类和所有 Quarkus 相关类。

The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.

您的端点将在 [role="bare"][role="bare"]http://localhost:8080上提供。

Your endpoints will be available on [role="bare"]http://localhost:8080.

The BackgroundFunction

对于后台函数,您可以使用目标类 `io.quarkus.gcp.functions.BackgroundFunction`启动 invoker。

For background functions, you launch the invoker with a target class of io.quarkus.gcp.functions.BackgroundFunction.

java -jar java-function-invoker-{gcf-invoker-version}.jar \
  --classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.gcp.functions.QuarkusBackgroundFunction

`--classpath`参数需要设置为先前打包的 JAR,其中包含您的函数类和所有 Quarkus 相关类。

The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.

然后,您可以通过 HTTP 调用(其包含事件的有效负载)来调用您的 background 函数:

Then you can call your background function via an HTTP call with a payload containing the event:

curl localhost:8080 -d '{"data":{"name":"hello.txt"}}'

这将使用事件 {"name":"hello.txt"}(即 `hello.txt`文件上的事件)调用您的 Storage background 函数。

This will call your Storage background function with an event {"name":"hello.txt"}, so an event on the hello.txt file.

The RawBackgroundFunction

对于后台函数,您可以使用目标类 `io.quarkus.gcp.functions.BackgroundFunction`启动 invoker。

For background functions, you launch the invoker with a target class of io.quarkus.gcp.functions.BackgroundFunction.

java -jar java-function-invoker-{gcf-invoker-version}.jar \
  --classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.gcp.functions.QuarkusBackgroundFunction

`--classpath`参数需要设置为先前打包的 JAR,其中包含您的函数类和所有 Quarkus 相关类。

The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.

然后,您可以通过 HTTP 调用(其包含事件的有效负载)来调用您的 background 函数:

Then you can call your background function via an HTTP call with a payload containing the event:

curl localhost:8080 -d '{"data":{"greeting":"world"}}'

这将使用 PubSubMessage `{"greeting":"world"}`调用您的 PubSub background 函数。

This will call your PubSub background function with a PubSubMessage {"greeting":"world"}.

The CloudEventsFunction

`CloudEventsFunction`是仅适用于 Cloud Function 第 2 代的一项功能。

CloudEventsFunction is a feature of Cloud Function gen 2 only.

对于云事件函数,您可以使用目标类 `io.quarkus.gcp.functions.QuarkusCloudEventsFunction`启动 invoker。

For cloud events functions, you launch the invoker with a target class of io.quarkus.gcp.functions.QuarkusCloudEventsFunction.

java -jar java-function-invoker-{gcf-invoker-version}.jar \
  --classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.gcp.functions.QuarkusCloudEventsFunction

`--classpath`参数需要设置为先前打包的 JAR,其中包含您的函数类和所有 Quarkus 相关类。

The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.

然后,您可以通过 HTTP 调用(其包含事件的有效负载)来调用您的云事件函数:

Then you can call your cloud events function via an HTTP call with a payload containing the event:

curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -H "ce-id: 123451234512345" \
  -H "ce-specversion: 1.0" \
  -H "ce-time: 2020-01-02T12:34:56.789Z" \
  -H "ce-type: google.cloud.storage.object.v1.finalized" \
  -H "ce-source: //storage.googleapis.com/projects/_/buckets/MY-BUCKET-NAME" \
  -H "ce-subject: objects/MY_FILE.txt" \
  -d '{
        "bucket": "MY_BUCKET",
        "contentType": "text/plain",
        "kind": "storage#object",
        "md5Hash": "...",
        "metageneration": "1",
        "name": "MY_FILE.txt",
        "size": "352",
        "storageClass": "MULTI_REGIONAL",
        "timeCreated": "2020-04-23T07:38:57.230Z",
        "timeStorageClassUpdated": "2020-04-23T07:38:57.230Z",
        "updated": "2020-04-23T07:38:57.230Z"
      }'

这将使用 `"MY_FILE.txt`文件上的事件调用您的云事件函数。

This will call your cloud events function with an event on the "MY_FILE.txt file.

Testing your function

Quarkus 提供了内置支持,您可以通过 `quarkus-test-google-cloud-functions`依赖项来测试您的 Google Cloud 函数。

Quarkus provides built-in support for testing your Google Cloud functions via the quarkus-test-google-cloud-functions dependency.

要使用它,您必须在 `pom.xml`中添加以下测试依赖项。

To use it, you must add the following test dependency in your pom.xml.

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-test-google-cloud-functions</artifactId>
    <scope>test</scope>
</dependency>

此扩展提供了 `@WithFunction`注释,该注释可用于注释 `@QuarkusTest`测试用例,以便在测试用例之前启动 Cloud Function invoker 并在此类结束之后停止它。必须使用您想要启动的函数的类型来配置此注释,还可以选择函数的名称(如果您在应用程序中有多个函数)。

This extension provides a @WithFunction annotation that can be used to annotate @QuarkusTest test cases to start a Cloud Function invoker before you test cases and stop it at the end. This annotation must be configured with the type of the function you want to launch, and optionally the name of the function in case you have multiple functions inside your application.

将尊重默认 Quarkus 测试端口配置 (quarkus.http.test-port),如果您将它设置为 0,则会将一个随机端口分配给函数 invoker。

The default Quarkus test port configuration (quarkus.http.test-port) will be honored and if you set it to 0 a random port will be assigned to the function invoker.

The HttpFunction

import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.is;

import org.junit.jupiter.api.Test;

import io.quarkus.google.cloud.functions.test.FunctionType;
import io.quarkus.google.cloud.functions.test.WithFunction;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest (1)
@WithFunction(FunctionType.HTTP) (2)
class HttpFunctionTestCase {
    @Test
    public void test() {
        when()
                .get()
                .then()
                .statusCode(200)
                .body(is("Hello World!")); (3)
    }
}
  1. This is a standard Quarkus test that must be annotated by @QuarkusTest.

  2. @WithFunction(FunctionType.HTTP) indicates to launch the function as an HTTP function. If multiple functions exist in the same application, the functionName attribute must be used to denote which one should be launched.

  3. REST-assured is used to test the function, Hello World! will be sent to it via the invoker.

The BackgroundFunction

import static io.restassured.RestAssured.given;

import org.junit.jupiter.api.Test;

import io.quarkus.google.cloud.functions.test.FunctionType;
import io.quarkus.google.cloud.functions.test.WithFunction;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest (1)
@WithFunction(FunctionType.BACKGROUND) (2)
class BackgroundFunctionStorageTestCase {
    @Test
    public void test() {
        given()
                .body("{\"data\":{\"name\":\"hello.txt\"}}") (3)
                .when()
                .post()
                .then()
                .statusCode(200);
    }
}
  1. This is a standard Quarkus test that must be annotated by @QuarkusTest.

  2. @WithFunction(FunctionType.BACKGROUND) indicates to launch the function as a background function. If multiple functions exist in the same application, the functionName attribute must be used to denote which one should be launched.

  3. REST-assured is used to test the function, {"name":"hello.txt"} will be sent to it via the invoker.

The RawBackgroundFunction

import static io.restassured.RestAssured.given;

import org.junit.jupiter.api.Test;

import io.quarkus.google.cloud.functions.test.FunctionType;
import io.quarkus.google.cloud.functions.test.WithFunction;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest (1)
@WithFunction(FunctionType.RAW_BACKGROUND) (2)
class RawBackgroundFunctionPubSubTestCase {
    @Test
    public void test() {
        given()
                .body("{\"data\":{\"name\":\"hello.txt\"}}") (3)
                .when()
                .post()
                .then()
                .statusCode(200);
    }
}
  1. This is a standard Quarkus test that must be annotated by @QuarkusTest.

  2. @WithFunction(FunctionType.RAW_BACKGROUND) indicates to launch the function as a raw background function. If multiple functions exist in the same application, the functionName attribute must be used to denote which one should be launched.

  3. REST-assured is used to test the function, {"name":"hello.txt"} will be sent to it via the invoker.

The CloudEventsFunction

Cloud Events 函数仅是 Cloud Functions gen 2 的一项功能。

Cloud Events Function is a feature of Cloud Functions gen 2 only.

import static io.restassured.RestAssured.given;

import org.junit.jupiter.api.Test;

import io.quarkus.google.cloud.functions.test.FunctionType;
import io.quarkus.google.cloud.functions.test.WithFunction;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest (1)
@WithFunction(FunctionType.CLOUD_EVENTS) (2)
class CloudEventStorageTestCase {
    @Test
    public void test() {
        // test the function using RestAssured
        given()
                .body("{\n" + (3)
                        "        \"bucket\": \"MY_BUCKET\",\n" +
                        "        \"contentType\": \"text/plain\",\n" +
                        "        \"kind\": \"storage#object\",\n" +
                        "        \"md5Hash\": \"...\",\n" +
                        "        \"metageneration\": \"1\",\n" +
                        "        \"name\": \"MY_FILE.txt\",\n" +
                        "        \"size\": \"352\",\n" +
                        "        \"storageClass\": \"MULTI_REGIONAL\",\n" +
                        "        \"timeCreated\": \"2020-04-23T07:38:57.230Z\",\n" +
                        "        \"timeStorageClassUpdated\": \"2020-04-23T07:38:57.230Z\",\n" +
                        "        \"updated\": \"2020-04-23T07:38:57.230Z\"\n" +
                        "      }")
                .header("ce-specversion", "1.0") (4)
                .header("ce-id", "1234567890")
                .header("ce-type", "google.cloud.storage.object.v1.finalized")
                .header("ce-source", "//storage.googleapis.com/projects/_/buckets/MY-BUCKET-NAME")
                .header("ce-subject", "objects/MY_FILE.txt")
                .when()
                .post()
                .then()
                .statusCode(200);
    }
}
  1. This is a standard Quarkus test that must be annotated by @QuarkusTest.

  2. @WithFunction(FunctionType.CLOUD_EVENTS) indicates to launch the function as a cloud events function. If multiple functions exist in the same application, the functionName attribute must be used to denote which one should be launched.

  3. REST-assured is used to test the function, this payload that describe a storage event will be sent to it via the invoker.

  4. The cloud events headers must be sent via HTTP headers.

What’s next?

如果您正在为 Google Cloud Functions 寻找 Jakarta REST、Servlet 或 Vert.x 支持,我们已经使用Google Cloud Functions HTTP binding实现了该支持。

If you are looking for Jakarta REST, Servlet or Vert.x support for Google Cloud Functions, we have it thanks to our Google Cloud Functions HTTP binding.

如果您正在为 Google Cloud 函数寻找供应商无关的实现,我们已使用Funqy Google Cloud Functions extension实现了该实现。

If you are looking for a provider-agnostic implementation of your Google Cloud Functions, we have it thanks to our Funqy Google Cloud Functions extension.