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

Google Cloud Functions (サーバーレス)

quarkus-google-cloud-functions エクステンションを使用すると、Quarkusを使用してGoogle Cloud Functionsを構築することができます。関数では、CDIやSpringからのインジェクションアノテーションや、必要に応じて他のQuarkusの機能を使用できます。

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

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

For a full list of possible statuses, check our FAQ entry.

前提条件

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

ソリューション

このガイドでは、サンプルプロジェクトを生成し、Quarkusで HttpFunctionBackgroundFunctionRawBackgroundFunction を実装する方法を説明します。ビルド後は、プロジェクトをGoogle Cloudにデプロイすることができます。

これらの手順を順にすべて実行しない場合、完成したサンプルを以下で確認できます。

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

このガイドでのソリューションは google-cloud-functions-quickstart ディレクトリ にあります。

デプロイ用のMavenプロジェクトを作成する

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

CLI
quarkus create app org.acme:google-cloud-functions \
    --extension=google-cloud-functions \
    --no-code
cd google-cloud-functions

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

Quarkus CLIのインストール方法については、Quarkus CLIガイドをご参照ください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.11.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=google-cloud-functions \
    -Dextensions="google-cloud-functions" \
    -DnoCode
cd google-cloud-functions

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

Now, let’s remove the index.html from resources/META-INF/resources or it will be picked up instead of your Function.

Googleクラウドにログインする

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

gcloud auth login

Cloud Functions の関数を作成する

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 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 use gcloud beta command and add the --gen2 parameter.

Cloud Functions の関数を選択する

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.

しかし、同じコードを利用するCloud Functionの関数クラスが複数あるような場合に、個別maven モジュールを作成することは手間となります。このQuarkusエクステンションを使うと、複数のCloud Function関数を一つのプロジェクトにバンドルし、設定や環境変数を使ってデプロイしたい関数を選択することができます。

Cloud Functions の関数に名前を設定するには、以下の設定プロパティーを使用します。

quarkus.google-cloud-functions.function=test

quarkus.google-cloud-functions.function プロパティーは、デプロイする関数をQuarkusに伝えます。これは環境変数でオーバーライドすることもできます。

Cloud Functions の関数となるクラスの CDI 名は、 quarkus.google-cloud-functions.function プロパティー内で指定された値と一致している必要があります。これは @Named アノテーションを使用して行う必要があります。

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

HttpFunction

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.io.Writer;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.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 @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。
2 関数はCDI Beanでなければなりません。
3 Google Cloud Functionで実行するためには、実行する対象のクラスは`com.google.cloud.functions.HttpFunction`インターフェースをImplementsする必要があります .
4 インジェクションはCloud Function関数クラスの中で動作します。
5 これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。

BackgroundFunction

この BackgroundFunction はストレージイベントによってトリガーされる以外にも、Google Cloud でサポートされているトリガーイベントを使用できます。

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.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 @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。
2 関数はCDI Beanでなければなりません。
3 Google Cloud Functionで実行するためには、実行する対象のクラスは com.google.cloud.functions.BackgroundFunction インターフェースをImplementsする必要があります。
4 インジェクションはCloud Function関数クラスの中で動作します。
5 これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。
6 これはトリガーのイベントデータがデシリアライズされるクラスです。

RawBackgroundFunction

この RawBackgroundFunction は PubSub イベントでトリガーされる以外にも、Google Cloud でサポートされているトリガーイベントを使用することができます。

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.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 @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。
2 関数はCDI Beanでなければなりません。
3 Google Cloud Functionで実行するためには、実行する対象のクラスは com.google.cloud.functions.RawBackgroundFunction インターフェースをImplementsする必要があります。.
4 インジェクションはCloud Function関数クラスの中で動作します。
5 これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。

The CloudEventsFunction

