6.4. Quarkus 関数の開発

Quarkus 関数プロジェクトを作成 したら、指定のテンプレートを変更して、関数にビジネスロジックを追加できます。これには、関数呼び出しと返されるヘッダーとステータスコードの設定が含まれます。

6.4.1. 前提条件

6.4.2. Quarkus 関数テンプレートの構造

Knative (kn) CLI を使用して Quarkus 機能を作成する場合の、プロジェクトディレクトリーは通常の Maven プロジェクトに似ています。さらに、プロジェクトには、関数の設定に使用される func.yaml ファイルが含まれています。

http および event トリガー関数のテンプレート構造はいずれも同じです。

テンプレート構造

.
├── func.yaml 1
├── mvnw
├── mvnw.cmd
├── pom.xml 2
├── README.md
└── src
    ├── main
    │   ├── java
    │   │   └── functions
    │   │       ├── Function.java 3
    │   │       ├── Input.java
    │   │       └── Output.java
    │   └── resources
    │       └── application.properties
    └── test
        └── java
            └── functions 4
                ├── FunctionTest.java
                └── NativeFunctionIT.java

1
イメージ名とレジストリーを判断するために使用されます。
2
プロジェクトオブジェクトモデル (POM) ファイルには、依存関係に関する情報などのプロジェクト設定が含まれています。このファイルを変更して、別の依存関係を追加できます。

追加の依存関係の例

...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>3.8.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
...

依存関係は、最初のコンパイル時にダウンロードされます。

3
関数プロジェクトには、@Funq アノテーションが付けられた Java メソッドが含まれている必要があります。このメソッドは Function.java クラスに配置できます。
4
関数のローカルでのテストに使用できる単純なテストケースが含まれます。

6.4.3. Quarkus 関数の呼び出しについて

CloudEvents に応答する Quarkus プロジェクトや、簡単な HTTP 要求に応答する Quarkus プロジェクトを作成できます。Knative の CloudEvents は HTTP 経由で POST 要求として転送されるため、いずれかの関数タイプは受信 HTTP 要求をリッスンして応答します。

受信要求が受信されると、Quarkus 関数は使用可能なタイプのインスタンスと合わせて呼び出されます。

表6.1 関数呼び出しオプション

呼び出しメソッドインスタンスに含まれるデータタイプデータの例

HTTP POST 要求

要求のボディーに含まれる JSON オブジェクト

{ "customerId": "0123456", "productId": "6543210" }

HTTP GET 要求

クエリー文字列のデータ

?customerId=0123456&productId=6543210

CloudEvent

data プロパティーの JSON オブジェクト

{ "customerId": "0123456", "productId": "6543210" }

以下の例は、以前の表に記載されている customerId および productId の購入データを受信して処理する関数です。

Quarkus 関数の例

public class Functions {
    @Funq
    public void processPurchase(Purchase purchase) {
        // process the purchase
    }
}

購入データが含まれる、該当の Purchase JavaBean クラスは以下のようになります。

クラスの例

public class Purchase {
    private long customerId;
    private long productId;
    // getters and setters
}

6.4.3.1. StorageLocation の例

以下のコード例は、withBeanswithCloudEvent、および withBinary の 3 つの関数を定義します。

import io.quarkus.funqy.Funq;
import io.quarkus.funqy.knative.events.CloudEvent;

public class Input {
    private String message;

    // getters and setters
}

public class Output {
    private String message;

    // getters and setters
}

public class Functions {
    @Funq
    public Output withBeans(Input in) {
        // function body
    }

    @Funq
    public CloudEvent<Output> withCloudEvent(CloudEvent<Input> in) {
        // function body
    }

    @Funq
    public void withBinary(byte[] in) {
        // function body
    }
}

Functions クラスの withBeans 機能は、以下にで呼び出すことができます。

  • JSON ボディーが含まれる HTTP POST 要求:

    $ curl "http://localhost:8080/withBeans" -X POST \
        -H "Content-Type: application/json" \
        -d '{"message": "Hello there."}'
  • クエリーパラメーターが含まれる HTTP GET 要求:

    $ curl "http://localhost:8080/withBeans?message=Hello%20there." -X GET
  • バイナリーエンコーディングの CloudEvent オブジェクト:

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/json" \
      -H "Ce-SpecVersion: 1.0" \
      -H "Ce-Type: withBeans" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      -d '{"message": "Hello there."}'
  • 構造化されたエンコーディングでの CloudEvent オブジェクト:

    $ curl http://localhost:8080/ \
        -H "Content-Type: application/cloudevents+json" \
        -d '{ "data": {"message":"Hello there."},
              "datacontenttype": "application/json",
              "id": "42",
              "source": "curl",
              "type": "withBeans",
              "specversion": "1.0"}'

