The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Funqy Google Cloud Functions

このガイドでは、Funqy 関数を Google Cloud Functions にデプロイする方法をクイックスタートコードで説明しています。

この技術は、previewと考えられています。

preview では、下位互換性やエコシステムでの存在は保証されていません。具体的な改善には設定や API の変更が必要になるかもしれませんが、 stable になるための計画は現在進行中です。フィードバックは メーリングリストGitHub の課題管理 で受け付けています。

とりうるステータスの完全なリストについては、 FAQの項目 を参照してください。

前提条件

このガイドを完成させるには、以下が必要です:

Google Cloud にログイン

アプリケーションのデプロイには Google Cloud へのログインが必要で、以下のように行うことが出来ます:

gcloud auth login

クイックスタート

Git レポジトリーをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.gitアーカイブ をダウンロードします。

ソリューションは funqy-google-cloud-functions-quickstart ディレクトリ にあります。

Maven デプロイメントプロジェクトの作成

quarkus-funqy-google-cloud-functions のエクステンションを持つアプリケーションを作成します。 以下の Maven コマンドを使って作成します。

コマンドラインインタフェース
quarkus create app org.acme:funqy-google-cloud-functions \
    --extension='funqy-google-cloud-functions' \
    --no-code
cd funqy-google-cloud-functions

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.9.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=funqy-google-cloud-functions \
    -Dextensions='funqy-google-cloud-functions' \
    -DnoCode
cd funqy-google-cloud-functions

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=funqy-google-cloud-functions"

コード

このコードには何も特別なものはありません。また、重要なこととして、Google Cloud に特化したものは何もありません。Funqy 関数はさまざまな環境にデプロイすることができ、Google Cloud Functions はそのうちの 1 つです。

関数の選択

Google Cloud Functions のデプロイごとにエクスポートできる Funqy 関数は 1 つだけです。プロジェクト内に @Funq でアノテーションされたメソッドが 1 つしかない場合は、心配ありません。プロジェクト内に複数の関数が定義されている場合は、Quarkus application.properties 内で関数を選択する必要があります。

quarkus.funqy.export=greet

あるいは、gcloud cliを使って Google Cloud Function を作成する際に、環境変数 QUARKUS_FUNQY_EXPORT を設定することもできます。

ビルドとデプロイ

プロジェクトのビルド

コマンドラインインタフェース
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

これでコードがコンパイルされ、パッケージ化されます。

関数の作成

この例では、2 つのバックグラウンド関数とcloud events functionを作成します。バックグラウンド関数は、PubSub メッセージ、Cloud Storage イベント、Firestore イベントなどの Google Cloud eventに対応することができます。cloud events functionを使用すると、Cloud Events 仕様を使用して、サポートされているイベントに対応できます。

Quarkusは、Cloud Functionsの第1世代と第2世代をサポートしています。Cloud Functions gen 2の概要については、Google Cloud Functionsのドキュメントの このページ を参照してください。gen 2を使用するには、 --gen2 パラメータを追加する必要があります。
import jakarta.inject.Inject;

import io.cloudevents.CloudEvent;
import io.quarkus.funqy.Funq;
import io.quarkus.funqy.gcp.functions.event.PubsubMessage;
import io.quarkus.funqy.gcp.functions.event.StorageEvent;

public class GreetingFunctions {

    @Inject GreetingService service; (1)

    @Funq (2)
    public void helloPubSubWorld(PubsubMessage pubSubEvent) {
        String message = service.hello(pubSubEvent.data);
        System.out.println(pubSubEvent.messageId + " - " + message);
    }

    @Funq (3)
    public void helloGCSWorld(StorageEvent storageEvent) {
        String message = service.hello("world");
        System.out.println(storageEvent.name + " - " + message);
    }

    @Funq (4)
    public void helloCloudEvent(CloudEvent cloudEvent) {
        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()));
        System.out.println("Be polite, say " + service.hello("world"));
    }
}
関数の戻り値の型は、Mutiny 反応型も可能です。
  1. インジェクションは Cloud Function 関数クラスの中で動作します。

  2. これは、io.quarkus.funqy.gcp.functions.event.PubsubMessage をパラメーターとするバックグルアンド関数で、PubSub メッセージをデシリアライズする便利なクラスです。

  3. これは、io.quarkus.funqy.gcp.functions.event.StorageEvent をパラメーターとするバックグラウンド関数で、Google Storage イベントをデシリアライズするための便利なクラスです。

  4. これはクラウドイベントの関数で、パラメータとして io.cloudevents.CloudEvent を受け取り、その内部で getData() メソッドがイベントの内容(この場合はストレージイベント)を返します。

io.quarkus.funqy.gcp.functions.event パッケージ内で Google Cloud の共通イベントをデシリアライズするための便利なクラスを提供しています。これらのクラスは必須ではなく、任意のオブジェクトを使用することができます。

