APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【Azure】AzureFunctionsアプリのJava構文を読む

はじめに

こんにちは。クラウド事業部の菅家です。
techblog.ap-com.co.jp 前回、公式チュートリアルに従ってIntelliJからFunctionsのアプリを作成し、デプロイをしてみたところ。
やはり構造などがわからないと、なかなかプログラムを自力で書くのは難しいもので、
書き方の通例を学んでFunctionsの基礎を学んでいきたいと思います。

目次

関数の定義方法

@FunctionName("Azureで表示する関数名")
public HttpResponseMessage run(...)

@FunctionNameアノテーションを特定のメソッドの上に記載することで、関数が定義できます。
Azure上での関数名はアノテーション側で定義するため、アノテーションを付けるJavaメソッド側の名前は任意となります。
デプロイ後、Functionsアプリケーションの関数一覧に表示されます。

Functions
 |ー関数1
 |ー関数2
 |ー関数3
 |ー関数4
 |ー関数5
...

このようにFunctions1つに対して関数は複数定義できるようです。

Functionsってどこから開始するの?

Javaといえばpublic static void main(String[] args)ですが、Functionsはイベントをトリガーとしてプログラムを実行します。
○○をクリックしたなど、デスクトップアプリやWebアプリなどに感覚としては近そうです。

トリガーの種類としては以下が参考になりそうです。
learn.microsoft.com
com.microsoft.azure.functions.annotation.*パッケージ内の「○○Trigger」が該当します。

ざっと日本語訳したものまとめ

  • @HttpTrigger :HttpTrigger アノテーションは、関数が配置されている HTTP エンドポイントへの呼び出しによってトリガーされる Azure 関数に適用されます。
  • @TimerTrigger:タイマー トリガーを使用すると、関数を実行するタイミングを指定する CRON 式を指定して、スケジュールに従って関数を実行できます。
  • @BlobTrigger:これを、BLOB から値を取得するパラメータに配置し、BLOB がアップロードされたときにメソッドが実行されるようにします。
  • @QueueTrigger:これを、ストレージ キューから値を取得するパラメーターに配置し、新しい項目がプッシュされたときにメソッドが実行されるようにします。
  • @EventHubTrigger:これを、イベント ハブから値が取得されるパラメーターに配置し、新しいイベントが到着したときにメソッドが実行されるようにします。
  • @ServiceBusQueueTrigger:これを、Service Bus キューから値を取得するパラメーターに配置し、新しい項目がプッシュされたときにメソッドが実行されるようにします。
  • @ServiceBusTopicTrigger:これを、Service Bus トピックから値を取得するパラメーターに配置し、新しいアイテムが公開されたときにメソッドが実行されるようにします。
  • @CosmosDBTrigger:これを、CosmosDB から値を取得するパラメータに配置し、CosmosDB データが変更されたときにメソッドが実行されるようにします。
  • @EventGridTrigger:これを、EventGrid から値が取得されるパラメータに配置し、イベントが到着したときにメソッドが実行されるようにします。

learn.microsoft.com

バインディングについて

また、バインディングという概念もある模様。
遅延バインディングなどは聞いた記憶がありますが、正直何だったか思い出せないので復習します。

以下の記事によると

learn.microsoft.com

バインドでは、データを関数に渡し、関数からデータを返す方法が提供されます。

とのこと。
それから、関数定義において「String req」がバインド引数であるところ。

public class Function {
    public String echo(@HttpTrigger(name = "req", 
      methods = {HttpMethod.POST},  authLevel = AuthorizationLevel.ANONYMOUS) 
        String req, ExecutionContext context) {
        return String.format(req);
    }
}

このことから関数において入出力データの受け渡しを担うのがバインドというところになります。
トリガーによって何をバインドするかは変わるため、使い方に関しては各Triggerアノテーションを見るのが良さそうです。
@HttpTriggerはわかりやすい感じがします。「HttpRequestMessage<Optional> request」なのでなにかしらのリクエストの内容が見られそうです。

アノテーションによってバインドを自分でカスタマイズできるし、各トリガーごとの入出力についても記載があります。
learn.microsoft.com

Functionsメソッドの引数について