Functions クラスの withCloudEvent 機能は、withBeans 関数 と同様に CloudEvent オブジェクトを使用して呼び出すことができます。ただし、withBeans とは異なり、withCloudEvent はプレーン HTTP 要求で呼び出すことはできません。

Functions クラスの withBinary 関数は、以下にで呼び出すことができます。

  • バイナリーエンコーディングの CloudEvent オブジェクト:

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/octet-stream" \
      -H "Ce-SpecVersion: 1.0"\
      -H "Ce-Type: withBinary" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      --data-binary '@img.jpg'
  • 構造化されたエンコーディングでの CloudEvent オブジェクト:

    $ curl http://localhost:8080/ \
      -H "Content-Type: application/cloudevents+json" \
      -d "{ \"data_base64\": \"$(base64 --wrap=0 img.jpg)\",
            \"datacontenttype\": \"application/octet-stream\",
            \"id\": \"42\",
            \"source\": \"curl\",
            \"type\": \"withBinary\",
            \"specversion\": \"1.0\"}"

6.4.4. CloudEvent 属性

type または subject など CloudEvent の属性を読み取るか、書き込む必要がある場合は、CloudEvent<T> 汎用インターフェイスおよび CloudEventBuilder ビルダーを使用できます。<T> タイプパラメーターは使用可能なたタイプのいずれかでなければなりません。

以下の例では、CloudEventBuilder を使用して、購入処理の成功または失敗を返します。

public class Functions {

    private boolean _processPurchase(Purchase purchase) {
        // do stuff
    }

    public CloudEvent<Void> processPurchase(CloudEvent<Purchase> purchaseEvent) {
        System.out.println("subject is: " + purchaseEvent.subject());

        if (!_processPurchase(purchaseEvent.data())) {
            return CloudEventBuilder.create()
                    .type("purchase.error")
                    .build();
        }
        return CloudEventBuilder.create()
                .type("purchase.success")
                .build();
    }
}

6.4.5. Quarkus 関数の戻り値

関数は、許可された型のリストから任意の型のインスタンスを返すことができます。または、Uni<T> 型を返すこともできます。ここで、<T> 型パラメーターは、許可されている型の任意の型にすることができます。

Uni<T> タイプは、返されるオブジェクトが受信したオブジェクトと同じ形式でシリアライズされるため、関数が非同期 API を呼び出す場合に便利です。以下に例を示します。

  • 関数が HTTP 要求を受信すると、返されるオブジェクトが HTTP 応答のボディーに送信されます。
  • 関数がバイナリーエンコーディングで CloudEvent オブジェクトを受信する場合に、返されるオブジェクトはバイナリーエンコードされた CloudEvent オブジェクトの data プロパティーで送信されます。

以下の例は、購入リストを取得する関数を示しています。

コマンドの例

public class Functions {
    @Funq
    public List<Purchase> getPurchasesByName(String name) {
      // logic to retrieve purchases
    }
}

  • HTTP 要求経由でこの関数を呼び出すと、応答のボディーに購入された一覧が含まれる HTTP 応答が生成されます。
  • 受信 CloudEvent オブジェクト経由でこの関数を呼び出すと、data プロパティーの購入リストが含まれる CloudEvent 応答が生成されます。

6.4.5.1. 使用可能なタイプ

関数の入力と出力は、voidString、または byte[] 型のいずれかです。さらに、プリミティブ型とそのラッパー (intInteger など) にすることもできます。これらは、Javabean、マップ、リスト、配列、および特殊な CloudEvents<T> タイプの複合オブジェクトにすることもできます。

マップ、リスト、配列、CloudEvents<T> 型の <T> 型パラメーター、および Javabeans の属性は、ここにリストされている型のみにすることができます。

public class Functions {
    public List<Integer> getIds();
    public Purchase[] getPurchasesByName(String name);
    public String getNameById(int id);
    public Map<String,Integer> getNameIdMapping();
    public void processImage(byte[] img);
}

6.4.6. Quarkus 関数のテスト

Quarkus 関数は、コンピューターに対してローカルでテストできます。kn func create を使用して関数を作成するときに作成されるデフォルトプロジェクトには、基本的な Maven テストを含む src/test/ ディレクトリーがあります。これらのテストは、必要に応じて拡張できます。

前提条件

  • Quarkus 関数を作成している。
  • Knative (kn) CLI をインストールしている。

手順

  1. 関数のプロジェクトフォルダーに移動します。
  2. Maven テストを実行します。

    $ ./mvnw test

6.4.7. 次のステップ