プロジェクトには複数の関数が含まれているので、どの関数をデプロイする必要があるかを application.properties 内の以下のプロパティーから指定する必要があります:

quarkus.funqy.export=helloPubSubWorld

アプリケーションのビルドと Google Cloud へのデプロイ

アプリケーションをビルドするには、 mvn clean package からアプリケーションをパッケージ化することができます。target/deployment リポジトリー内には、クラスとすべての依存関係が含まれた単一の JAR があります。

これで、 gcloud を使って関数を Google Cloud にデプロイすることができるようになります。 gcloud コマンドは、どのイベントが関数のトリガーになるかによって異なります。

ここではJava 17ランタイムを使用しますが、デプロイ・コマンドで --runtime=java17 の代わりに --runtime=java21 を使用することで、Java 21ランタイムに切り替えることができます。

初めて gcloud beta functions deploy を実行すると、以下のようなエラーメッセージが表示されます:

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 がまだ有効化されていないことを意味します。このエラーを解決するには、エラーに表示されている URL を開き指示に従った後、数分待ってからコマンドを再試行してください。

バックグラウンド関数 - PubSub

このコマンドを使用して、Google Cloud Functions にデプロイします。

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

Quarkus をブートストラップするのはこのクラスなので、エントリーポイントは常に io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction である必要があります。

--trigger-resource オプションは PubSub トピックの名前を定義し、--trigger-event google.pubsub.topic.publish オプションは、この関数がトピック内のすべてのメッセージ公開によってトリガーされることを定義します。

この関数にイベントをトリガーするには、 gcloud functions call コマンドを使用します。

gcloud functions call quarkus-example-funky-pubsub --data '{"data":"Pub/Sub"}'

--data '{"data":"Hello, Pub/Sub"}' オプションでは、メッセージが PubSub に送信されるようにできます。

バックグラウンド関数 - クラウドストレージ

関数をデプロイする前に、バケットを作成する必要があります。

gsutil mb gs://quarkus-hello

そして、このコマンドを使って Google Cloud Functions にデプロイします。

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

Quarkus をブートストラップするのはこのクラスなので、エントリーポイントは常に io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction である必要があります。

--trigger-resource オプションは Cloud Storage のバケット名を定義します。また、--trigger-event google.storage.object.finalize オプションはこのバケット内のすべての新規ファイルに対してこの関数がトリガーされることを定義します。

この関数にイベントをトリガーするには、 gcloud functions call コマンドを使用します。

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

--data '{"name":"test.txt"}' オプションでは、偽のファイル名を指定することができ、この名前に対して偽のクラウドストレージイベントが作成されます。

また、Web コンソールのコマンドラインを使用して、Cloud Storage にファイルを追加するだけでも簡単にできます。

Cloud Events Functions - クラウドストレージ

Cloud Events Function は、Cloud Functions gen 2のみの機能です。

関数をデプロイする前に、バケットを作成する必要があります。

gsutil mb gs://quarkus-hello

そして、このコマンドを使って Google Cloud Functions にデプロイします。

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

Quarkus をブートストラップするのはこのクラスなので、エントリーポイントは常に io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction である必要があります。

--trigger-bucket= オプションは、Cloud Storage バケットの名称を定義します。

イベントをトリガーするために、GCS example-cloud-event のバケットにファイルを送信することができます。

ローカルでの実行

関数をローカルで実行する最も簡単な方法は、Cloud Function invoker JAR を使用することです。

以下のコマンドで Maven 経由でダウンロードできます。

mvn dependency:copy \
    -Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.3.0' \
    -DoutputDirectory=.

invokerを使用する前に、まず、以下のように関数をビルドする必要があります。

コマンドラインインタフェース
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

その後、これは、ローカルで関数を起動するために使用することができます。このコマンドは、関数の種類とイベントの種類に依存します。

バックグラウンド関数 - PubSub

バックグラウンド関数の場合は、 io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction のターゲットクラスで invoker を起動します。

java -jar java-function-invoker-1.3.0.jar \
  --classpath target/funqy-google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction
--classpath パラメーターには、関数クラスと Quarkus 関連のすべてのクラスを含む、先の手順でパッケージ化された JAR を指定する必要があります。

起動後、HTTP 呼び出しにイベントを含むペイロードを付与することでバックグラウンド関数を呼び出すことができます。

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

