.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする - AWS Lambda

.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする

AWS Lambda 関数のコードは、スクリプトまたはコンパイルされたプログラム、さらにそれらの依存関係で構成されます。デプロイパッケージを使用して、Lambda に関数コードをデプロイします。Lambda は、コンテナイメージと .zip ファイルアーカイブの 2 種類のデプロイパッケージをサポートしています。

このページでは、デプロイパッケージを .zip ファイルまたは Jar ファイルとして作成し、そのデプロイパッケージを使用して、AWS Lambda (AWS Command Line Interface) で関数コードを AWS CLI にデプロイする方法について説明します。

前提条件

AWS CLI は、コマンドラインシェルでコマンドを使用して AWS サービスとやり取りするためのオープンソースツールです。このセクションの手順を完了するには、以下が必要です。

ツールとライブラリ

Lambda には、Java 関数用に以下のライブラリが用意されています。

  • com.amazonaws:aws-lambda-java-core (必須) - ランタイムがハンドラに渡すハンドラメソッドインターフェイスとコンテキストオブジェクトを定義します。独自の入力タイプを定義する場合、これが唯一必要なライブラリです。

  • com.amazonaws:aws-lambda-java-events - Lambda 関数を呼び出すサービスからのイベントの入力タイプ。

  • com.amazonaws:aws-lambda-java-log4j2 - 現在の呼び出しのリクエスト ID を関数ログに追加するために使用できる Apache Log4j 2 のアペンダーライブラリ。

  • AWS SDK for Java 2.0 - Java プログラミング言語用の公式の AWS SDK。

これらのライブラリは Maven Central Repository から入手できます。以下のようにそれらのライブラリをビルド定義に追加します。

Gradle
dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.1' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1' }
Maven
<dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> <version>3.11.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-log4j2</artifactId> <version>1.5.1</version> </dependency> </dependencies>

デプロイパッケージを作成するには、関数コードと依存関係を 1 つの ZIP ファイルまたは Java Archive (JAR) ファイルにコンパイルします。Gradle の場合は、Zip ビルドタイプを使用します。Apache Maven の場合、Maven Shade プラグインを使用します。

注記

デプロイパッケージのサイズを小さく保つため、関数の依存関係をレイヤーにパッケージ化します。レイヤーを使用すると、依存関係を独立して管理し、複数の関数で使用できます。また、他のアカウントと共有することもできます。詳細については、「Lambda レイヤーの作成と共有」を参照してください。

デプロイパッケージをアップロードするには、Lambda コンソール、Lambda API、または AWS Serverless Application Model (AWS SAM) を使用します。

Lambda コンソールを使用してデプロイパッケージをアップロードするには

  1. Lambda コンソールの [Functions] (関数) ページを開きます。

  2. 関数を選択します。

  3. [Code source (コードソース)] で、[Upload from (アップロード元)] を選択します。

  4. デプロイパッケージをアップロードする

  5. [Save] を選択します。

Gradle を使用したデプロイパッケージのビルド

Zip ビルドタイプを使用して、関数のコードと依存関係を含むデプロイパッケージを作成します。

例 build.gradle - ビルドタスク

task buildZip(type: Zip) { from compileJava from processResources into('lib') { from configurations.runtimeClasspath } }

このビルド設定により、build/distributions ディレクトリにデプロイパッケージが作成されます。compileJava タスクは、関数のクラスをコンパイルします。processResources タスクが Java プロジェクトのリソースをターゲットディレクトリにコピーし、処理する可能性があります。その後 into('lib') ステートメントが、依存関係ライブラリをビルドのクラスパスから lib という名前のフォルダにコピーします。

例 build.gradle - 依存関係

