Java の AWS Lambda 関数ハンドラー - AWS Lambda

Java の AWS Lambda 関数ハンドラー

Lambda 関数のハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。ハンドラーによってレスポンスが終了するか、レスポンスが返ったら、別のイベントを処理できるようになります。

以下の例では、Handler という名前のクラスで handleRequest という名前のハンドラーメソッドを定義しています。ハンドラーメソッドは、イベントとコンテキストオブジェクトを入力として受け取り、文字列を返します。

Handler.java

package example; import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.RequestHandler import com.amazonaws.services.lambda.runtime.LambdaLogger ... // Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String>{ Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public String handleRequest(Map<String,String> event, Context context) { LambdaLogger logger = context.getLogger(); String response = new String("200 OK"); // log execution details logger.log("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv())); logger.log("CONTEXT: " + gson.toJson(context)); // process event logger.log("EVENT: " + gson.toJson(event)); logger.log("EVENT TYPE: " + event.getClass().toString()); return response; } }

Lambda ランタイムは、イベントを JSON 形式の文字列として受け取り、オブジェクトに変換します。また、イベントオブジェクトを、呼び出しと関数の詳細を提供するコンテキストオブジェクトと共に、関数ハンドラーに渡します。関数の設定でハンドラーパラメータを指定することで、呼び出すメソッドをランタイムに指示します。

ハンドラーの形式

  • package.Class::method – 完全形式。例: example.Handler::handleRequest

  • package.Classハンドラーインターフェイスを実装する関数の省略形式。例: example.Handler

ハンドラーメソッドの外側に初期化コードを追加して、複数の呼び出し間でリソースを再利用できます。ランタイムがハンドラーをロードすると、静的コードとクラスコンストラクタが実行されます。初期化中に作成されたリソースは、呼び出し間でメモリ内に留まり、ハンドラーによって何千回も再利用できます。

以下の例では、関数が最初のイベントを処理するときに、ロガー、シリアライザー、AWS SDK クライアントが作成されます。同じ関数インスタンスによって処理される後続のイベントは、それらのリソースがすでに存在するため、はるかに高速です。

Handler.java – 初期化コード

// Handler value: example.Handler public class Handler implements RequestHandler<SQSEvent, String>{ private static final Logger logger = LoggerFactory.getLogger(Handler.class); private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private static final LambdaAsyncClient lambdaClient = LambdaAsyncClient.create(); ... @Override public String handleRequest(SQSEvent event, Context context) { String response = new String(); // call Lambda API logger.info("Getting account settings"); CompletableFuture<GetAccountSettingsResponse> accountSettings = lambdaClient.getAccountSettings(GetAccountSettingsRequest.builder().build()); // log execution details logger.info("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv())); ...

このガイドの GitHub リポジトリには、さまざまなハンドラータイプを示す、簡単にデプロイできるサンプルアプリケーションが用意されています。詳細については、このトピックの最後を参照してください。

入力タイプと出力タイプの選択

イベントがマッピングするオブジェクトのタイプは、ハンドラーメソッドの署名で指定します。上記の例では、Java ランタイムはイベントを、Map<String,String> インターフェイスを実装するタイプに逆シリアル化します。文字列から文字列へのマッピングは、以下のような階層なしのイベントで機能します。

Event.json – 気象データ

{ "temperatureK": 281, "windKmh": -3, "humidityPct": 0.55, "pressureHPa": 1020 }

ただし、各フィールドの値は文字列または数値であることが必要です。イベント内のフィールドにオブジェクトが値として含まれている場合、ランタイムはそれを逆シリアル化できず、エラーを返します。

関数が処理するイベントデータに使用する入力タイプを選択します。基本タイプ、汎用タイプ、または良定義タイプを使用できます。

入力タイプ

  • IntegerLongDouble など– イベントは、追加の形式のない数値です (3.5 など)。ランタイムは、値を指定されたタイプのオブジェクトに変換します。

  • String – イベントは、引用符ありの JSON 文字列です ("My string." など)。ランタイムは、引用符なしの値を String オブジェクトに変換します。

  • TypeMap<String,Type> など– イベントは JSON オブジェクトです。ランタイムは、それを指定されたタイプまたはインターフェイスのオブジェクトに逆シリアル化します。

  • List<Integer>List<String>List<Object> など– イベントは JSON 配列です。ランタイムは、それを指定されたタイプまたはインターフェイスのオブジェクトに逆シリアル化します。

  • InputStream – イベントは任意の JSON タイプです。ランタイムは、ドキュメントのバイトストリームを変更せずにハンドラーに渡します。入力を逆シリアル化し、出力を出力ストリームに書き込みます。

  • ライブラリタイプ – AWS のサービスによって送信されるイベントの場合、aws-lambda-java-events ライブラリのタイプを使用します。