これは、PubSub のバックグラウンド関数を PubSubMessage で呼び出します {"data":"hello”}

バックグラウンド関数 - クラウドストレージ

バックグラウンド関数の場合は、 io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction のターゲットクラスで invoker を起動します。

java -jar java-function-invoker-1.3.0.jar \
  --classpath target/funqy-google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction
--classpath パラメーターには、関数クラスと Quarkus 関連のすべてのクラスを含む、先の手順でパッケージ化された JAR を指定する必要があります。

起動後、HTTP 呼び出しにイベントを含むペイロードを付与することでバックグラウンド関数を呼び出すことができます。

curl localhost:8080 -d '{"data":{"name":"text"}}'

これは、Cloud Storage のイベント {"name":"file.txt"} (file.txt ファイル上のイベント) で PubSub のバックグラウンド関数を呼び出します。

Cloud Events Functions - クラウドストレージ

Cloud Events Function は、Cloud Functions gen 2のみの機能です。

cloud events functionsの場合は、 io.quarkus.funqy.gcp.functions.FunqyBackgroundFunction をターゲットクラスとして invoker を起動します。

java -jar java-function-invoker-1.3.0.jar \
  --classpath target/funqy-google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
  --target io.quarkus.funqy.gcp.functions.FunqyCloudEventsFunction
--classpath パラメーターには、関数クラスと Quarkus 関連のすべてのクラスを含む、先の手順でパッケージ化された JAR を指定する必要があります。

起動後、HTTP 呼び出しにイベントを含むペイロードを付与することでバックグラウンド関数を呼び出すことができます。

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 ファイルのイベントでcloud events functionが呼び出されます。

関数のテスト

Quarkusは、 quarkus-test-google-cloud-functions の依存関係を介してFunqy Google Cloud functions をテストするためのサポートを提供しています。

これを使うには、次のようなテストの依存関係を pom.xml に追加する必要があります。

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

このエクステンションは、 @QuarkusTest のテストケースに、テストケースの前に Cloud Function invoker を起動し、終了時に停止するためのアノテーションとして使用できる @WithFunction アノテーションを提供します。このアノテーションは、起動したい関数のタイプと、アプリケーション内に複数の関数がある場合は関数の名前をオプションで設定する必要があります。

デフォルトのQuarkusテストポート設定 ( quarkus.http.test-port ) が優先され、0に設定するとランダムなポートが関数呼び出し元に割り当てられます。

バックグラウンド関数 - PubSub

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.FUNQY_BACKGROUND) (2)
class GreetingFunctionsPubsubTest {
    @Test
    public void test() {
        given()
                .body("{\"data\":{\"data\":\"world\"}}") (3)
                .when()
                .post()
                .then()
                .statusCode(200);
    }
}
  1. これは標準的なQuarkusのテストであり、 @QuarkusTest によってアノテーションを付ける必要があります。

  2. @WithFunction(FunctionType.FUNQY_BACKGROUND) は、Funqyのバックグラウンド関数としてその関数を起動することを示します。同じアプリケーションに複数の関数が存在する場合、 functionName 属性を使用して、どの関数を起動させるかを示す必要があります。

  3. REST-assuredは関数のテストに使用され、 {"data":"world"} が、invokerを介して送信されます。

バックグラウンド関数 - クラウドストレージ

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.FUNQY_BACKGROUND) (2)
class GreetingFunctionsStorageTest {
    @Test
    public void test() {
        given()
                .body("{\"data\":{\"name\":\"hello.txt\"}}") (2)
                .when()
                .post()
                .then()
                .statusCode(200);
    }
}
  1. これは標準的なQuarkusのテストであり、 @QuarkusTest によってアノテーションを付ける必要があります。

  2. @WithFunction(FunctionType.FUNQY_BACKGROUND) は、Funqyのバックグラウンド関数としてその関数を起動することを示します。同じアプリケーションに複数の関数が存在する場合、 functionName 属性を使用して、どの関数を起動させるかを示す必要があります。

  3. REST-assuredは関数のテストに使用されます。 {"name":"hello.txt"} はinvokerを介して送られます。

Cloud Events Functions - クラウドストレージ

Cloud Events Function は、Cloud Functions gen 2のみの機能です。
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.FUNQY_CLOUD_EVENTS) (2)
class GreetingFunctionsCloudEventTest {
    @Test
    public void test() {
        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-id", "123451234512345") (4)
                .header("ce-specversion", "1.0")
                .header("ce-time", "2020-01-02T12:34:56.789Z")
                .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. これは標準的なQuarkusのテストであり、 @QuarkusTest によってアノテーションを付ける必要があります。

  2. @WithFunction(FunctionType.FUNQY_CLOUD_EVENTS) は、その関数を Funqy クラウドイベント関数として起動することを示します。同じアプリケーションに複数の機能が存在する場合、 functionName 属性を使用して、どの関数を起動させるかを示す必要があります。

  3. REST-assuredは関数のテストに使用され、ストレージイベントを記述したこのペイロードがinvokerを介して送信されます。

  4. クラウドイベントヘッダーは、HTTPヘッダで送信する必要があります。

次のステップ

Google Cloud Functionsの Jakarta REST、Servlet、Vert.xのサポートを探しているなら、 Google Cloud Functions HTTP binding が存在します。

関連コンテンツ