#chiroito ’s blog

Java を中心とした趣味の技術について

ファンクションの入出力を JSON 形式にする @ Fn Project

Fn Project で作成したファンクションの入出力を JSON 形式にしてみましょう。

以下のチュートリアルをベースにしています。
tutorials/JavaFDKIntroduction at master · fnproject/tutorials · GitHub

ファンクションの修正

fn initでテンプレートとして作成されるファンクションを使って、入出力を JSON 形式に変更してみましょう。テンプレートで作成されるクラスは以下のとおりです。handleRequestメソッドがファンクションとして実行されます。

既存

package com.example.fn;

public class HelloFunction {

    public String handleRequest(String input) {
        String name = (input == null || input.isEmpty()) ? "world"  : input;

        return "Hello, " + name + "!";
    }

}

入出力を文字列から JSON 形式にするには、引数や戻り値の型を String クラスから任意のクラスへ変更します。チュートリアルでは、入力用の Input クラスと出力用の Result クラスを定義し、handleRequest メソッドの引数として Input クラスを、戻り値として Result クラスを指定してます。

JSON 対応後

package com.example.fn;

public class HelloFunction {

    public static class Input {
        public String name;
    }

    public static class Result {
        public String salutation;
    }

    public Result handleRequest(Input input) {
        Result result = new Result();
        result.salutation = "Hello " + input.name;
        return result;
    }

}

テストケースの修正

ファンクションを変更したのでテストケースも修正しましょう。

既存

package com.example.fn;

import com.fnproject.fn.testing.*;
import org.junit.*;

import static org.junit.Assert.*;

public class HelloFunctionTest {

    @Rule
    public final FnTestingRule testing = FnTestingRule.createDefault();

    @Test
    public void shouldReturnGreeting() {
        testing.givenEvent().enqueue();
        testing.thenRun(HelloFunction.class, "handleRequest");

        FnResult result = testing.getOnlyResult();
        assertEquals("Hello, world!", result.getBodyAsString());
    }

}

空のリクエストボディで関数を実行した結果が"Hello, world!"という文字列かどうかを試す試験でした。入出力の JSON 可に伴い、リクエスト用の JSON を用いて関数を実行した結果が検証用の JSON と同一かを試験します。

リクエスト用 JSON

{
    "name": "Bob"
}

検証用 JSON

{
    "salutation": "Hello Bob"
}

テストコードではこれらのJSON をエスケープした文字列を使って試験します。リクエストボディに"{\"name\":\"Bob\"}"を指定して暗数を実行した結果が"{\"salutation\":\"Hello Bob\"}"であることを検証します。

JSON対応後

package com.example.fn;

import com.fnproject.fn.testing.*;
import org.junit.*;

import static org.junit.Assert.*;

public class HelloFunctionTest {

    @Rule
    public final FnTestingRule testing = FnTestingRule.createDefault();

    @Test
    public void shouldReturnGreeting(){
        testing.givenEvent().withBody("{\"name\":\"Bob\"}").enqueue();
        testing.thenRun(HelloFunction.class,"handleRequest");

        FnResult result = testing.getOnlyResult();
        assertEquals("{\"salutation\":\"Hello Bob\"}", result.getBodyAsString());
    }
}

デプロイと実行

現在の位置とファイルの確認

> pwd
/home/chiroito/javafn

> ls
func.yaml  pom.xml  src

ファンクションを Fn Server へデプロイします。

> fn deploy --app myapp

デプロイが成功したら、ファンクションを実行してみましょう。現段階(0.4.9)ではfn callではリクエストボディを含めることには対応していないようですので、curlを使用してファンクションを実行します。 本環境では Fn Server は localhost の 8080 番ポートで動いています。

>curl --data '{"name": "Bob"}' http://localhost:8080/r/javafn/myapp
{"salutation":"Hello Bob"}