わかりやすそうかつ、ほかサービスとの連携がないものとして「@HttpTrigger」「@TimerTrigger」がサンプルとしていいかなと思い、リファレンスを読んでみます。


リファレンス
@HttpTrigger
learn.microsoft.com

@FunctionName("hello")
  public HttpResponseMessage<String> helloFunction(
    @HttpTrigger(name = "req",
                  methods = {HttpMethod.GET},
                  authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request
  ) {
     ....
  }


@TimerTrigger*
learn.microsoft.com

@FunctionName("keepAlive")
 public void keepAlive(
    @TimerTrigger(name = "keepAliveTrigger", schedule = "0 */5 * * * *") String timerInfo,
     ExecutionContext context
 ) {
     // timeInfo is a JSON string, you can deserialize it to an object using your favorite JSON library
     context.getLogger().info("Timer is triggered: " + timerInfo);
 }


完全にAzureに関係のないJava余談ですが私は自作アノテーションを作ったことがないので、インターフェースなんだとすごく興味津々でリファレンスを眺めております。
「implements java.lang.annotation.Annotation」アノテーションInterfaceを実装するんですね。

引数①
定義の作りとしては、まず引数に「@HttpTrigger」などのトリガーがあるというところ。トリガーのnameは関数単位で一意であれば良さそうです。
function.jsonに定義されているとか。そういえばAzureのUI上から関数の画面を開いたときに「function.json」を見るみたいなところがありましたので、デプロイされてから定義ファイルに落とし込まれるようですね。
トリガーの設定と考えると良さそうです。

引数②
「HttpRequestMessage<Optional> request」「String timerInfo」これがバインディング関連。
HttpRequestMessageに関しては、書いても書かなくてもいいOptionalですね。
「String timerInfo」は関数がトリガーされた際のスケジュール情報が入っているようです。

引数③
最後にfinal ExecutionContext context。
正直一番気になってました。

リファレンス
learn.microsoft.com

The execution context enables interaction with the Azure Functions execution environment. 実行コンテキストにより、Azure Functions 実行環境との対話が可能になります。

Javaのインターフェース=規格やシナリオ、外部・他機能との接続部品やデータ受け渡し部品のイメージが私の中でとても強いんですけども、なんとなくこのイメージに合いそうです。
finalは値の変更防止だそうで、情報を自分で書くわけでもこの内容を送るわけでも無いのでつけるのが無難な気がします。

getLogger() Returns the built-in logger, which is integrated with the logging functionality provided in the Azure Functions portal, as well as in Azure Application Insights.

これ、Application Insightsでログを出すためのメソッドっぽいですね。
関数名や呼び出しIDの取得、ロガーの取得。トレースコンテキスト(エラーログなどの意図的に出してない自動生成ログみたいなもの)の取得などの機能があります。
引数①②はトリガーとのやり取りでしたが、Azure Functionsそのものとのやり取りをするのがこのインターフェースだと理解しました。

Functionsアプリケーションの構造について

調べてみましたが、JavaアプリケーションにおけるFunctions用のフレームワークやベストプラクティスのような構造は見つかりませんでした。
src/main配下(今回はGradleのため)は、一般的なmodelやutilなどよく見るパッケージ構成で良さそうです。
Lombokなどと組み合わせるのもできるので、getter/setter/コンストラクタ定義を省きたいであったり、DBを使うなどで他フレームワークとうまく共存するのはありですね。

おわりに

今度はここからApplication Insightsとの連携をし、実際にログを出していこうと思います。
外部アクセスや他リソースの動きに依存しない@TimerTriggerで試すのが良さそうです。
  →トリガーを使って実行、何かしらの実行結果を得る
  →Application Insightsに文字を表示する
こちらに手を付けていければと思います。

お知らせ

私達クラウド事業部はクラウド技術を活用したSI/SESのご支援をしております。
https://www.ap-com.co.jp/service/utilize-aws/

また、一緒に働いていただける仲間も募集中です! ご興味持っていただけましたらぜひお声がけください。 hrmos.co

本記事の投稿者: s-sugaya
AWSをメインにインフラ系のご支援を担当しています。