独自の入力タイプを定義する場合、そのタイプは、逆シリアライズかつ変更可能な Plain Old Java Object (POJO) であり、デフォルトのコンストラクタと、イベントの各フィールドのプロパティが必要です。プロパティにマッピングされないイベントのキー、およびイベントに含まれていないプロパティは、エラーなしでドロップされます。

出力タイプはオブジェクトまたは void です。ランタイムは、戻り値をテキストにシリアル化します。出力が、フィールドを含むオブジェクトの場合、ランタイムは、それを JSON ドキュメントにシリアル化します。出力が、プリミティブ値をラップするタイプの場合、ランタイムは、その値のテキスト表現を返します。

ハンドラーのインターフェイス

aws-lambda-java-core ライブラリは、ハンドラーメソッドの 2 つのインターフェイスを定義します。用意されているインターフェイスを使用して、ハンドラー設定をシンプルにし、コンパイル時にハンドラーメソッドの署名を検証します。

RequestHandler インターフェイスは、入力タイプと出力タイプの 2 つのパラメータを受け取る汎用タイプです。どちらのタイプもオブジェクトであることが必要です。このインターフェイスを使用すると、Java ランタイムはイベントを入力タイプのオブジェクトに逆シリアル化し、出力をテキストにシリアル化します。組み込みのシリアル化が入力タイプと出力タイプで機能する場合は、このインターフェイスを使用します。

Handler.java – ハンドラーインターフェイス

// Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String>{ @Override public String handleRequest(Map<String,String> event, Context context)

独自のシリアル化を使用するには、RequestStreamHandler インターフェイスを実装します。このインターフェイスでは、Lambda はハンドラーに入力ストリームと出力ストリームを渡します。ハンドラーは、入力ストリームからバイトを読み取り、出力ストリームに書き込み、void を返します。

以下の例では、バッファされたリーダーとライターのタイプを使用して、入力ストリームと出力ストリームを処理しています。シリアル化と逆シリアル化には Gson ライブラリを使用します。

ハンドラーストリーム

import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.RequestStreamHandler import com.amazonaws.services.lambda.runtime.LambdaLogger ... // Handler value: example.HandlerStream public class HandlerStream implements RequestStreamHandler { Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { LambdaLogger logger = context.getLogger(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("US-ASCII"))); PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, Charset.forName("US-ASCII")))); try { HashMap event = gson.fromJson(reader, HashMap.class); logger.log("STREAM TYPE: " + inputStream.getClass().toString()); logger.log("EVENT TYPE: " + event.getClass().toString()); writer.write(gson.toJson(event)); if (writer.checkError()) { logger.log("WARNING: Writer encountered an error."); } } catch (IllegalStateException | JsonSyntaxException exception) { logger.log(exception.toString()); } finally { reader.close(); writer.close(); } } }

サンプルハンドラーコード

このガイドの GitHub リポジトリには、さまざまなハンドラータイプとインターフェイスの使用方法を示すサンプルアプリケーションが含まれています。各サンプルアプリケーションには、簡易のデプロイとクリーンアップ用のスクリプト、AWS SAM テンプレート、サポートリソースが含まれています。

Java のサンプル Lambda アプリケーション

  • blank-java – Lambda の Java ライブラリ、ロギング、環境変数、レイヤー、AWS X-Ray トレース、単体テスト、および AWS SDK の使用を示す Java 関数。

  • java-basic – 単体テストと変数ログ記録設定を使用する、最小限の Java 関数。

  • java-events – Amazon API Gateway など、依存関係として AWS SDK を必要としないイベントタイプで、aws-lambda-java-events ライブラリを使用する最小限の Java 関数。

  • java-events-v1sdk – Amazon Simple Storage Service や Amazon DynamoDB、Amazon Kinesis など、依存関係として AWS SDK を必要とするイベントタイプで、aws-lambda-java-events ライブラリを使用する Java 関数。

  • s3-java – Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) によりアップロード済みイメージファイルからサムネイルを作成する、Java 関数。

blank-java および s3-java アプリケーションは、AWS のサービスのイベントを入力として受け取り、文字列を返します。java-basic アプリケーションには数タイプのハンドラーが含まれています。

さまざまなハンドラータイプをテストするには、AWS SAM テンプレートのハンドラー値を変更するだけです。詳細な手順については、サンプルアプリケーションの readme ファイルを参照してください。