CloudEventsFunction is a feature of Cloud Functions gen 2 only.

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

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.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 @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。
2 関数はCDI Beanでなければなりません。
3 This is a regular Google Cloud Function implementation, so it needs to implement com.google.cloud.functions.CloudEventsFunction.
4 インジェクションはCloud 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.

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

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

CLI
quarkus build
Maven
./mvnw clean package
Gradle
./gradlew build

前のコマンドの結果、 target/deployment リポジトリ内に単一の JAR ファイルが生成されます。このJARファイルにはプロジェクト内のクラスと、依存関係のクラスが含まれています

これで gcloud beta functions deploy コマンドを使って Google Cloud に関数をデプロイすることができるようになります。

このコマンドを初めて起動したときには、以下のようなエラーメッセージが表示されることがあります。

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を開き指示に従った後、数分待ってからコマンドを再試行してください。

HttpFunction

これは HttpFunction を Google Cloud にデプロイするためのコマンドの例です。

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

エントリーポイントは常に io.quarkus.gcp.functions.QuarkusHttpFunction に設定する必要があります。このクラスはQuarkusとCloud Functionsを統合するクラスです。

You can also use the new Java 17 runtime by using --runtime=java17 in the gcloud command line.

このコマンドは、作成したCloud Functions 関数をトリガーするための httpsTrigger.url を出力します。

BackgroundFunction

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

gsutil mb gs://quarkus-hello

これは BackgroundFunction を Google Cloud にデプロイするためのコマンドの例です。この関数は Storage イベントによってトリガーされるため、 --trigger-event google.storage.object.finalize--trigger-resource パラメーターに先の手順で作成したバケットの名前を指定する必要があります。

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

エントリーポイントは常に io.quarkus.gcp.functions.QuarkusBackgroundFunction に設定する必要があります。このクラスはQuarkusとCloud Functionsを統合するクラスです。

You can also use the new Java 17 runtime by using --runtime=java17 in the gcloud command line.

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形式のフォーマットです。

RawBackgroundFunction

これは RawBackgroundFunction を Google Cloud にデプロイするコマンドの例です。この関数は PubSub イベントによってトリガーされるので、 --trigger-event google.pubsub.topic.publish--trigger-resource パラメーターに、先の手順で作成したトピックの名前を指定する必要があります。

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

エントリーポイントは常に io.quarkus.gcp.functions.QuarkusBackgroundFunction に設定する必要があります。このクラスはQuarkusとCloud Functionsを統合するクラスです。

You can also use the new Java 17 runtime by using --runtime=java17 in the gcloud command line.

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 is a feature of Cloud Functions gen 2 only.

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 beta functions deploy quarkus-example-cloud-event --gen2 \
  --entry-point=io.quarkus.gcp.functions.QuarkusCloudEventsFunction \
  --runtime=java11 --trigger-bucket=example-cloud-event --source=target/deployment

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

You can also use the new Java 17 runtime by using --runtime=java17 in the gcloud command line.

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

ローカルでのテスト

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

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

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

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

CLI
quarkus build
Maven
./mvnw clean package
Gradle
./gradlew build

HttpFunction

HttpFunction をテストするために、以下のコマンドを使用しローカルで関数を起動することができます。

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

エンドポイントは http://localhost:8080 で利用できます。

BackgroundFunction

BackgroundFunction関数の場合は、 io.quarkus.gcp.functions.BackgroundFunction のターゲットクラスでinvokerを起動します。

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

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

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

このコマンドにより、イベント {"name":"hello.txt"} でBackgroundFunctionを呼び出します。これは、`hello.txt`をCloud Storageに保存した際のイベントをテストするのと同じです。

RawBackgroundFunction

BackgroundFunction関数の場合は、 io.quarkus.gcp.functions.BackgroundFunction のターゲットクラスでinvokerを起動します。

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

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

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

このコマンドは、PubSubのBackgroundFunctionを次のPubSubMessageで呼び出します {"greeting":"world"} .

The CloudEventsFunction

CloudEventsFunction is a feature of Cloud Function gen 2 only.

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

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

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"
      }'

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