dependencies { implementation platform('software.amazon.awssdk:bom:2.10.73') implementation 'software.amazon.awssdk:lambda' implementation 'com.amazonaws:aws-lambda-java-core:1.2.1' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.google.code.gson:gson:2.8.6' implementation 'org.apache.logging.log4j:log4j-api:2.17.1' implementation 'org.apache.logging.log4j:log4j-core:2.17.1' runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.1' runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.0' }

Lambda では、Unicode のアルファベット順で JAR ファイルをロードします。lib ディレクトリの複数の JAR ファイルに同じクラスが含まれている場合は、最初の JAR ファイルが使用されます。重複するクラスを識別するには、次のシェルスクリプトを使用します。

例 test-zip.sh

mkdir -p expanded unzip path/to/my/function.zip -d expanded find ./expanded/lib -name '*.jar' | xargs -n1 zipinfo -1 | grep '.*.class' | sort | uniq -c | sort

Maven を使用したデプロイパッケージのビルド

Maven でデプロイパッケージをビルドするには、Maven Shade プラグインを使用します。このプラグインは、コンパイルされた関数コードとそのすべての依存関係を含む JAR ファイルを作成します。

例 pom.xml - プラグイン設定

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>

デプロイパッケージをビルドするには、mvn package コマンドを使用します。

[INFO] Scanning for projects... [INFO] -----------------------< com.example:java-maven >----------------------- [INFO] Building java-maven-function 1.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- ... [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ java-maven --- [INFO] Building jar: target/java-maven-1.0-SNAPSHOT.jar [INFO] [INFO] --- maven-shade-plugin:3.2.2:shade (default) @ java-maven --- [INFO] Including com.amazonaws:aws-lambda-java-core:jar:1.2.1 in the shaded jar. [INFO] Including com.amazonaws:aws-lambda-java-events:jar:3.11.0 in the shaded jar. [INFO] Including joda-time:joda-time:jar:2.6 in the shaded jar. [INFO] Including com.google.code.gson:gson:jar:2.8.6 in the shaded jar. [INFO] Replacing original artifact with shaded artifact. [INFO] Replacing target/java-maven-1.0-SNAPSHOT.jar with target/java-maven-1.0-SNAPSHOT-shaded.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.321 s [INFO] Finished at: 2020-03-03T09:07:19Z [INFO] ------------------------------------------------------------------------

このコマンドは、target ディレクトリ内に JAR ファイルを生成します。

アペンダーライブラリ (aws-lambda-java-log4j2) を使用する場合は、Maven Shade プラグインのトランスフォーマーも設定する必要があります。トランスフォーマーライブラリは、アペンダーライブラリと Log4j の両方のキャッシュファイルのバージョンを組み合わせます。

例 pom.xml - Log4j 2 アペンダーを使用したプラグイン設定

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="com.github.edwgiz.maven_shade_plugin.log4j2_cache_transformer.PluginsCacheFileTransformer"> </transformer> </transformers> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>com.github.edwgiz</groupId> <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId> <version>2.13.0</version> </dependency> </dependencies> </plugin>

Lambda API を使用したデプロイパッケージのアップロード

関数のコードを AWS Command Line Interface (AWS CLI) または AWS SDK で更新するには、UpdateFunctionCode API オペレーションを使用します。AWS CLI では、update-function-code コマンドを使用します。以下のコマンドは、現在のディレクトリに my-function.zip という名前のデプロイパッケージをアップロードします。

aws lambda update-function-code --function-name my-function --zip-file fileb://my-function.zip

次のような出力が表示されます。

{ "FunctionName": "my-function", "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function", "Runtime": "java8", "Role": "arn:aws:iam::123456789012:role/lambda-role", "Handler": "example.Handler", "CodeSha256": "Qf0hMc1I2di6YFMi9aXm3JtGTmcDbjniEuiYonYptAk=", "Version": "$LATEST", "TracingConfig": { "Mode": "Active" }, "RevisionId": "983ed1e3-ca8e-434b-8dc1-7d72ebadd83d", ... }

デプロイパッケージが 50 MB よりも大きい場合、直接アップロードすることはできません。Amazon Simple Storage Service (Amazon S3) バケットにアップロードし、Lambda がオブジェクトを指定するようにします。以下のコマンド例は、デプロイパッケージを my-bucket という名前の S3 バケットにアップロードし、それに応じて関数のコードを更新します。

aws s3 cp my-function.zip s3://my-bucket

次のような出力が表示されます。

upload: my-function.zip to s3://my-bucket/my-function
aws lambda update-function-code --function-name my-function \ --s3-bucket my-bucket --s3-key my-function.zip

次のような出力が表示されます。

{ "FunctionName": "my-function", "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function", "Runtime": "java8", "Role": "arn:aws:iam::123456789012:role/lambda-role", "Handler": "example.Handler", "CodeSha256": "Qf0hMc1I2di6YFMi9aXm3JtGTmcDbjniEuiYonYptAk=", "Version": "$LATEST", "TracingConfig": { "Mode": "Active" }, "RevisionId": "983ed1e3-ca8e-434b-8dc1-7d72ebadd83d", ... }

この方法を使用して、最大 250 MB (解凍後サイズ) の関数パッケージをアップロードできます。

AWS SAM によるデプロイパッケージのアップロード

AWS SAM を使用して、関数コード、設定、依存関係のデプロイを自動化できます。AWS SAM は AWS CloudFormation の拡張であり、サーバーレスアプリケーションを定義するための構文が簡略化されています。以下のサンプルテンプレートは、Gradle 用の build/distributions ディレクトリにあるデプロイパッケージを使用する関数を定義します。

例 template.yml

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: An AWS Lambda application that calls the Lambda API. Resources: function: Type: AWS::Serverless::Function Properties: CodeUri: build/distributions/java-basic.zip Handler: example.Handler Runtime: java8 Description: Java function MemorySize: 512 Timeout: 10 # Function's execution role Policies: - AWSLambdaBasicExecutionRole - AWSLambda_ReadOnlyAccess - AWSXrayWriteOnlyAccess - AWSLambdaVPCAccessExecutionRole Tracing: Active

関数を作成するには、package コマンドと deploy コマンドを使用します。これらのコマンドは AWS CLI に合わせてカスタマイズされています。他のコマンドをラップして、デプロイパッケージを Amazon S3 にアップロードし、オブジェクト URI でテンプレートを書き換え、関数のコードを更新します。

以下のサンプルスクリプトは、Gradle ビルドを実行し、作成されたデプロイパッケージをアップロードします。また、初回実行時に AWS CloudFormation スタックを作成します。そのスタックがすでに存在する場合は更新します。

例 deploy.sh

#!/bin/bash set -eo pipefail aws cloudformation package --template-file template.yml --s3-bucket MY_BUCKET --output-template-file out.yml aws cloudformation deploy --template-file out.yml --stack-name java-basic --capabilities CAPABILITY_NAMED_IAM

完全な使用例については、以下のサンプルアプリケーションを参照してください。

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

  • java-basic - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。

  • java-events - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの aws-lambda-java-events ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。

  • s3-java - Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。

  • API ゲートウェイを使用して Lambda 関数を呼び出す - 従業員情報を含む Amazon DynamoDB テーブルをスキャンする Java 関数。次に、Amazon Simple Notification Service を使用して、仕事の記念日を祝うテキストメッセージを従業員に送信します。この例では、API ゲートウェイを使用して関数を呼び出します。