Google Cloud FunctionsでJava11を使う

#はじめに

2020年5月にGoogle Cloud FunctionsでJava11がβ版ですがサポートされました。[こちら](https://cloud.google.com/blog/ja/products/application-development/introducing-java-11-on-google-cloud-functions)
当記事ではHTTPリクエストをトリガーに動くJava11アプリケーションを実際にデプロイをするまでを解説しています。

操作にはCloud Shellを使っています。

#Mavenの準備
まずはMavenに必要なpomファイルから用意します。Cloud Functionsで動かすのに必要なfunctions-framework-apiへの依存性と
ローカルで動かすために必要なプラグインの記述をします。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>example</groupId>
  <artifactId>functions-hello-world</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
  </properties>

  <dependencies>
    <!--  Functions Framework for Javaを依存関係に入れる -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.0.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <!-- Function Maven プラグインを入れ、ローカル実行できるようにする -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.9.3</version>
        <configuration>
          <functionTarget>CloudFunctionsForJava</functionTarget>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
```

#プログラム
次にプログラムの準備をします。HTTPリクエストをトリガーに動かす場合、functions-framework-apiの`com.google.cloud.functions.HttpFunction`
インターフェースを実装する必要があります。実装するメソッドは`service`メソッドのみで、このメソッドに処理したい内容を記載します。

当記事では、Qiita APIで私のユーザIDを叩いた時の結果を返すアプリケーションにしてあります。Java11っぽくするためになるべくローカル変数に型推論を使い、`java.net.http.HttpRequest`を使ってリクエストを飛ばしてあります。

`service`メソッドの引数である`com.google.cloud.functions.HttpRequest`にCloud Functionsを呼び出した時のリクエストパラメータ等が格納されます。同様にパラメータの`com.google.cloud.functions.HttpResponse`に値を書き出すことで、呼び出し元へレスポンスを返せます。


```java:CloudFunctionsForJava.java
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;

public class CloudFunctionsForJava implements HttpFunction {

  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException, InterruptedException {
    
    //Qiita APIを呼び出す準備
    var httpClient = HttpClient.newHttpClient();
    var requestFromGCF = java.net.http.HttpRequest
            .newBuilder(URI.create("https://qiita.com/api/v2/users/shuichiro"))
            .header("Content-Type", "application/json; charset=utf-8")
            .build();

    //呼び出しを実行
    var responseFromQiita
        = httpClient.send(requestFromGCF,java.net.http.HttpResponse.BodyHandlers.ofString());
    
    //Content-Typeの設定、日本語を表示するため
    response.setContentType("application/json; charset=utf-8");

    //Qiita APIから取得した値をCloud Functionを呼び出した相手へに
    var writer = response.getWriter();
    writer.write(responseFromQiita.body());
  }
}
```

作成したプログラムとpomの場所は以下の通りです。

```shell-session
$ tree
.
├── pom.xml
└── src
    └── main
        └── java
            └── CloudFunctionsForJava.java
```

#テスト

まずはコンパイルをします。

```shell-session
$ mvn compile
```
少し時間がかかりますが、「BUILD SUCCESS」と出れば成功です。
コンパイルが通ったら、ローカル環境で実行します。

```shell-session
$ mvn function:run
```

実行するとターミナルにスタートしたログが出るので別のターミナルを開いてcurlを実行します。

```shell-session
$ curl localhost:8080
{"description":　～～～略～～～～～ "website_url":""}

```
Qiita APIの結果が表示されているのが解ります。

#デプロイ
最後に実際にCloud Functionsにデプロイをします。以下のコマンドでデプロイを行いいます。トリガーをHTTPリクエストにし、認証無しで実行可能にしています。

```shell-session
$ gcloud functions deploy java-function --entry-point CloudFunctionsForJava --runtime java11 --trigger-http --memory 512MB --allow-unauthenticated
```

数分するとデプロイが終わるので、デプロイ時に表示されるURLを叩きます。

```shell-session
$ curl https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/java-function 
{"description":　～～～略～～～～～ "website_url":""}
```

Java11で作成したアプリケーションがCloud Functionsにデプロイできたのが確認できました。