

# Java による Lambda 関数の構築
<a name="lambda-java"></a>

Java コードを AWS Lambda で実行できます。Lambda は、コードを実行してイベントを処理する Java 用の[ランタイム](lambda-runtimes.md)を提供します。コードは、管理している AWS Identity and Access Management (IAM) ロールからの AWS 認証情報を含む Amazon Linux 環境で実行されます。

Lambda は、以下の Java ランタイムをサポートしています。<a name="java-runtimes"></a>


| 名前 | 識別子 | オペレーティングシステム | 廃止日 | 関数の作成をブロックする | 関数の更新をブロックする | 
| --- | --- | --- | --- | --- | --- | 
|  Java 25  |  `java25`  |  Amazon Linux 2023  |   2029 年 6 月 30 日   |   2029 年 7 月 31 日   |   2029 年 8 月 31 日   | 
|  Java 21  |  `java21`  |  Amazon Linux 2023  |   2029 年 6 月 30 日   |   2029 年 7 月 31 日   |   2029 年 8 月 31 日   | 
|  Java 17  |  `java17`  |  Amazon Linux 2  |   2027 年 6 月 30 日   |   2027 年 7 月 31 日   |   2027 年 8 月 31 日   | 
|  Java 11  |  `java11`  |  Amazon Linux 2  |   2027 年 6 月 30 日   |   2027 年 7 月 31 日   |   2027 年 8 月 31 日   | 
|  Java 8  |  `java8.al2`  |  Amazon Linux 2  |   2027 年 6 月 30 日   |   2027 年 7 月 31 日   |   2027 年 8 月 31 日   | 

AWS は Java 関数用に以下のライブラリを提供しています。これらのライブラリは [Maven Central Repository](https://search.maven.org/search?q=g:com.amazonaws) から入手できます。
+ [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) (必須) － ランタイムがハンドラに渡すハンドラメソッドインターフェイスとコンテキストオブジェクトを定義します。独自の入力タイプを定義する場合、これが唯一必要なライブラリです。
+ [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events) － Lambda 関数を呼び出すサービスからのイベントの入力タイプ。
+ [com.amazonaws:aws-lambda-java-log4j2](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2) － 現在の呼び出しのリクエスト ID を[関数ログ](java-logging.md)に追加するために使用できる Apache Log4j 2 のアペンダーライブラリ。
+ [AWS SDK for Java 2.0](https://github.com/aws/aws-sdk-java-v2) - Java プログラミング言語用の公式の AWS SDK。

以下のように、これらのライブラリをビルド定義に追加します。

------
#### [ Gradle ]

```
dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
    implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
    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.2</version>
    </dependency>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-events</artifactId>
      <version>3.11.1</version>
    </dependency>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-log4j2</artifactId>
      <version>1.5.1</version>
    </dependency>
  </dependencies>
```

------

**重要**  
プライベートフィールド、メソッド、クラスなどの JDK API のプライベートコンポーネントは使用しないでください。非公開 API コンポーネントは更新時に変更または削除され、アプリケーションが動作しなくなる可能性があります。

**Java 関数を作成するには**

1. [Lambda コンソール](https://console.aws.amazon.com/lambda)を開きます。

1. [**Create function**] (関数の作成) をクリックします。

1. 以下の設定を行います。
   + **[関数名]**: 関数名を入力します。
   + **[Runtime]**: **[Java 25]** を選択します。

1. [**関数の作成**] を選択してください。

コンソールは、`Hello` という名前のハンドラクラスを持つ Lambda 関数を作成します。Java はコンパイルされた言語であるため、Lambda コンソールでソースコードを表示または編集することはできませんが、設定の変更、呼び出し、トリガーの設定を行うことができます。

**注記**  
ローカル環境でアプリケーション開発を開始するには、このガイドの GitHub リポジトリで利用可能な[サンプルアプリケーション](java-samples.md)の 1 つをデプロイします。

`Hello` クラスには、イベントオブジェクトおよびコンテキストオブジェクトを取得する `handleRequest` という名前の関数が含まれています。これは、関数が呼び出されるときに Lambda が呼び出す[ハンドラー関数](java-handler.md)です。Java 関数のランタイムは Lambda から呼び出しイベントを取得し、ハンドラに渡します。関数設定で、ハンドラ値は `example.Hello::handleRequest` です。

関数のコードを更新するには、デプロイパッケージを作成します。このパッケージは、関数コードを含む .zip ファイルアーカイブです。関数の開発が進むにつれて、ソース管理への関数コードの保存、ライブラリの追加、デプロイの自動化を行うことがあります。まず、[デプロイパッケージを作成](java-package.md)し、コマンドラインでコードを更新します。

関数のランタイムによって、呼び出しイベントに加えて、コンテキストオブジェクトがハンドラに渡されます。[コンテキストオブジェクト](java-context.md)には、呼び出し、関数、および実行環境に関する追加情報が含まれます。詳細情報は、環境変数から入手できます。

Lambda 関数には CloudWatch Logs ロググループが付属しています。関数のランタイムは、各呼び出しに関する詳細を CloudWatch Logs に送信します。これは呼び出し時に、任意の[関数が出力するログ](java-logging.md)を中継します。関数がエラーを返す場合、Lambda はエラー形式を整え、それを呼び出し元に返します。

**Topics**
+ [Java の Lambda 関数ハンドラーの定義](java-handler.md)
+ [.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする](java-package.md)
+ [コンテナイメージを使用した Java Lambda 関数のデプロイ](java-image.md)
+ [Java Lambda 関数のレイヤーを操作する](java-layers.md)
+ [Lambda Java 関数のシリアル化をカスタマイズ](java-custom-serialization.md)
+ [Lambda 関数の Java ランタイムの起動時の動作をカスタマイズする](java-customization.md)
+ [Lambda コンテキストオブジェクトを使用して Java 関数の情報を取得する](java-context.md)
+ [Java Lambda 関数のログ記録とモニタリング](java-logging.md)
+ [AWS Lambda での Java コードの作成](java-tracing.md)
+ [AWS Lambda の Java サンプルアプリケーション](java-samples.md)

# Java の Lambda 関数ハンドラーの定義
<a name="java-handler"></a>

Lambda 関数*ハンドラー*は、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

このページでは、プロジェクトのセットアップオプション、命名規則、ベストプラクティスなど、Java で Lambda 関数ハンドラーを使用する方法について説明します。このページには、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon Simple Storage Service (Amazon S3) バケットに配置する Java Lambda 関数の例も含まれています。関数を書き込んだ後にデプロイする方法については、「[.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする](java-package.md)」または「[コンテナイメージを使用した Java Lambda 関数のデプロイ](java-image.md)」を参照してください。

**Topics**
+ [Java ハンドラープロジェクトのセットアップ](#java-handler-setup)
+ [Java Lambda 関数のコードの例](#java-example-code)
+ [Java ハンドラーの有効なクラス定義](#java-handler-signatures)
+ [ハンドラーの命名規則](#java-example-naming)
+ [入力イベントオブジェクトの定義とアクセス](#java-handler-input)
+ [Lambda コンテキストオブジェクトへのアクセスと使用](#java-example-context)
+ [ハンドラーでの AWS SDK for Java v2 の使用](#java-example-sdk-usage)
+ [環境変数にアクセスする](#java-example-envvars)
+ [グローバルな状態を使用する](#java-handler-state)
+ [Java Lambda 関数のコードのベストプラクティス](#java-best-practices)

## Java ハンドラープロジェクトのセットアップ
<a name="java-handler-setup"></a>

Java で Lambda 関数を使用する場合、このプロセスにはコードの記述、コンパイル、コンパイルされたアーティファクトの Lambda へのデプロイが含まれます。Java Lambda プロジェクトはさまざまな方法で初期化できます。例えば、[Lambda 関数の Maven Archetype](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda)、AWS SAM CLI [sam init コマンド](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-init.html)、または IntelliJ IDEA や Visual Studio Code といった任意の IDE での標準 Java プロジェクト設定などのツールを使用できます。または、必要なファイル構造を手動で作成することもできます。

一般的な Java Lambda 関数プロジェクトは、次の一般的な構造に従います。

```
/project-root
    └ src
        └ main
            └ java
                └ example
                    └ OrderHandler.java (contains main handler)
                    └ <other_supporting_classes>
     └ build.gradle OR pom.xml
```

Maven または Gradle を使用してプロジェクトを構築し、依存関係を管理できます。

関数のメインハンドラーロジックは、`src/main/java/example` ディレクトリの Java ファイルにあります。このページの例では、このファイルに `OrderHandler.java` という名前を付けます。このファイルとは別に、必要に応じて追加の Java クラスを含めることができます。関数を Lambda にデプロイする際は、呼び出し中に Lambda が呼び出すメインハンドラーメソッドを含む Java クラスを必ず指定してください。

## Java Lambda 関数のコードの例
<a name="java-example-code"></a>

以下の Java 21 Lambda 関数コードの例では、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon S3 バケットに配置します。

**Example `OrderHandler.java` Lambda 関数**  

```
package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.nio.charset.StandardCharsets;

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {

    private static final S3Client S3_CLIENT = S3Client.builder().build();

    /**
     * Record to model the input event.
     */
    public record Order(String orderId, double amount, String item) {}

    @Override
    public String handleRequest(Order event, Context context) {
        try {
            // Access environment variables
            String bucketName = System.getenv("RECEIPT_BUCKET");
            if (bucketName == null || bucketName.isEmpty()) {
                throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
            }

            // Create the receipt content and key destination
            String receiptContent = String.format("OrderID: %s\nAmount: $%.2f\nItem: %s",
                    event.orderId(), event.amount(), event.item());
            String key = "receipts/" + event.orderId() + ".txt";

            // Upload the receipt to S3
            uploadReceiptToS3(bucketName, key, receiptContent);

            context.getLogger().log("Successfully processed order " + event.orderId() +
                    " and stored receipt in S3 bucket " + bucketName);
            return "Success";

        } catch (Exception e) {
            context.getLogger().log("Failed to process order: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private void uploadReceiptToS3(String bucketName, String key, String receiptContent) {
        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();

            // Convert the receipt content to bytes and upload to S3
            S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
        } catch (S3Exception e) {
            throw new RuntimeException("Failed to upload receipt to S3: " + e.awsErrorDetails().errorMessage(), e);
        }
    }
}
```

この `OrderHandler.java` ファイルには以下のコードのセクションが含まれます:
+ `package example`: Java では、これは任意のものにできますが、プロジェクトのディレクトリ構造と一致する必要があります。ここでは、ディレクトリ構造が `src/main/java/example` であるため、`package example` を使用します。
+ `import` ステートメント: これらを使用して、Lambda 関数に必要な Java クラスをインポートします。
+ `public class OrderHandler ...`: これは Java クラスを定義します。また、[有効なクラス定義](#java-handler-signatures)である必要があります。
+ `private static final S3Client S3_CLIENT ...`: これにより、クラスのメソッドの外部で S3 クライアントが初期化されます。これにより、Lambda は[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)中にこのコードを実行します。
+ `public record Order ...`: このカスタム Java [レコード](https://openjdk.org/jeps/395)で予想される入力イベントの形状を定義します。
+ `public String handleRequest(Order event, Context context)`: これは**メインハンドラーメソッド**で、メインアプリケーションロジックが含まれています。
+ `private void uploadReceiptToS3(...) {}`: これは、メイン `handleRequest` ハンドラーメソッドによって参照されるヘルパーメソッドです。

### build.gradle および pom.xml ファイルのサンプル
<a name="java-gradle-maven-example"></a>

次の `build.gradle` または `pom.xml` ファイルは、この関数に付随します。

------
#### [ build.gradle ]

```
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
    implementation 'software.amazon.awssdk:s3:2.28.29'
    implementation 'org.slf4j:slf4j-nop:2.0.16'
}

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

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

build.dependsOn buildZip
```

------
#### [ 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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-java</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>example-java-function</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
            <version>2.28.29</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>2.0.16</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.4.1</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*</exclude>
                                <exclude>META-INF/versions/**</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>21</release>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

------

この関数が正しく機能するには、[実行ロール](lambda-intro-execution-role.md)で `s3:PutObject` アクションを許可する必要があります。また、必ず `RECEIPT_BUCKET` 環境変数を定義してください。呼び出しに成功したら、Amazon S3 バケットに受信ファイルが含まれているはずです。

**注記**  
この関数がタイムアウトすることなく正常に実行されるには、追加の構成設定が必要になる場合があります。メモリを 256 MB、タイムアウトを 10 秒に設定することをお勧めします。[コールドスタート](lambda-runtime-environment.md#cold-start-latency)により、最初の呼び出しにさらに時間がかかる場合があります。実行環境が再利用されるため、それ以降の呼び出しはより高速に実行されます。

## Java ハンドラーの有効なクラス定義
<a name="java-handler-signatures"></a>

クラスを定義するために、[aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) ライブラリは、ハンドラーメソッドの 2 つのインターフェイスを定義します。用意されているインターフェイスを使用して、ハンドラー設定をシンプルにし、コンパイル時にメソッドシグネチャを検証します。
+ [com.amazonaws.services.lambda.runtime.RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java)
+ [com.amazonaws.services.lambda.runtime.RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java)

`RequestHandler` インターフェイスは、入力タイプと出力タイプの 2 つのパラメータを受け取る汎用タイプです。どちらのタイプもオブジェクトであることが必要です。この例では、`OrderHandler` クラスは `RequestHandler<OrderHandler.Order, String>` を実装します。入力タイプはクラス内で定義する `Order` レコードで、出力タイプは `String` です。

```
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {
    ...
}
```

このインターフェイスを使用すると、Java ランタイムはイベントを入力タイプのオブジェクトに逆シリアル化し、出力をテキストにシリアル化します。組み込みのシリアル化が入力タイプと出力タイプで機能する場合は、このインターフェイスを使用します。

独自のシリアル化を使用するために、`RequestStreamHandler` インターフェイスを実装できます。このインターフェイスでは、Lambda はハンドラーに入力ストリームと出力ストリームを渡します。ハンドラーは、入力ストリームからバイトを読み取り、出力ストリームに書き込み、void を返します。Java 21 ランタイムを使用したこの例については、「[HandlerStream.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/main/java/example/HandlerStream.java)」を参照してください。

Java 関数で基本型と汎用型 (`String`、`Integer`、`List` または `Map`) のみを使用している場合は、インターフェイスを実装する必要はありません。例えば、関数が `Map<String, String>` 入力を受け取り、`String` を返す場合、クラス定義とハンドラー署名は次のようになります。

```
public class ExampleHandler {
    public String handleRequest(Map<String, String> input, Context context) {
        ...
    }
}
```

さらに、インターフェイスを実装しない場合、[コンテキスト](java-context.md)オブジェクトはオプションです。例えば、クラス定義とハンドラー署名は次のようになります。

```
public class NoContextHandler {
   public String handleRequest(Map<String, String> input) {
        ...
   }
}
```

## ハンドラーの命名規則
<a name="java-example-naming"></a>

Java の Lambda 関数では、`RequestHandler` または `RequestStreamHandler` インターフェイスを実装する場合、メインハンドラーメソッドの名前は `handleRequest` である必要があります。また、`handleRequest` メソッドの上に `@Override` タグを含めます。関数を Lambda にデプロイするときは、関数の設定でメインハンドラーを次の形式で指定します。
+ *<package>*.*<Class>* – 例: `example.OrderHandler`。

`RequestHandler` または `RequestStreamHandler` インターフェイスを実装しない Java の Lambda 関数の場合、ハンドラーには任意の名前を使用できます。関数を Lambda にデプロイするときは、関数の設定でメインハンドラーを次の形式で指定します。
+ *<package>*.*<Class>*::*<handler\$1method\$1name>* – 例: `example.Handler::mainHandler`。

## 入力イベントオブジェクトの定義とアクセス
<a name="java-handler-input"></a>

JSON は Lambda 関数の最も一般的な標準入力形式です。この例では、関数は以下のような入力を想定しています:

```
{
    "orderId": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

Java 17 以降で Lambda 関数を使用する場合、予想される入力イベントの形状を Java レコードとして定義できます。この例では、`Order` オブジェクトを表すレコードを `OrderHandler` クラス内で定義します。

```
public record Order(String orderId, double amount, String item) {}
```

このレコードは、予想される入力形状と一致します。レコードを定義したら、レコード定義に準拠する JSON 入力を取り込むハンドラー署名を記述できます。Java ランタイムは、この JSON を Java オブジェクトに自動的に逆シリアル化します。その後、オブジェクトのフィールドにアクセスできます。例えば、`event.orderId` は元の入力から `orderId` の値を取得します。

**注記**  
Java レコードは、Java 17 ランタイム以降の機能です。すべての Java ランタイムで、クラスを使用してイベントデータを表すことができます。このような場合は、[jackson](https://github.com/FasterXML/jackson) などのライブラリを使用して JSON 入力を逆シリアル化できます。

### その他の入力イベントタイプ
<a name="java-input-event-types"></a>

Java の Lambda 関数には、多くの入力イベントが考えられます。
+ `Integer``Long` 、`Double`、など － イベントは、追加の形式のない数値です (`3.5` など)。Java ランタイムは、値を指定されたタイプのオブジェクトに変換します。
+ `String` － イベントは、引用符を含む JSON 文字列です ( など)`“My string”`。ランタイムは、値を引用符なしの `String` オブジェクトに変換します。
+ `List<Integer>``List<String>` 、`List<Object>`、など － イベントは JSON 配列です。ランタイムは、それを指定されたタイプまたはインターフェイスのオブジェクトに逆シリアル化します。
+ `InputStream` － イベントは任意の JSON タイプです。ランタイムは、ドキュメントのバイトストリームを変更せずにハンドラーに渡します。入力を逆シリアル化し、出力を出力ストリームに書き込みます。
+ ライブラリタイプ － 他の AWS サービスによって送信されるイベントの場合、[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events) ライブラリのタイプを使用します。例えば、Lambda 関数が Amazon Simple Queue Service (SQS) によって呼び出された場合、`SQSEvent` オブジェクトを入力として使用します。

## Lambda コンテキストオブジェクトへのアクセスと使用
<a name="java-example-context"></a>

Lambda [コンテキストオブジェクト](java-context.md)には、呼び出し、関数、および実行環境に関する情報が含まれます。この例では、コンテキストオブジェクトは `com.amazonaws.services.lambda.runtime.Context` 型で、メインハンドラー関数の 2 番目の引数です。

```
public String handleRequest(Order event, Context context) {
    ...
}
```

クラスで [RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java) インターフェイスまたは [RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java) インターフェイスを実装する場合、コンテキストオブジェクトは必須引数です。それ以外の場合、コンテキストオブジェクトはオプションです。有効な受理されたハンドラー署名の詳細については、「[Java ハンドラーの有効なクラス定義](#java-handler-signatures)」を参照してください。

AWS SDK を使用して他のサービスを呼び出す場合、コンテキストオブジェクトはいくつかの重要な領域で必要です。例えば、Amazon CloudWatch の関数ログを生成するには、`context.getLogger()` メソッドを使用してログ記録用の `LambdaLogger` オブジェクトを取得できます。この例では、何らかの理由で処理が失敗した場合、ロガーを使用してエラーメッセージをログに記録できます。

```
context.getLogger().log("Failed to process order: " + e.getMessage());
```

ログ記録以外では、関数のモニタリングにコンテキストオブジェクトを使用することもできます。コンテキストオブジェクトの詳細については、「[Lambda コンテキストオブジェクトを使用して Java 関数の情報を取得する](java-context.md)」を参照してください。

## ハンドラーでの AWS SDK for Java v2 の使用
<a name="java-example-sdk-usage"></a>

多くの場合、Lambda 関数を使用して、他の AWS リソースとやり取りしたり、更新したりします。これらのリソースとインターフェイスする最も簡単な方法は、AWS SDK for Java v2 を使用することです。

**注記**  
AWS SDK for Java (v1) はメンテナンスモードであり、2025 年 12 月 31 日にサポートが終了する予定です。今後は AWS SDK for Java v2 のみを使用することをお勧めします。

SDK 依存関係を関数に追加するには、Gradle の場合は `build.gradle` に、Maven の場合は `pom.xml` ファイルに追加します。関数に必要なライブラリのみを追加することをお勧めします。前のコード例では、`software.amazon.awssdk.services.s3` ライブラリを使用しました。Gradle では、`build.gradle` の依存関係セクションに次の行を追加することで、この依存関係を追加できます。

```
implementation 'software.amazon.awssdk:s3:2.28.29'
```

Maven で、`pom.xml` の `<dependencies>` セクションに次の行を追加します。

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
        <version>2.28.29</version>
    </dependency>
```

**注記**  
これは SDK の最新バージョンではない場合があります。アプリケーションに適したバージョンの SDK を選択します。

次に、依存関係を Java クラスに直接インポートします。

```
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
```

次に、コード例は次のように Amazon S3 クライアントを初期化します。

```
private static final S3Client S3_CLIENT = S3Client.builder().build();
```

この例では、関数を呼び出すたびに Amazon S3 クライアントを初期化する必要がないように、メインハンドラー関数の外で Amazon S3 クライアントを初期化しました。SDK クライアントを初期化したら、SDK クライアントを使用して他の AWS サービスとやり取りできます。サンプルコードは、以下のように Amazon S3 `PutObject` API を呼び出します。

```
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build();

// Convert the receipt content to bytes and upload to S3
S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
```

## 環境変数にアクセスする
<a name="java-example-envvars"></a>

ハンドラーコードでは、`System.getenv()` メソッドを使用して任意の[環境変数](configuration-envvars.md)を参照できます。この例では、以下のコード行を使用して、定義された `RECEIPT_BUCKET` 環境変数を参照します:

```
String bucketName = System.getenv("RECEIPT_BUCKET");
if (bucketName == null || bucketName.isEmpty()) {
    throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
}
```

## グローバルな状態を使用する
<a name="java-handler-state"></a>

Lambda は、関数を初めて呼び出す前の[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)で静的コードとクラスコンストラクターを実行します。初期化中に作成されたリソースは呼び出し間でメモリに保持されるため、関数を呼び出すたびにリソースを作成する必要がなくなります。

コード例では、S3 クライアント初期化コードはメインハンドラーメソッドの外にあります。ランタイムは、関数が最初のイベントを処理する前にクライアントを初期化し、クライアントはすべての呼び出しで再利用できます。

## Java Lambda 関数のコードのベストプラクティス
<a name="java-best-practices"></a>

Lambda 関数をビルドするときは、次のリストのガイドラインに従って、コーディングのベストプラクティスを実行してください。
+ **Lambda ハンドラーをコアロジックから分離します。**これにより、関数の単体テストが実行しやすくなります。
+ **関数のデプロイパッケージ内で依存関係を制御します。**AWS Lambda 実行環境には多数のライブラリが含まれています。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda はこれらのライブラリを定期的に更新します。この更新により、Lambda 関数の動作が微妙に変化する場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。
+ **依存関係の複雑さを最小限に抑えます。**フレームワークを単純化して、[実行環境](lambda-runtime-environment.md)起動時のロードを高速化します。たとえば、[Spring Framework](https://github.com/spring-projects/spring-framework) などの複雑なフレームワークよりも、[Dagger](https://google.github.io/dagger/) や [Guice](https://github.com/google/guice) などの単純な Java 依存関係インジェクション (IoC) フレームワークを使用します。
+ **デプロイパッケージをランタイムに必要な最小限のサイズにします。**これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。Java で記述された関数の場合は、デプロイパッケージの一部として AWS SDK ライブラリ全体をアップロードしないようにしてください。代わりに、SDK のコンポーネントを必要に応じて選別するモジュール (DynamoDB、Amazon S3 SDK モジュール、[Lambda コアライブラリ](https://github.com/aws/aws-lambda-java-libs)など) を使用します。

**実行環境の再利用を活用して関数のパフォーマンスを向上させます。**関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを `/tmp` ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。

呼び出し間でデータが漏れるのを防ぐため、実行環境を使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラー内のメモリに保存できない変更可能な状態に依存している場合は、ユーザーごとに個別の関数または個別のバージョンの関数を作成することを検討してください。

**keep-alive ディレクティブを使用して永続的な接続を維持します。**Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「[Node.js で Keep-alive を使用して接続を再利用する](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)」を参照してください。

**[環境変数](configuration-envvars.md)を使用して、オペレーショナルパラメータを関数に渡します。**たとえば、Amazon S3 バケットに書き込む場合、書き込み先のバケット名はハードコーディングせずに、環境変数として設定します。

Lambda 関数では、**再帰呼び出しを使用しないでください**。関数が自身を呼び出すこともあれば、新たに開始されたプロセスで関数が再度呼び出される可能性もあります。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。意図しない呼び出しがいくつも見つかった場合は、すぐに関数の予約済同時実行数を `0` に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。

Lambda 関数コードで**文書化されていない非公開の API を使用しないでください**。AWS Lambda マネージドランタイムでは、Lambda が Lambda の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「[API リファレンス](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)」を参照してください。

**冪等性コードを記述します。**関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「[Lambda 関数を冪等にするにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)」を参照してください。
+ **Java DNS キャッシュを使用しない** Lambda 関数は、既に DNS レスポンスをキャッシュしています。別の DNS キャッシュを使用すると、接続タイムアウトが発生する可能性があります。

  `java.util.logging.Logger` クラスは JVM DNS キャッシュを間接的に有効にできます。デフォルト設定を上書きするには、 を初期化する前に [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) を 0 に設定します`logger`。例:

  ```
  public class MyHandler {
    // first set TTL property
    static{
     java.security.Security.setProperty("networkaddress.cache.ttl" , "0");
    }
   // then instantiate logger
    var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class);
  }
  ```
+ Java で記述された**デプロイパッケージを Lambda で解凍する所要時間を短縮します**。そのために、依存する `.jar` ファイルを別個の /lib ディレクトリにファイルします。これで関数のすべてのコードを多数の `.class` ファイルと一緒に単一の Jar に収納するよりも高速化されます。手順については、「[.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする](java-package.md)」を参照してください。

# .zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする
<a name="java-package"></a>

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

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

**重要**  
Java 25 では Ahead-of-Time (AOT) キャッシュのサポートが導入されました。Lambda がマネージドランタイムを更新するとキャッシュが予期しない動作を引き起こす可能性があるため、関数を .zip または JAR ファイルアーカイブとしてデプロイするときは AOT キャッシュを使用しないことを強くお勧めします。詳細については、「[Ahead-of-Time (AOT) キャッシュと CDS キャッシュ](java-customization.md#aot-cds-caches)」を参照してください。

**Topics**
+ [前提条件](#java-package-prereqs)
+ [ツールとライブラリ](#java-package-libraries)
+ [Gradle を使用したデプロイパッケージのビルド](#java-package-gradle)
+ [依存関係へのレイヤーの使用](#java-package-layers)
+ [Maven を使用したデプロイパッケージのビルド](#java-package-maven)
+ [Lambda コンソールでデプロイパッケージのアップロード](#java-package-console)
+ [AWS CLI を使用したデプロイパッケージのアップロード](#java-package-cli)
+ [AWS SAM によるデプロイパッケージのアップロード](#java-package-cloudformation)

## 前提条件
<a name="java-package-prereqs"></a>

AWS CLI は、コマンドラインシェルでコマンドを使用して AWS サービスとやり取りするためのオープンソースツールです。このセクションの手順を完了するには、[AWS CLIバージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) が必要です。

## ツールとライブラリ
<a name="java-package-libraries"></a>

AWS は Java 関数用に以下のライブラリを提供しています。これらのライブラリは [Maven Central Repository](https://search.maven.org/search?q=g:com.amazonaws) から入手できます。
+ [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) (必須) － ランタイムがハンドラに渡すハンドラメソッドインターフェイスとコンテキストオブジェクトを定義します。独自の入力タイプを定義する場合、これが唯一必要なライブラリです。
+ [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events) － Lambda 関数を呼び出すサービスからのイベントの入力タイプ。
+ [com.amazonaws:aws-lambda-java-log4j2](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2) － 現在の呼び出しのリクエスト ID を[関数ログ](java-logging.md)に追加するために使用できる Apache Log4j 2 のアペンダーライブラリ。
+ [AWS SDK for Java 2.0](https://github.com/aws/aws-sdk-java-v2) - Java プログラミング言語用の公式の AWS SDK。

以下のように、これらのライブラリをビルド定義に追加します。

------
#### [ Gradle ]

```
dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
    implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
    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.2</version>
    </dependency>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-events</artifactId>
      <version>3.11.1</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` ビルドタイプを使用](#java-package-gradle)します。Apache Maven の場合、[Maven Shade プラグインを使用](#java-package-maven)します。デプロイパッケージをアップロードするには、Lambda コンソール、Lambda API、AWS Serverless Application Model (AWS SAM) を使用します。

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

## Gradle を使用したデプロイパッケージのビルド
<a name="java-package-gradle"></a>

関数のコードおよび Gradle の依存関係を含むデプロイパッケージを作成するには、`Zip` 構築タイプを使用します。「[完全なサンプル build.gradle ファイル](https://github.com/awsdocs/aws-lambda-developer-guide/blob/main/sample-apps/s3-java/build.gradle)」の例を示します。

**Example build.gradle － ビルドタスク**  

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

このビルド設定により、`build/distributions` ディレクトリにデプロイパッケージが作成されます。`into('lib')` ステートメント内で、`jar` タスクはメインクラスを含む jar アーカイブを `lib` という名前のフォルダにアセンブルします。さらに、`configurations.runtimeClassPath` タスクが、依存関係ライブラリをビルドのクラスパスから同じ `lib` フォルダにコピーします。

**Example build.gradle － 依存関係**  

```
dependencies {
    ...
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
    implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
    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'
    ...
}
```

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

**Example 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
```

## 依存関係へのレイヤーの使用
<a name="java-package-layers"></a>

関数の依存関係をレイヤーにパッケージ化して、デプロイパッケージを小さく保ち、依存関係を個別に管理することができます。詳細については、「[Java Lambda 関数のレイヤーを操作する](java-layers.md)」を参照してください。

## Maven を使用したデプロイパッケージのビルド
<a name="java-package-maven"></a>

Maven でデプロイパッケージをビルドするには、[Maven Shade プラグイン](https://maven.apache.org/plugins/maven-shade-plugin/)を使用します。このプラグインは、コンパイルされた関数コードとそのすべての依存関係を含む JAR ファイルを作成します。

**Example 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.2 in the shaded jar.
[INFO] Including com.amazonaws:aws-lambda-java-events:jar:3.11.1 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 ファイルを生成します。

**注記**  
「[マルチリリース JAR (MRJAR)](https://openjdk.org/jeps/238)」を使用している場合、を `lib` ディレクトリに MRJAR (つまり、Maven Shade プラグインによって生成されるシェーディング JAR) 含め、デプロイパッケージを Lambda にアップロードする前に圧縮する必要があります。そうしないと、Lambda が JAR ファイルを適切に解凍せず、`MANIFEST.MF` ファイルが無視される可能性があります。

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

**Example 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 コンソールでデプロイパッケージのアップロード
<a name="java-package-console"></a>

 新しい関数を作成するには、まずコンソールで関数を作成し、次に .zip または JAR ファイルをアップロードする必要があります。既存の関数を更新するには、その関数のページを開き、同じ手順に従って更新した .zip または JAR ファイルを追加します。

 デプロイパッケージファイルが 50 MB 未満の場合は、ローカルマシンから直接ファイルをアップロードして関数を作成または更新できます。50 MB を超える .zip または JAR ファイルの場合は、まず Amazon S3 バケットにパッケージをアップロードする必要があります。AWS マネジメントコンソール を使用して Amazon S3 バケットにファイルをアップロードする手順については、「[Amazon S3 の開始方法](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html)」を参照してください。AWS CLI を使用してファイルをアップロードするには、「*AWS CLI ユーザーガイド*」の「[オブジェクトの移動](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)」を参照してください。

**注記**  
既存の関数の[デプロイパッケージタイプ](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-PackageType) (.zip またはコンテナイメージ) を変更することはできません。例えば、既存のコンテナイメージ関数を、.zip ファイルアーカイブを使用するように変換することはできません。この場合は、新しい関数を作成する必要があります。

**新しい関数を作成するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、**[関数の作成]** を選択します。

1. **[一から作成]** を選択します。

1. **[基本的な情報]** で、以下を行います。

   1. **[関数名]** に、関数名を入力します。

   1. **[ランタイム]** で、使用するランタイムを選択します。

   1. (オプション) **[アーキテクチャ]**で、関数の命令セットアーキテクチャを選択します。デフォルトのアーキテクチャは x86\$164 です。関数用の .zip デプロイパッケージと選択した命令セットのアーキテクチャに互換性があることを確認してください。

1. (オプション) **[アクセス権限]** で、**[デフォルトの実行ロールの変更]** を展開します。新しい **[実行ロール]** を作成することも、既存のロールを使用することもできます。

1. **[関数の作成]**を選択します。Lambda は、選択したランタイムを使用して基本的な「Hello world」関数を作成します。

**ローカルマシンから .zip または JAR アーカイブをアップロードするには (コンソール)**

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) で、.zip または JAR ファイルをアップロードする関数を選択します。

1. **[コード]** タブを選択します。

1. **[コードソース]** ペインで、**[アップロード]** をクリックします。

1. **.zip または.jar ファイル**を選択します。

1. .zip または JAR ファイルをアップロードするには、次の操作を行います。

   1. **[アップロード]** をクリックし、ファイルセレクターで .zip または JAR ファイルを選択します。

   1. **[開く]** をクリックします。

   1. **[保存]** をクリックします。

**Amazon S3 バケットから .zip または JAR アーカイブをアップロードするには (コンソール)**

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) で、新しい .zip または JAR ファイルをアップロードする関数を選択します。

1. **[コード]** タブを選択します。

1. **[コードソース]** ペインで、**[アップロード元]** をクリックします。

1. **[Amazon S3 ロケーション]** を選択します。

1. .zip ファイルの Amazon S3 リンク URL を貼り付けて、**[保存]** をクリックします。

## AWS CLI を使用したデプロイパッケージのアップロード
<a name="java-package-cli"></a>

 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) を使用して新しい関数を作成したり、.zip または JAR ファイルを使用して既存の関数を更新したりできます。[create-function](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) コマンドと [update-function-code](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) を使用して、.zip または JAR パッケージをデプロイします。ファイルが 50 MB 未満の場合は、ローカルビルドマシン上のファイルの場所からパッケージをアップロードできます。サイズの大きいファイルの場合は、Amazon S3 バケットから .zip または JAR パッケージをアップロードする必要があります。AWS CLI を使用して Amazon S3 バケットにファイルをアップロードする方法については、「AWS CLI ユーザーガイド」の「[オブジェクトの移動](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)」を参照してください。

**注記**  
AWS CLI を使用して Amazon S3 バケットから .zip または JAR ファイルをアップロードする場合、このバケットは関数と同じ AWS リージョン に配置する必要があります。

 AWS CLI を含む .zip または JAR ファイルを使用して新しい関数を作成するには、以下を指定する必要があります。
+ 関数の名前 (`--function-name`)
+ 関数のランタイム (`--runtime`)
+ 関数の[実行ロール](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html) (`--role`) の Amazon リソースネーム (ARN)
+ 関数コード内のハンドラーメソッド (`--handler`) の名前

 .zip ファイルの場所も指定する必要があります。.zip または JAR ファイルがローカルビルドマシン上のフォルダにある場合は、次のコマンド例に示すように、`--zip-file` オプションを使用してファイルパスを指定します。

```
aws lambda create-function --function-name myFunction \
--runtime java25 --handler example.handler \
--role arn:aws:iam::123456789012:role/service-role/my-lambda-role \
--zip-file fileb://myFunction.zip
```

 Amazon S3 バケット内の .zip ファイルの場所を指定するには、以下のコマンド例にある `--code` オプションを使用します。`S3ObjectVersion` パラメータは、バージョン管理下のオブジェクトにのみ使用する必要があります。

```
aws lambda create-function --function-name myFunction \
--runtime java25 --handler example.handler \
--role arn:aws:iam::123456789012:role/service-role/my-lambda-role \
--code S3Bucket=amzn-s3-demo-bucket,S3Key=myFileName.zip,S3ObjectVersion=myObjectVersion
```

 CLI を使用して既存の関数を更新するには、`--function-name` パラメータを使用して関数の名前を指定します。関数コードの更新に使用する .zip ファイルの場所も指定する必要があります。.zip ファイルがローカルビルドマシン上のフォルダにある場合は、次のコマンド例に示すように、`--zip-file` オプションを使用してファイルパスを指定します。

```
aws lambda update-function-code --function-name myFunction \
--zip-file fileb://myFunction.zip
```

 Amazon S3 バケット内の .zip ファイルの場所を指定するには、以下のコマンド例にある `--s3-bucket` および `--s3-key` オプションを使用します。`--s3-object-version` パラメータは、バージョン管理下のオブジェクトにのみ使用する必要があります。

```
aws lambda update-function-code --function-name myFunction \
--s3-bucket amzn-s3-demo-bucket --s3-key myFileName.zip --s3-object-version myObject Version
```

## AWS SAM によるデプロイパッケージのアップロード
<a name="java-package-cloudformation"></a>

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

**Example 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](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      CodeUri: build/distributions/java-basic.zip
      Handler: example.Handler
      Runtime: java25
      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 ビルドを実行し、作成されたデプロイパッケージをアップロードします。また、初回実行時に CloudFormation スタックを作成します。そのスタックがすでに存在する場合は更新します。

**Example 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 アプリケーション**
+ [example-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/example-java) – Lambda を使用して注文処理を行う Java 関数。この関数は、カスタム入力イベントオブジェクトの定義と逆シリアル化、 AWS SDK の使用方法、および出力ログ記録の方法を示しています。
+ [java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。
+ [java-events](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events) - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの [aws-lambda-java-events](#java-package) ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。
+ [s3-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java) － Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。
+ [layer-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-java) – Lambda レイヤーを使用して、コアとなる関数コードから分離して依存関係をパッケージ化する方法を示す Java 関数。

# コンテナイメージを使用した Java Lambda 関数のデプロイ
<a name="java-image"></a>

Java Lambda 関数のコンテナイメージを構築するには 3 つの方法があります。
+ [Java の AWS ベースイメージを使用する](#java-image-instructions)

  [AWS ベースイメージ](images-create.md#runtimes-images-lp)には、言語ランタイム、Lambda と関数コード間のやり取りを管理するランタイムインターフェースクライアント、ローカルテスト用のランタイムインターフェースエミュレーターがあらかじめロードされています。
+ [AWS の OS 専用ベースイメージを使用する](images-create.md#runtimes-images-provided)

  [AWS OS 専用ベースイメージ](https://gallery.ecr.aws/lambda/provided)には、Amazon Linux ディストリビューションおよび[ランタイムインターフェイスエミュレータ](https://github.com/aws/aws-lambda-runtime-interface-emulator/)が含まれています。これらのイメージは、[Go](go-image.md#go-image-provided) や [Rust](lambda-rust.md) などのコンパイル済み言語や、Lambda がベースイメージを提供していない言語または言語バージョン (Node.js 19 など) のコンテナイメージの作成によく使用されます。OS 専用のベースイメージを使用して[カスタムランタイム](runtimes-custom.md)を実装することもできます。イメージに Lambda との互換性を持たせるには、[Java のランタイムインターフェイスクライアント](#java-image-clients)をイメージに含める必要があります。
+ [非 AWS ベースイメージを使用する](#java-image-clients)

  Alpine Linux や Debian など、別のコンテナレジストリの代替ベースイメージを使用することもできます。組織が作成したカスタムイメージを使用することもできます。イメージに Lambda との互換性を持たせるには、[Java のランタイムインターフェイスクライアント](#java-image-clients)をイメージに含める必要があります。

**ヒント**  
Lambda コンテナ関数がアクティブになるまでの時間を短縮するには、「Docker ドキュメント」の「[マルチステージビルドを使用する](https://docs.docker.com/build/building/multi-stage/)」を参照してください。効率的なコンテナイメージを構築するには、「[Dockerfiles を記述するためのベストプラクティス](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)」に従ってください。

このページでは、Lambda のコンテナイメージを構築、テスト、デプロイする方法について説明します。

**Topics**
+ [Java の AWS ベースイメージ](#java-image-base)
+ [Java の AWS ベースイメージを使用する](#java-image-instructions)
+ [ランタイムインターフェイスクライアントで代替ベースイメージを使用する](#java-image-clients)

## Java の AWS ベースイメージ
<a name="java-image-base"></a>

AWS は、Java の次のベースイメージを提供します。


| タグ | ランタイム | オペレーティングシステム | Dockerfile | 非推奨 | 
| --- | --- | --- | --- | --- | 
| 25 | Java 25 | Amazon Linux 2023 | [GitHub の Java 25 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/java25/Dockerfile.java25) |   2029 年 6 月 30 日   | 
| 21 | Java 21 | Amazon Linux 2023 | [GitHub の Java 21 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/java21/Dockerfile.java21) |   2029 年 6 月 30 日   | 
| 17 | Java 17 | Amazon Linux 2 | [GitHub の Java 17 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/java17/Dockerfile.java17) |   2027 年 6 月 30 日   | 
| 11 | Java 11 | Amazon Linux 2 | [GitHub の Java 11 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/java11/Dockerfile.java11) |   2027 年 6 月 30 日   | 
| 8.al2 | Java 8 | Amazon Linux 2 | [GitHub の Java 8 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/java8.al2/Dockerfile.java8.al2) |   2027 年 6 月 30 日   | 

Amazon ECR リポジトリ: [gallery.ecr.aws/lambda/java](https://gallery.ecr.aws/lambda/java)

Java 21 以降のベースイメージは、[Amazon Linux 2023 の最小コンテナイメージ](https://docs.aws.amazon.com/linux/al2023/ug/minimal-container.html)に基づいています。以前のベースイメージでは Amazon Linux 2 が使用されています。AL2023 ランタイムには、デプロイのフットプリントが小さいことや、`glibc` などのライブラリのバージョンが更新されていることなど、Amazon Linux 2 に比べていくつかの利点があります。

AL2023 ベースのイメージでは、Amazon Linux 2 のデフォルトのパッケージマネージャである `yum` の代わりに `microdnf` (`dnf` としてシンボリックリンク) がパッケージマネージャとして使用されています。`microdnf` は `dnf` のスタンドアロン実装です。AL2023 ベースのイメージに含まれるパッケージのリストについては、「[Comparing packages installed on Amazon Linux 2023 Container Images](https://docs.aws.amazon.com/linux/al2023/ug/al2023-container-image-types.html)」の「**Minimal Container**」列を参照してください。AL2023 と Amazon Linux 2 の違いの詳細については、AWS コンピューティングブログの「[Introducing the Amazon Linux 2023 runtime for AWS Lambda](https://aws.amazon.com/blogs/compute/introducing-the-amazon-linux-2023-runtime-for-aws-lambda/)」を参照してください。

**注記**  
AWS Serverless Application Model (AWS SAM) を含む AL2023 ベースのイメージをローカルで実行するには、Docker バージョン 20.10.10 以降を使用する必要があります。

## Java の AWS ベースイメージを使用する
<a name="java-image-instructions"></a>

### 前提条件
<a name="java-image-prerequisites"></a>

このセクションの手順を完了するには、以下が必要です。
+ Java (たとえば、「[Amazon Corretto](https://aws.amazon.com/corretto)」)
+ 「[Apache Maven](https://maven.apache.org/)」または「[Gradle](https://gradle.org/install/)」
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (最小バージョン 25.0.0)
+ Docker [buildx プラグイン](https://github.com/docker/buildx/blob/master/README.md)。

### ベースイメージからイメージを作成する
<a name="java-image-create"></a>

------
#### [ Maven ]

1. 次のコマンドを実行し、「[Lambda のアーキタイプ](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda)」を使用して Maven プロジェクトを作成します。以下のパラメータは必須です。
   + **サービス** — Lambda 関数の使用対象となる AWS のサービス クライアント。利用可能なソースのリストについては、GitHub の「[aws-sdk-java-v2/services](https://github.com/aws/aws-sdk-java-v2/tree/master/services)」をご覧ください。
   + **region** – Lambda 関数を作成する AWS リージョン。
   + **groupId** — アプリケーションの完全パッケージの名前空間。
   + **artifactId** — ユーザーのプロジェクト名。これがプロジェクトのディレクトリの名前になります。

   Linux および macOS では、次のコマンドを実行します。

   ```
   mvn -B archetype:generate \
      -DarchetypeGroupId=software.amazon.awssdk \
      -DarchetypeArtifactId=archetype-lambda -Dservice=s3 -Dregion=US_WEST_2 \
      -DgroupId=com.example.myapp \
      -DartifactId=myapp
   ```

   PowerShell で、次のコマンドを実行します。

   ```
   mvn -B archetype:generate `
      "-DarchetypeGroupId=software.amazon.awssdk" `
      "-DarchetypeArtifactId=archetype-lambda" "-Dservice=s3" "-Dregion=US_WEST_2" `
      "-DgroupId=com.example.myapp" `
      "-DartifactId=myapp"
   ```

   Lambda の Maven アーキタイプは、Java SE 8 でコンパイルするように事前設定されており、AWS SDK for Java への依存関係を含みます。別のアーキタイプまたは別の方法でプロジェクトを作成する場合、[Maven の Java コンパイラを設定](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#configure-maven-compiler)し、[SDK を依存関係として宣言](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#configure-maven-compiler)する必要があります。

1. `myapp/src/main/java/com/example/myapp` ディレクトリを開いて `App.java` ファイルを探します。これは Lambda 関数のコードです。提供されるサンプルコードをテストに使用することも、独自のサンプルコードで置き換えることもできます。

1. プロジェクトのルートディレクトリに戻り、次の設定で新しい Dockerfile を作成します。
   + `FROM` プロパティに[ベースイメージの URI](https://gallery.ecr.aws/lambda/java) を設定します。
   + `CMD` 引数を Lambda 関数ハンドラーに設定します。

   この例の Dockerfile には [USER 命令](https://docs.docker.com/reference/dockerfile/#user)が含まれていないことに注意してください。コンテナイメージを Lambda にデプロイすると、最小特権のアクセス許可を付与したデフォルトの Linux ユーザーを Lambda が自動的に定義します。これは標準の Docker 動作とは異なります。標準の動作とは、`USER` 命令を指定しなかったときに `root` ユーザーのデフォルトとなる動作のことです。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/java:21
     
   # Copy function code and runtime dependencies from Maven layout
   COPY target/classes ${LAMBDA_TASK_ROOT}
   COPY target/dependency/* ${LAMBDA_TASK_ROOT}/lib/
       
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "com.example.myapp.App::handleRequest" ]
   ```

1. プロジェクトをコンパイルしてランタイムの依存関係を収集します。

   ```
   mvn compile dependency:copy-dependencies -DincludeScope=runtime
   ```

1. Docker イメージを「[Docker の構築](https://docs.docker.com/engine/reference/commandline/build/)」コマンドで構築します。次の例では、イメージを `docker-image` と名付けて `test` [タグ](https://docs.docker.com/engine/reference/commandline/build/#tag)を付けます。Lambda互換のイメージを作成するには、 `--provenance=false` オプションを使用する必要があります。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注記**  
このコマンドは、ビルドマシンのアーキテクチャに関係なく、コンテナが Lambda の実行環境と互換性があることを確認する `--platform linux/amd64` オプションを特定します。ARM64 命令セットアーキテクチャを使用して Lambda 関数を作成する場合は、代わりに `--platform linux/arm64` オプションを使用するようにコマンドを変更してください。

------
#### [ Gradle ]

1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

   ```
   mkdir example
   cd example
   ```

1. 次のコマンドを実行して、Gradle が 環境の `example` ディレクトリに新しい Java アプリケーションプロジェクトを生成するようにします。**[ビルドスクリプト DSL を選択]** では、**[2: Groovy]** を選択します。

   ```
   gradle init --type java-application
   ```

1. `/example/app/src/main/java/example` ディレクトリを開いて `App.java` ファイルを探します。これは Lambda 関数のコードです。次のサンプルコードをテストに使用することも、独自のサンプルコードで置き換えることもできます。  
**Example App.java**  

   ```
   package com.example;
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   public class App implements RequestHandler<Object, String> {
       public String handleRequest(Object input, Context context) {
           return "Hello world!";
       }
   }
   ```

1. `build.gradle` ファイルを開きます。前のステップのサンプル関数コードを使用している場合、「`build.gradle`」の内容を次の内容で置き換えてください。独自の関数コードを使用している場合、必要に応じて「`build.gradle`」ファイルを変更してください。  
**Example build.gradle (Groovy DSL)**  

   ```
   plugins {
     id 'java'
   }
   group 'com.example'
   version '1.0-SNAPSHOT'
   sourceCompatibility = 1.8
   repositories {
     mavenCentral()
   }
   dependencies {
     implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
   }
   jar {
     manifest {
         attributes 'Main-Class': 'com.example.App'
     }
   }
   ```

1. また。ステップ 2 の `gradle init` コマンドが `app/test` ディレクトリにダミーのテストケースを生成しました。このチュートリアルの用途のため、`/test` ディレクトリを削除してテスト実行をスキップします。

1. プロジェクトをビルドします。

   ```
   gradle build
   ```

1. プロジェクトのルートディレクトリ (`/example`) に、次の設定で Dockerfile を作成します。
   + `FROM` プロパティを「[ベースイメージの URI](https://gallery.ecr.aws/lambda/java)」に設定します。
   + COPY コマンドを使用し、関数コードおよびランタイムの依存関係を `{LAMBDA_TASK_ROOT}` ([Lambda 定義の環境変数](configuration-envvars.md#configuration-envvars-runtime)) にコピーします。
   + `CMD` 引数を Lambda 関数ハンドラーに設定します。

   この例の Dockerfile には [USER 命令](https://docs.docker.com/reference/dockerfile/#user)が含まれていないことに注意してください。コンテナイメージを Lambda にデプロイすると、最小特権のアクセス許可を付与したデフォルトの Linux ユーザーを Lambda が自動的に定義します。これは標準の Docker 動作とは異なります。標準の動作とは、`USER` 命令を指定しなかったときに `root` ユーザーのデフォルトとなる動作のことです。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/java:21
     
   # Copy function code and runtime dependencies from Gradle layout
   COPY app/build/classes/java/main ${LAMBDA_TASK_ROOT}
     
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "com.example.App::handleRequest" ]
   ```

1. Docker イメージを「[Docker の構築](https://docs.docker.com/engine/reference/commandline/build/)」コマンドで構築します。次の例では、イメージを `docker-image` と名付けて `test` [タグ](https://docs.docker.com/engine/reference/commandline/build/#tag)を付けます。Lambda互換のイメージを作成するには、 `--provenance=false` オプションを使用する必要があります。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注記**  
このコマンドは、ビルドマシンのアーキテクチャに関係なく、コンテナが Lambda の実行環境と互換性があることを確認する `--platform linux/amd64` オプションを特定します。ARM64 命令セットアーキテクチャを使用して Lambda 関数を作成する場合は、代わりに `--platform linux/arm64` オプションを使用するようにコマンドを変更してください。

------

### (オプション) イメージをローカルでテストする
<a name="java-image-test"></a>

1. **docker run** コマンドを使用して、Docker イメージを起動します。この例では、`docker-image` はイメージ名、`test` はタグです。

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   このコマンドはイメージをコンテナとして実行し、`localhost:9000/2015-03-31/functions/function/invocations` でローカルエンドポイントを作成します。
**注記**  
ARM64 命令セットアーキテクチャ用に Docker イメージをビルドした場合は、`--platform linux/amd64` の代わりに `--platform linux/arm64` オプションを使用してください。

1. 新しいターミナルウィンドウから、イベントをローカルエンドポイントにポストします。

------
#### [ Linux/macOS ]

   Linux および macOS では、次の `curl` コマンドを実行します。

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   このコマンドは、空のイベントで関数を呼び出し、応答を返します。サンプル関数コードではなく独自の関数コードを使用している場合は、JSON ペイロードを使用して関数を呼び出すことをお勧めします。例:

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   PowerShell で次の `Invoke-WebRequest` コマンドを実行します。

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   このコマンドは、空のイベントで関数を呼び出し、応答を返します。サンプル関数コードではなく独自の関数コードを使用している場合は、JSON ペイロードを使用して関数を呼び出すことをお勧めします。例:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. コンテナ ID を取得します。

   ```
   docker ps
   ```

1. 「[docker kill](https://docs.docker.com/engine/reference/commandline/kill/)」コマンドを使用してコンテナを停止します。このコマンドでは、`3766c4ab331c` を前のステップのコンテナ ID で置き換えます。

   ```
   docker kill 3766c4ab331c
   ```

### イメージのデプロイ
<a name="java-image-deploy"></a>

**Amazon ECR にイメージをアップロードして Lambda 関数を作成するには**

1. 「[get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html)」コマンドを実行して Amazon ECR レジストリに Docker CLI を認証します。
   + `--region` 値を Amazon ECR リポジトリを作成する AWS リージョン に設定します。
   + `111122223333` を AWS アカウント ID に置き換えます。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 「[create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html)」コマンドを使用して Amazon ECR にリポジトリを作成します。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注記**  
Amazon ECR リポジトリは Lambda 関数と同じ AWS リージョン に配置されている必要があります。

   成功すると、次のようなレスポンスが表示されます。

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 前のステップの出力から `repositoryUri` をコピーします。

1. 「[docker tag](https://docs.docker.com/engine/reference/commandline/tag/)」コマンドを実行して、最新バージョンとしてローカルイメージを Amazon ECR リポジトリにタグ付けします。このコマンドで:
   + `docker-image:test` は、Docker イメージの名前と[タグ](https://docs.docker.com/engine/reference/commandline/build/#tag)です。これは、`docker build` コマンドに指定したイメージの名前とタグです。
   + `<ECRrepositoryUri>` を、コピーした `repositoryUri` に置き換えます。URI の末尾には必ず `:latest` を含めてください。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   例:

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 「[docker push](https://docs.docker.com/engine/reference/commandline/push/)」コマンドを実行して Amazon ECR リポジトリにローカルイメージをデプロイします リポジトリ URI の末尾には必ず `:latest` を含めてください。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. まだ作成済みでない場合、関数に「[実行ロールの作成](lambda-intro-execution-role.md#permissions-executionrole-api)」を実行してください。次のステップではロールの Amazon リソースネーム (ARN) が必要です。

1. Lambda 関数を作成します。`ImageUri` には、先ほど使用したリポジトリ URI を指定します。URI の末尾には必ず `:latest` を含めてください。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注記**  
イメージが Lambda 関数と同じリージョンに配置されていれば、別の AWS アカウントのイメージを使用して関数を作成することができます。詳細については、「[Amazon ECR クロスアカウント許可](images-create.md#configuration-images-xaccount-permissions)」を参照してください。

1. 関数を呼び出します。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   次のような結果が表示されます。

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 関数の出力を確認するには、`response.json` ファイルをチェックします。

関数コードを更新するには、イメージを再構築し、新しいイメージを Amazon ECR リポジトリにアップロードしてから、[update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) コマンドを使用してイメージを Lambda 関数にデプロイする必要があります。

Lambda は、イメージタグを特定のイメージダイジェストに解決します。これは、関数のデプロイに使用されたイメージタグを Amazon ECR 内の新しいイメージを指すように変更しても、Lambda は新しいイメージを使用するように自動的に関数を更新しないことを意味します。

新しいイメージを同じ Lambda 関数にデプロイするには、Amazon ECR のイメージタグが同じままであっても、[update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) コマンドを使用する必要があります。次の例では、`--publish` オプションが最新のコンテナイメージを使用して関数の新しいバージョンを作成しています。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

## ランタイムインターフェイスクライアントで代替ベースイメージを使用する
<a name="java-image-clients"></a>

[OS 専用ベースイメージ](images-create.md#runtimes-images-provided)または代替のベースイメージを使用する場合、イメージにランタイムインターフェイスクライアントを含める必要があります。ランタイムインターフェイスクライアントは、Lambda と関数コード間の相互作用を管理する [ランタイム API](runtimes-api.md) を拡張します。

Java 用のランタイムインターフェイスクライアントを Dockerfile にインストールするか、プロジェクトの依存関係としてインストールします。たとえば、Maven パッケージマネージャーを使用してランタイムインターフェイスクライアントをインストールするには、`pom.xml` ファイルに以下を追加します。

```
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-runtime-interface-client</artifactId>
    <version>2.3.2</version>
</dependency>
```

パッケージの詳細については、「Maven Central Repository」の「[AWS Lambda Java ランタイムのインターフェイスクライアント](https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-runtime-interface-client)」を参照してください。GitHub リポジトリの [AWS Lambda Java Support Libraries](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-runtime-interface-client) で、ランタイムインターフェイスクライアントのソースコードを確認することもできます。

次の例は、[Amazon Corretto イメージ](https://gallery.ecr.aws/amazoncorretto/amazoncorretto)を使用して Java 用のコンテナイメージを構築する方法を示しています。Amazon Corretto は、Open Java Development Kit (OpenJDK) の、マルチプラットフォーム対応の本番稼働可能な、無償ディストリビューションです。Maven プロジェクトには、ランタイムインターフェイスクライアントが依存関係として含まれています。

### 前提条件
<a name="java-alt-prerequisites"></a>

このセクションの手順を完了するには、以下が必要です。
+ Java (たとえば、「[Amazon Corretto](https://aws.amazon.com/corretto)」)
+ [Apache Maven](https://maven.apache.org/)
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (最小バージョン 25.0.0)
+ Docker [buildx プラグイン](https://github.com/docker/buildx/blob/master/README.md)。

### 代替ベースイメージからイメージを作成する
<a name="java-alt-create"></a>

1. Maven プロジェクトの作成 以下のパラメータは必須です。
   + **groupId** — アプリケーションの完全パッケージの名前空間。
   + **artifactId** — ユーザーのプロジェクト名。これがプロジェクトのディレクトリの名前になります。

------
#### [ Linux/macOS ]

   ```
   mvn -B archetype:generate \
      -DarchetypeArtifactId=maven-archetype-quickstart \
      -DgroupId=example \
      -DartifactId=myapp \
      -DinteractiveMode=false
   ```

------
#### [ PowerShell ]

   ```
   mvn -B archetype:generate `
      -DarchetypeArtifactId=maven-archetype-quickstart `
      -DgroupId=example `
      -DartifactId=myapp `
      -DinteractiveMode=false
   ```

------

1. プロジェクトディレクトリを開きます。

   ```
   cd myapp
   ```

1. `pom.xml` ファイルを開き、内容を次に置き換えます。このファイルには、[aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-runtime-interface-client) が依存関係として含まれています。代わりに、ランタイムインターフェイスクライアントを Dockerfile にインストールすることもできます。ただし、最も簡単な方法は、ライブラリを依存関係として含めることです。

   ```
   <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/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>example</groupId>
     <artifactId>hello-lambda</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>hello-lambda</name>
     <url>http://maven.apache.org</url>
     <properties>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
     <dependencies>
       <dependency>
         <groupId>com.amazonaws</groupId>
         <artifactId>aws-lambda-java-runtime-interface-client</artifactId>
         <version>2.3.2</version>
       </dependency>
     </dependencies>
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-dependency-plugin</artifactId>
           <version>3.1.2</version>
           <executions>
             <execution>
               <id>copy-dependencies</id>
               <phase>package</phase>
               <goals>
                 <goal>copy-dependencies</goal>
               </goals>
             </execution>
           </executions>
         </plugin>
       </plugins>
     </build>
   </project>
   ```

1. `myapp/src/main/java/com/example/myapp` ディレクトリを開いて `App.java` ファイルを探します。これは Lambda 関数のコードです。このコードを、次のコードで置き換えます。  
**Example 関数ハンドラ**  

   ```
   package example;
   
   public class App {
       public static String sayHello() {
           return "Hello world!";
       }
   }
   ```

1. ステップ 1 の `mvn -B archetype:generate` コマンドにより、ダミーのテストケースも `src/test` ディレクトリに生成されます。このチュートリアルでは、この生成された `/test` ディレクトリ全体を削除して、実行中のテストをスキップします。

1. プロジェクトのルートディレクトリに戻り、新しい Dockerfile を作成します。次の Dockerfile の例では、[Amazon Corretto](https://gallery.ecr.aws/amazoncorretto/amazoncorretto) イメージを使用しています。Amazon Corretto は、マルチプラットフォーム対応で本番稼働可能な OpenJDK の無償ディストリビューションです。
   + ベースイメージの URI に `FROM` プロパティを設定します。
   + `ENTRYPOINT` を、Docker コンテナの起動時に実行させるモジュールに設定します。この場合、モジュールはランタイムインターフェイスクライアントです。
   + `CMD` 引数を Lambda 関数ハンドラーに設定します。

   この例の Dockerfile には [USER 命令](https://docs.docker.com/reference/dockerfile/#user)が含まれていないことに注意してください。コンテナイメージを Lambda にデプロイすると、最小特権のアクセス許可を付与したデフォルトの Linux ユーザーを Lambda が自動的に定義します。これは標準の Docker 動作とは異なります。標準の動作とは、`USER` 命令を指定しなかったときに `root` ユーザーのデフォルトとなる動作のことです。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/amazoncorretto/amazoncorretto:21 as base
   
   # Configure the build environment
   FROM base as build
   RUN yum install -y maven
   WORKDIR /src
   
   # Cache and copy dependencies
   ADD pom.xml .
   RUN mvn dependency:go-offline dependency:copy-dependencies
   
   # Compile the function
   ADD . .
   RUN mvn package 
   
   # Copy the function artifact and dependencies onto a clean base
   FROM base
   WORKDIR /function
   
   COPY --from=build /src/target/dependency/*.jar ./
   COPY --from=build /src/target/*.jar ./
   
   # Set runtime interface client as default command for the container runtime
   ENTRYPOINT [ "/usr/bin/java", "-cp", "./*", "com.amazonaws.services.lambda.runtime.api.client.AWSLambda" ]
   # Pass the name of the function handler as an argument to the runtime
   CMD [ "example.App::sayHello" ]
   ```

1. Docker イメージを「[Docker の構築](https://docs.docker.com/engine/reference/commandline/build/)」コマンドで構築します。次の例では、イメージを `docker-image` と名付けて `test` [タグ](https://docs.docker.com/engine/reference/commandline/build/#tag)を付けます。Lambda互換のイメージを作成するには、 `--provenance=false` オプションを使用する必要があります。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注記**  
このコマンドは、ビルドマシンのアーキテクチャに関係なく、コンテナが Lambda の実行環境と互換性があることを確認する `--platform linux/amd64` オプションを特定します。ARM64 命令セットアーキテクチャを使用して Lambda 関数を作成する場合は、代わりに `--platform linux/arm64` オプションを使用するようにコマンドを変更してください。

### (オプション) イメージをローカルでテストする
<a name="java-alt-test"></a>

[ランタイムインターフェイスエミュレーター](https://github.com/aws/aws-lambda-runtime-interface-emulator/)を使用して、イメージをローカルでテストします。[エミュレーターはイメージに組み込むことも](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image)、次の手順を使用してローカルマシンにインストールすることもできます。

**ローカルマシンにランタイムインターフェイスエミュレーターをインストールして実行するには**

1. プロジェクトディレクトリから次のコマンドを実行して、GitHub からランタイムインターフェイスエミュレーター (x86-64 アーキテクチャ) をダウンロードし、ローカルマシンにインストールします。

------
#### [ Linux/macOS ]

   ```
   mkdir -p ~/.aws-lambda-rie && \
       curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
       chmod +x ~/.aws-lambda-rie/aws-lambda-rie
   ```

   arm64 エミュレータをインストールするには、前のコマンドの GitHub リポジトリ URL を次のように置き換えます。

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------
#### [ PowerShell ]

   ```
   $dirPath = "$HOME\.aws-lambda-rie"
   if (-not (Test-Path $dirPath)) {
       New-Item -Path $dirPath -ItemType Directory
   }
         
   $downloadLink = "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie"
   $destinationPath = "$HOME\.aws-lambda-rie\aws-lambda-rie"
   Invoke-WebRequest -Uri $downloadLink -OutFile $destinationPath
   ```

   arm64 エミュレーターをインストールするには、`$downloadLink` を次のように置き換えます。

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------

1. **docker run** コマンドを使用して、Docker イメージを起動します。次の点に注意してください。
   + `docker-image` はイメージ名、`test` はタグです。
   + `/usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello` は `ENTRYPOINT` で、その後に Dockerfile の `CMD` が続きます。

------
#### [ Linux/macOS ]

   ```
   docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
       --entrypoint /aws-lambda/aws-lambda-rie \
       docker-image:test \
           /usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello
   ```

------
#### [ PowerShell ]

   ```
   docker run --platform linux/amd64 -d -v "$HOME\.aws-lambda-rie:/aws-lambda" -p 9000:8080 `
   --entrypoint /aws-lambda/aws-lambda-rie `
   docker-image:test `
       /usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello
   ```

------

   このコマンドはイメージをコンテナとして実行し、`localhost:9000/2015-03-31/functions/function/invocations` でローカルエンドポイントを作成します。
**注記**  
ARM64 命令セットアーキテクチャ用に Docker イメージをビルドした場合は、`--platform linux/amd64` の代わりに `--platform linux/arm64` オプションを使用してください。

1. イベントをローカルエンドポイントにポストします。

------
#### [ Linux/macOS ]

   Linux および macOS では、次の `curl` コマンドを実行します。

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   このコマンドは、空のイベントで関数を呼び出し、応答を返します。サンプル関数コードではなく独自の関数コードを使用している場合は、JSON ペイロードを使用して関数を呼び出すことをお勧めします。例:

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   PowerShell で次の `Invoke-WebRequest` コマンドを実行します。

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   このコマンドは、空のイベントで関数を呼び出し、応答を返します。サンプル関数コードではなく独自の関数コードを使用している場合は、JSON ペイロードを使用して関数を呼び出すことをお勧めします。例:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. コンテナ ID を取得します。

   ```
   docker ps
   ```

1. 「[docker kill](https://docs.docker.com/engine/reference/commandline/kill/)」コマンドを使用してコンテナを停止します。このコマンドでは、`3766c4ab331c` を前のステップのコンテナ ID で置き換えます。

   ```
   docker kill 3766c4ab331c
   ```

### イメージのデプロイ
<a name="java-alt-deploy"></a>

**Amazon ECR にイメージをアップロードして Lambda 関数を作成するには**

1. 「[get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html)」コマンドを実行して Amazon ECR レジストリに Docker CLI を認証します。
   + `--region` 値を Amazon ECR リポジトリを作成する AWS リージョン に設定します。
   + `111122223333` を AWS アカウント ID に置き換えます。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 「[create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html)」コマンドを使用して Amazon ECR にリポジトリを作成します。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注記**  
Amazon ECR リポジトリは Lambda 関数と同じ AWS リージョン に配置されている必要があります。

   成功すると、次のようなレスポンスが表示されます。

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 前のステップの出力から `repositoryUri` をコピーします。

1. 「[docker tag](https://docs.docker.com/engine/reference/commandline/tag/)」コマンドを実行して、最新バージョンとしてローカルイメージを Amazon ECR リポジトリにタグ付けします。このコマンドで:
   + `docker-image:test` は、Docker イメージの名前と[タグ](https://docs.docker.com/engine/reference/commandline/build/#tag)です。これは、`docker build` コマンドに指定したイメージの名前とタグです。
   + `<ECRrepositoryUri>` を、コピーした `repositoryUri` に置き換えます。URI の末尾には必ず `:latest` を含めてください。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   例:

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 「[docker push](https://docs.docker.com/engine/reference/commandline/push/)」コマンドを実行して Amazon ECR リポジトリにローカルイメージをデプロイします リポジトリ URI の末尾には必ず `:latest` を含めてください。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. まだ作成済みでない場合、関数に「[実行ロールの作成](lambda-intro-execution-role.md#permissions-executionrole-api)」を実行してください。次のステップではロールの Amazon リソースネーム (ARN) が必要です。

1. Lambda 関数を作成します。`ImageUri` には、先ほど使用したリポジトリ URI を指定します。URI の末尾には必ず `:latest` を含めてください。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注記**  
イメージが Lambda 関数と同じリージョンに配置されていれば、別の AWS アカウントのイメージを使用して関数を作成することができます。詳細については、「[Amazon ECR クロスアカウント許可](images-create.md#configuration-images-xaccount-permissions)」を参照してください。

1. 関数を呼び出します。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   次のような結果が表示されます。

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 関数の出力を確認するには、`response.json` ファイルをチェックします。

関数コードを更新するには、イメージを再構築し、新しいイメージを Amazon ECR リポジトリにアップロードしてから、[update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) コマンドを使用してイメージを Lambda 関数にデプロイする必要があります。

Lambda は、イメージタグを特定のイメージダイジェストに解決します。これは、関数のデプロイに使用されたイメージタグを Amazon ECR 内の新しいイメージを指すように変更しても、Lambda は新しいイメージを使用するように自動的に関数を更新しないことを意味します。

新しいイメージを同じ Lambda 関数にデプロイするには、Amazon ECR のイメージタグが同じままであっても、[update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) コマンドを使用する必要があります。次の例では、`--publish` オプションが最新のコンテナイメージを使用して関数の新しいバージョンを作成しています。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

# Java Lambda 関数のレイヤーを操作する
<a name="java-layers"></a>

[Lambda レイヤー](chapter-layers.md)を使用して、複数の関数間で再利用するコードおよび依存関係をパッケージ化できます。レイヤーには通常、ライブラリの依存関係、[カスタムランタイム](runtimes-custom.md)、または設定ファイルが含まれています。レイヤーの作成には、次の 3 つの一般的な手順が含まれます。

1. レイヤーコンテンツのパッケージ化。これは、関数で使用する依存関係を含む .zip ファイルアーカイブを作成することを意味します。

1. Lambda でレイヤーを作成します。

1. レイヤーを関数に追加します。

**Topics**
+ [レイヤーコンテンツのパッケージ化](#java-layers-package)
+ [Lambda でレイヤーを作成する](#publishing-layer)
+ [レイヤーを関数に追加する](#java-layer-adding)

## レイヤーコンテンツのパッケージ化
<a name="java-layers-package"></a>

レイヤーを作成するには、次の要件を満たす .zip ファイルのアーカイブにパッケージをバンドルします。
+ Maven または Gradle が参照する Java バージョンが、デプロイする関数の Java バージョンと同じであることを確認してください。例えば、Java 25 関数の場合、`mvn -v` コマンドは出力に Java 25 をリストする必要があります。
+ 依存関係は、.zip ファイルのルートにある `java/lib` ディレクトリに格納する必要があります。詳細については、「[各 Lambda ランタイムのレイヤーパス](packaging-layers.md#packaging-layers-paths)」を参照してください。
+ レイヤーのパッケージは Linux と互換性がある必要があります。Lambda 関数は Amazon Linux 上で動作します。

サードパーティの Java ライブラリか、あるいはユーザー独自の Java モジュールやパッケージを含むレイヤーを作成できます。次の手順では、Maven を使用します。Gradle を使用してレイヤーコンテンツをパッケージ化することもできます。

**Maven の依存関係を使用してレイヤーを作成するには**

1. 依存関係を定義する `pom.xml` ファイルを使用して Apache Maven プロジェクトを作成します。

   次の例には、JSON 処理用の [Jackson Databind](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind) が含まれています。この `<build>` セクションでは、[maven-dependency-plugin](https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin) を使用して、依存関係を 1 つの uber-jar にバンドルするのではなく、依存関係ごとに個別の JAR ファイルを作成します。uber-jar を作成する場合は、[maven-shade-plugin](https://maven.apache.org/plugins/maven-shade-plugin/) を使用します。  
**Example pom.xml**  

   ```
   <dependencies>
       <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-databind</artifactId>
           <version>2.17.0</version>
       </dependency>
   </dependencies>
   
   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.13.0</version>
               <configuration>
                   <source>21</source>
                   <target>21</target>
                   <release>21</release>
               </configuration>
           </plugin>
           
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-dependency-plugin</artifactId>
               <version>3.6.1</version>
               <executions>
                   <execution>
                       <id>copy-dependencies</id>
                       <phase>package</phase>
                       <goals>
                           <goal>copy-dependencies</goal>
                       </goals>
                       <configuration>
                           <outputDirectory>${project.build.directory}/lib</outputDirectory>
                       </configuration>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>
   ```

1. プロジェクトをビルドします。このコマンドを実行すると、依存関係のすべての JAR ファイルが `target/lib/` ディレクトリに生成されます。

   ```
   mvn clean package
   ```

1. レイヤーに必要なディレクトリ構造を作成します。

   ```
   mkdir -p java/lib
   ```

1. 依存関係 JAR ファイルを `java/lib` ディレクトリにコピーします。

   ```
   cp target/lib/*.jar java/lib/
   ```

1. レイヤーコンテンツを圧縮します。

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip java/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\java -DestinationPath .\layer.zip
   ```

------

   .zip ファイルのディレクトリ構造は次のようになります。

   ```
   java/              
   └── lib/
       ├── jackson-databind-2.17.0.jar
       ├── jackson-core-2.17.0.jar
       └── jackson-annotations-2.17.0.jar
   ```
**注記**  
zip ファイルには、ルートレベルに `java` ディレクトリを含み、その中に `lib` ディレクトリがあることを確認してください。この構造により、Lambda はライブラリを正確に探し出してインポートできます。各依存関係は、uber-jar にバンドルされるのではなく、個別の JAR ファイルとして保持されます。

## Lambda でレイヤーを作成する
<a name="publishing-layer"></a>

AWS CLI または Lambda コンソールを使用して、レイヤーを発行できます。

------
#### [ AWS CLI ]

[publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) AWS CLI コマンドを実行して Lambda レイヤーを作成します。

```
aws lambda publish-layer-version --layer-name my-layer --zip-file fileb://layer.zip --compatible-runtimes java25
```

[互換性のあるランタイム](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)パラメータの使用は任意です。指定すると、Lambda はこのパラメータを使用して Lambda コンソールのレイヤーをフィルタリングします。

------
#### [ Console ]

**レイヤーを作成するには (コンソール)**

1. Lambda コンソールの [[Layers (レイヤー)] ページ](https://console.aws.amazon.com/lambda/home#/layers)を開きます。

1. [**Create layer**] (レイヤーの作成) を選択します。

1. **[.zip ファイルをアップロードする]**を選択し、前の手順で作成しておいた .zip アーカイブをアップロードします。

1. (オプション) **[互換性のあるランタイム]** では、 Java バージョンに対応する Java ランタイムを選択できます。

1. **[作成]** を選択します。

------

## レイヤーを関数に追加する
<a name="java-layer-adding"></a>

------
#### [ AWS CLI ]

レイヤーを関数にアタッチするには、[update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) AWS CLI コマンドを実行します。`--layers` パラメータには、レイヤー ARN を使用します。ARN はバージョンを指定する必要があります (`arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1` など)。詳細については、「[レイヤーとレイヤーバージョン](chapter-layers.md#lambda-layer-versions)」を参照してください。

```
aws lambda update-function-configuration --function-name my-function --cli-binary-format raw-in-base64-out --layers "arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1"
```

AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。

------
#### [ Console ]

**関数にレイヤーを追加する方法**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 関数を選択します。

1. **[レイヤー]** セクションまで下にスクロールし、**[レイヤーの追加]** を選択します。

1. **[レイヤーの選択]** で **[カスタムレイヤー]** を選択し、レイヤーを指定します。
**注記**  
レイヤーの作成時に[互換性のあるランタイム](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)を追加しなかった場合、レイヤーはここには表示されません。代わりにレイヤー ARN を指定できます。

1. **[Add]** (追加) を選択します。

------

# Lambda Java 関数のシリアル化をカスタマイズ
<a name="java-custom-serialization"></a>

Lambda [Java マネージドランタイム](lambda-java.md#java-runtimes)は、JSON イベントのカスタムシリアル化をサポートしています。カスタムシリアル化はコードを簡素化し、パフォーマンスを向上させる可能性があります。

**Topics**
+ [カスタムシリアル化を使用する場合](#custom-serialization-use-cases)
+ [カスタムシリアル化の実装](#implement-custom-serialization)
+ [カスタムシリアル化のテスト](#test-custom-serialization)

## カスタムシリアル化を使用する場合
<a name="custom-serialization-use-cases"></a>

Lambda 関数を呼び出すと、入力イベントデータを Java オブジェクトに逆シリアル化し、関数からの出力を関数のレスポンスとして返すことができる形式にシリアル化する必要があります。Lambda Java マネージドランタイムは、Amazon API Gateway や Amazon Simple Queue Service (Amazon SQS) など、さまざまな AWS サービスからのイベントペイロードを処理するのに最適なデフォルトのシリアル化および逆シリアル化機能を提供します。関数でこれらのサービス統合イベントを使用するには、[aws-java-lambda-events](https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-events) の依存関係をプロジェクトに追加します。この AWS ライブラリには、これらのサービス統合イベントを表す Java オブジェクトが含まれています。

また、独自のオブジェクトを使用して、Lambda 関数に渡すイベント JSON を表すこともできます。マネージドランタイムは、JSON をデフォルトの動作でオブジェクトの新しいインスタンスにシリアル化しようとします。デフォルトのシリアライザーにユースケースに必要な動作がない場合は、カスタムシリアル化を使用します。

例えば、関数ハンドラーが、以下の構造で `Vehicle` クラスを入力として想定するとします:

```
public class Vehicle {
    private String vehicleType;
    private long vehicleId;
}
```

ただし、JSON イベントペイロードは以下のようになります:

```
{
    "vehicle-type": "car",
    "vehicleID": 123
}
```

このシナリオでは、マネージドランタイムのデフォルトのシリアル化により、JSON プロパティ名がキャメルケースの Java クラスプロパティ名 (`vehicleType`、`vehicleId`) と一致することが想定されます。JSON イベントのプロパティ名はキャメルケース (`vehicle-type`、`vehicleID`) にないため、カスタムシリアル化を使用する必要があります。

## カスタムシリアル化の実装
<a name="implement-custom-serialization"></a>

[サービスプロバイダーインターフェイス](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html)を使用して、マネージドランタイムのデフォルトのシリアル化ロジックではなく、選択したシリアライザーをロードします。標準 `RequestHandler` インターフェイスを使用して、JSON イベントペイロードを Java オブジェクトに直接シリアル化できます。

**Lambda Java 関数でカスタムシリアル化を使用するには**

1. [aws-lambda-java-core](https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-core) ライブラリを依存関係として追加します。このライブラリには、[CustomPojoSerializer](https://github.com/aws/aws-lambda-java-libs/blob/main/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CustomPojoSerializer.java) インターフェイスと、Lambda で Java を操作するための他のインターフェイス定義が含まれています。

1. プロジェクトの `src/main/resources/META-INF/services/` ディレクトリに `com.amazonaws.services.lambda.runtime.CustomPojoSerializer` という名前のファイルを作成します。

1. このファイルで、`CustomPojoSerializer` インターフェイスを実装する必要があるカスタムシリアライザー実装の完全修飾名を指定します。例:

   ```
   com.mycompany.vehicles.CustomLambdaSerialzer
   ```

1. `CustomPojoSerializer` インターフェイスを実装して、カスタムシリアル化ロジックを提供します。

1. Lambda 関数で標準 `RequestHandler` インターフェイスを使用します。マネージドランタイムは、カスタムシリアライザーを使用します。

fastJson 、Gson、Moshi、jackson-jr などの一般的なライブラリを使用してカスタムシリアル化を実装するその他の例については、「AWS GitHub リポジトリ」の「[custom-serialization](https://github.com/aws/aws-lambda-java-libs/tree/main/samples/custom-serialization)」のサンプルを参照してください。

## カスタムシリアル化のテスト
<a name="test-custom-serialization"></a>

関数をテストして、シリアル化ロジックと逆シリアル化ロジックが期待どおりに動作していることを確認します。AWS Serverless Application Model コマンドラインインターフェイス (AWS SAM CLI) を使用して、Lambda ペイロードの呼び出しをエミュレートできます。これにより、カスタムシリアライザーを導入する際に、関数ですばやくテストして反復処理できます。

1. 関数を呼び出す JSON イベントペイロードを使用してファイルを作成し、AWS SAM CLI を呼び出します。

1. [sam ローカル呼び出し](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html )コマンドを実行して、関数をローカルで呼び出します。例:

   ```
   sam local invoke -e src/test/resources/event.json
   ```

詳細については、「[AWS SAM を使用して Lambda 関数をローカルで呼び出し](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-invoke.html)」を参照してください。

# Lambda 関数の Java ランタイムの起動時の動作をカスタマイズする
<a name="java-customization"></a>

このページでは、AWS Lambda の Java 関数固有の設定について説明します。これらの設定を使用して、Java ランタイムの起動時の動作をカスタマイズできます。これにより、コードを変更することなく、関数全体のレイテンシを低下させ、関数全体のパフォーマンスを向上させることができます。

**Topics**
+ [`JAVA_TOOL_OPTIONS` 環境変数について](#java-tool-options)
+ [Log4Shell の Log4j パッチ](#log4shell-patch)
+ [Ahead-of-Time (AOT) キャッシュと CDS キャッシュ](#aot-cds-caches)

## `JAVA_TOOL_OPTIONS` 環境変数について
<a name="java-tool-options"></a>

Java を使用する場合、Lambda は追加のコマンドライン変数を設定するために、`JAVA_TOOL_OPTIONS` 環境変数をサポートします。この環境変数は、階層化コンパイル設定のカスタマイズなど、さまざまな方法で使用できます。次の例では、このユースケースで `JAVA_TOOL_OPTIONS` 環境変数を使用する方法を示します。

### 例: 階層型コンパイル設定のカスタマイズ
<a name="tiered-compilation"></a>

階層型コンパイルとは、Java 仮想マシン (JVM) の機能です。JVM のジャストインタイム (JIT) コンパイラを十分に活用するため、特定の階層型コンパイル設定を使用することができます。通常、C1 コンパイラは起動時間を短縮するように最適化されています。C2 コンパイラは、全体的なパフォーマンスを最大限に高めるように最適化されていますが、メモリの使用量が多く、処理に時間がかかります。階層型コンパイルには 5 つの異なるレベルがあります。レベル 0 では、JVM は Java バイトコードを解釈します。レベル 4 では、JVM は C2 コンパイラを使用して、アプリケーションの起動時に収集されたプロファイリングデータを分析します。時間の経過とともに、コードの使用状況を監視して最善の最適化方法を特定します。

階層型コンパイルのレベルをカスタマイズすると、Java 関数のパフォーマンスを調整するのに役立ちます。短時間で実行される小さな関数の場合、階層型コンパイルをレベル 1 に設定すると、JVM が C1 コンパイラを使用することによってコールドスタートの性能を向上させることができます。この設定は、最適化されたネイティブコードを迅速に生成しますが、プロファイリングデータは生成せず、C2 コンパイラも使用しません。大規模で計算負荷の高い関数の場合、階層型コンパイルをレベル 4 に設定することで、全体的なパフォーマンスを最大化できますが、その分メモリ使用量が増加し、各 Lambda 実行環境がプロビジョニングされた後の最初の呼び出し中に追加の最適化処理が発生します。

Java 11 およびそれ以前のランタイムの場合、Lambda はデフォルトの JVM 階層型コンパイル設定を使用します。Java 17 および Java 21 の場合、Lambda はデフォルトでレベル 1 で階層型コンパイルを停止するように JVM を設定します。Java 25 以降においても、Lambda はデフォルトで階層型コンパイルをレベル 1 で停止します。ただし、SnapStart またはプロビジョニングされた同時実行を使用する場合は、デフォルトの JVM 設定が使用されます。これらのケースでは階層型コンパイルが呼び出しパスの外部で実行されるため、コールドスタートのペナルティを発生させることなく、SnapStart とプロビジョニングされた同時実行のパフォーマンスを向上させます。この利点を最大化するには、プリミングを使用できます。これは、関数の初期化時にコードパスを実行して、SnapStart スナップショットを取得する前、または Provisioned Concurrency の実行環境が事前プロビジョニングされているときに JIT をトリガーできます。詳細については、ブログ記事「[Optimizing cold start performance of AWS Lambda using advanced priming strategies with SnapStart](https://aws.amazon.com/blogs/compute/optimizing-cold-start-performance-of-aws-lambda-using-advanced-priming-strategies-with-snapstart/)」を参照してください。

**階層型コンパイル設定をカスタマイズするには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 階層型コンパイルをカスタマイズする Java 関数を選択します。

1. **[設定]** タブを選択し、左側のメニューで **[環境変数]** を選択します。

1. **[編集]** を選択します。

1. **[環境変数の追加]** を選択します。

1.  [キー] に、`JAVA_TOOL_OPTIONS` と入力します。[値] に、`-XX:+TieredCompilation -XX:TieredStopAtLevel=1` と入力します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/java-tool-options-tiered-compilation.png)

1. **[保存]** を選択します。

**注記**  
Lambda SnapStart を使用して、コールドスタートの問題を軽減することもできます。SnapStartは、実行環境のキャッシュされたスナップショットを使用して、起動時のパフォーマンスを大幅に向上させます。SnapStartの機能、制限事項、サポートされているリージョンの詳細については、[Lambda SnapStart による起動パフォーマンスの向上](snapstart.md) を参照してください。

### 例: JAVA\$1TOOL\$1OPTIONS を使用した GC の動作のカスタマイズ
<a name="gc-behavior"></a>

Java 11 ランタイムは、ガベージコレクションに[シリアル](https://docs.oracle.com/en/java/javase/18/gctuning/available-collectors.html#GUID-45794DA6-AB96-4856-A96D-FDE5F7DEE498)ガベージコレクター (GC) を使用します。デフォルトでは、Java 17 ランタイムもシリアル GC を使用します。ただし、Java 17 では、`JAVA_TOOL_OPTIONS` 環境変数を使用してデフォルトの GC を変更することもできます。パラレル GC と [Shenandoah GC](https://wiki.openjdk.org/display/shenandoah/Main) のどちらかを選択できます。

例えば、ワークロードでより多くのメモリと複数の CPU を使用する場合は、パフォーマンス向上のためにパラレル GC の使用を検討してください。そのためには、`JAVA_TOOL_OPTIONS` 環境変数の値に以下の値を追加します。

```
-XX:+UseParallelGC
```

ワークロードに存続期間の短いオブジェクトが多数ある場合は、Java 25 で導入された Shenandoah ガベージコレクターの世代モードを有効にすることで、メモリ消費量を抑えられる可能性があります。このためには、`JAVA_TOOL_OPTIONS` 環境変数の値に以下の値を追加します。

```
-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
```

## Log4Shell の Log4j パッチ
<a name="log4shell-patch"></a>

Java 8、11、17、21 の Lambda ランタイムには、一般的な Java ログ記録フレームワークである Log4j の Log4Shell 脆弱性 (CVE-2021-44228) を軽減するためのパッチが含まれています。このパッチでは、コールドスタートの性能オーバーヘッドが発生します。パッチ適用されたバージョンの Log4j (バージョン 2.17.0 以降) を使用している場合は、このパッチを無効にすることでコールドスタートの性能を向上させることができます。このパッチを無効にするには、環境変数 `AWS_LAMBDA_DISABLE_CVE_2021_44228_PROTECTION` を `true` に設定します。

Java 25 以降、Lambda ランタイムには Log4Shell パッチが含まれなくなりました。Log4j バージョン 2.17.0 以降を使用していることを確認する必要があります。

## Ahead-of-Time (AOT) キャッシュと CDS キャッシュ
<a name="aot-cds-caches"></a>

Java 25 以降、Lambda ランタイムには、Java ランタイムインターフェイスクライアント (RIC) の Ahead-of-Time (AOT) キャッシュが含まれています。RIC は、Lambda Runtime API からのイベントをアクティブにポーリングするランタイムコンポーネントです。これにより、コールドスタートの性能を向上させることができます。

AOT キャッシュは JVM ビルドに固有です。Lambda がマネージドランタイムを更新すると、RIC の AOT キャッシュも更新されます。ただし、ユーザーが独自の AOT キャッシュをデプロイすると、それらが無効になったり、ランタイムの更新後に予期しない動作が発生する可能性があります。したがって、マネージドランタイムを使用する場合は AOT キャッシュを使用しないことを強くお勧めします。AOT キャッシュを使用するには、コンテナイメージを使用して関数をデプロイする必要があります。

AOT キャッシュは、Class Data Sharing (CDS) キャッシュでは使用できません。Lambda 関数に CDS キャッシュをデプロイすると、Lambda は AOT キャッシュを無効にします。

# Lambda コンテキストオブジェクトを使用して Java 関数の情報を取得する
<a name="java-context"></a>

Lambda で関数が実行されると、コンテキストオブジェクトが[ハンドラー](java-handler.md)に渡されます。このオブジェクトは、呼び出し、関数、および実行関数に関する情報を示すメソッドおよびプロパティを提供します。

**context メソッド**
+ `getRemainingTimeInMillis()` － 実行がタイムアウトするまでの残りのミリ秒数を返します。
+ `getFunctionName()` － Lambda 関数の名前を返します。
+ `getFunctionVersion()` － 関数の[バージョン](configuration-versions.md)を返します。
+ `getInvokedFunctionArn()` － この関数を呼び出すために使用される Amazon リソースネーム (ARN) を返します。呼び出し元でバージョン番号またはエイリアスが指定されているかどうかを示します。
+ `getMemoryLimitInMB()` － 関数に割り当てられたメモリの量を返します。
+ `getAwsRequestId()` － 呼び出しリクエストの ID を返します。
+ `getLogGroupName()` － 関数のロググループを返します。
+ `getLogStreamName()` － 関数インスタンスのログストリームを返します。
+ `getIdentity()` － (モバイルアプリ) リクエストを承認した Amazon Cognito ID に関する情報を返します。
+ `getClientContext()` － (モバイルアプリ) クライアントアプリケーションから Lambda に提供されるクライアントコンテキストを返します。
+ `getLogger()` － 関数の[ロガーオブジェクト](java-logging.md)を返します。

以下の例では、コンテキストオブジェクトを使用して Lambda ロガーにアクセスする関数を示しています。

**Example [Handler.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/main/java/example/Handler.java)**  

```
package example;

import [com.amazonaws.services.lambda.runtime.Context](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java);
import [com.amazonaws.services.lambda.runtime.LambdaLogger](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java);
import [com.amazonaws.services.lambda.runtime.RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java);

import java.util.Map;

// Handler value: example.Handler
public class Handler implements RequestHandler<Map<String,String>, Void>{

  @Override
  public Void handleRequest(Map<String,String> event, Context context)
  {
    LambdaLogger logger = context.getLogger();
    logger.log("EVENT TYPE: " + event.getClass());
    return null;
  }
}
```

関数は、`null` を返す前に受信イベントのクラスタイプをログに記録します。

**Example ログ出力**  

```
EVENT TYPE: class java.util.LinkedHashMap
```

コンテキストオブジェクトのインターフェイスは [aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) ライブラリに含まれています。このインターフェイスを実装して、テスト用のコンテキストクラスを作成できます。以下の例では、ほとんどのプロパティのダミー値を返すコンテキストクラス、およびテスト用のロガーを示しています。

**Example [src/test/java/example/TestContext.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/test/java/example/TestContext.java)**  

```
package example;

import [com.amazonaws.services.lambda.runtime.Context](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java);
import [com.amazonaws.services.lambda.runtime.CognitoIdentity](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java);
import [com.amazonaws.services.lambda.runtime.ClientContext](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/ClientContext.java);
import [com.amazonaws.services.lambda.runtime.LambdaLogger](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java);

public class TestContext implements Context{

  public TestContext() {}
  public String getAwsRequestId(){
    return new String("495b12a8-xmpl-4eca-8168-160484189f99");
  }
  public String getLogGroupName(){
    return new String("/aws/lambda/my-function");
  }
  public String getLogStreamName(){
    return new String("2020/02/26/[$LATEST]704f8dxmpla04097b9134246b8438f1a");
  }
  public String getFunctionName(){
    return new String("my-function");
  }
  public String getFunctionVersion(){
    return new String("$LATEST");
  }
  public String getInvokedFunctionArn(){
    return new String("arn:aws:lambda:us-east-2:123456789012:function:my-function");
  }
  public CognitoIdentity getIdentity(){
    return null;
  }
  public ClientContext getClientContext(){
    return null;
  }
  public int getRemainingTimeInMillis(){
    return 300000;
  }
  public int getMemoryLimitInMB(){
    return 512;
  }
  public LambdaLogger getLogger(){
    return new TestLogger();
  }

}
```

ログ記録の詳細については、「」を参照してください[Java Lambda 関数のログ記録とモニタリング](java-logging.md)

## サンプルアプリケーションのコンテキスト
<a name="java-context-samples"></a>

このガイドの GitHub リポジトリには、コンテキストオブジェクトの使用方法を示すサンプルアプリケーションが含まれています。各サンプルアプリケーションには、簡易のデプロイとクリーンアップ用のスクリプト、AWS Serverless Application Model (AWS SAM) テンプレート、サポートリソースが含まれています。

**Java のサンプル Lambda アプリケーション**
+ [example-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/example-java) – Lambda を使用して注文処理を行う Java 関数。この関数は、カスタム入力イベントオブジェクトの定義と逆シリアル化、 AWS SDK の使用方法、および出力ログ記録の方法を示しています。
+ [java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。
+ [java-events](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events) - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの [aws-lambda-java-events](java-package.md) ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。
+ [s3-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java) － Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。
+ [layer-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-java) – Lambda レイヤーを使用して、コアとなる関数コードから分離して依存関係をパッケージ化する方法を示す Java 関数。

# Java Lambda 関数のログ記録とモニタリング
<a name="java-logging"></a>

AWS Lambda は、Lambda 関数を自動的にモニタリングし、Amazon CloudWatch にログエントリを送信します。Lambda 関数には、関数のインスタンスごとに CloudWatch Logs ロググループとログストリームが用意されています。Lambda のランタイム環境は、各呼び出しの詳細や、関数のコードからのその他の出力をログストリームに送信します。CloudWatch Logs の詳細については、「[Lambda 関数ログを CloudWatch Logs に送信する](monitoring-cloudwatchlogs.md)」を参照してください。

関数コードからログを出力するには、「[java.lang.System](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html)」のメソッドを使用するか、stdout または stderr に書き込む任意のログ記録モジュールを使用できます。

**Topics**
+ [ログを返す関数の作成](#java-logging-output)
+ [Java での Lambda の高度なログ記録コントロールの使用](#java-logging-advanced)
+ [Log4j2 および SLF4J による高度なログ記録の実装](#java-logging-log4j2)
+ [他のログ記録ツールとライブラリの使用](#java-tools-libraries)
+ [AWS Lambda (Java) に Powertools の使用、構造化されたログ記録に AWS SAM の使用](#java-logging-sam)
+ [Lambda コンソールでログを表示する](#java-logging-console)
+ [CloudWatch コンソールでの ログの表示](#java-logging-cwconsole)
+ [AWS Command Line Interface (AWS CLI) を使用してログを表示する](#java-logging-cli)
+ [ログの削除](#java-logging-delete)
+ [サンプルログ記録コード](#java-logging-samples)

## ログを返す関数の作成
<a name="java-logging-output"></a>

関数コードからログを出力するには、[java.lang.System](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html) のメソッドを使用するか、`stdout` や `stderr` に書き込む任意のログ記録モジュールを使用できます。[aws-lambda-java-core](java-package.md) ライブラリには、コンテキストオブジェクトからアクセスできる `LambdaLogger` という名前のロガークラスが用意されています。ロガークラスは複数行のログをサポートしています。

以下の例では、コンテキストオブジェクトによって提供される `LambdaLogger` ロガーを使用しています。

**Example Handler.java**  

```
// Handler value: example.Handler
public class Handler implements RequestHandler<Object, String>{
  Gson gson = new GsonBuilder().setPrettyPrinting().create();
  @Override
  public String handleRequest(Object event, Context context)
  {
    LambdaLogger logger = context.getLogger();
    String response = new String("SUCCESS");
    // 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));
    return response;
  }
}
```

**Example ログの形式**  

```
START RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 Version: $LATEST
ENVIRONMENT VARIABLES: 
{
    "_HANDLER": "example.Handler",
    "AWS_EXECUTION_ENV": "AWS_Lambda_java8",
    "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "512",
    ...
}
CONTEXT: 
{
    "memoryLimit": 512,
    "awsRequestId": "6bc28136-xmpl-4365-b021-0ce6b2e64ab0",
    "functionName": "java-console",
    ...
}
EVENT:
{
  "records": [
    {
      "messageId": "19dd0b57-xmpl-4ac1-bd88-01bbb068cb78",
      "receiptHandle": "MessageReceiptHandle",
      "body": "Hello from SQS!",
       ...
    }
  ]
}
END RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0
REPORT RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0	Duration: 198.50 ms	Billed Duration: 724 ms	Memory Size: 512 MB	Max Memory Used: 90 MB	Init Duration: 524.75 ms
```

Java ランタイムは、呼び出しごとに `START`、`END`、および `REPORT` の各行を記録します。レポート行には、次の詳細が示されます。

**REPORT 行のデータフィールド**
+ **RequestId** － 呼び出しの一意のリクエスト ID。
+ **所要時間** － 関数のハンドラーメソッドがイベントの処理に要した時間。
+ **課金期間** － 呼び出しの課金対象の時間。
+ **メモリサイズ** － 関数に割り当てられたメモリの量。
+ **使用中の最大メモリ** － 関数によって使用されているメモリの量。呼び出しが実行環境を共有すると、Lambda はすべての呼び出しで使用される最大メモリを報告します。この動作により、予想よりも高い報告値が発生する可能性があります。
+ **初期所要時間** － 最初に処理されたリクエストについて、ハンドラーメソッド外で関数をロードしてコードを実行するためにランタイムにかかった時間。
+ **XRAY TraceId** － トレースされたリクエストの場合、[AWS X-Ray のトレース ID](services-xray.md)。
+ **SegmentId** － トレースされたリクエストの場合、X-Ray のセグメント ID。
+ **サンプリング済み** － トレースされたリクエストの場合、サンプリング結果。

## Java での Lambda の高度なログ記録コントロールの使用
<a name="java-logging-advanced"></a>

関数のログのキャプチャ、処理、利用方法をより細かく制御できるように、サポートされている Java ランタイムに以下のログ記録オプションを設定できます。
+ **ログの形式** - 関数のログをプレーンテキスト形式と構造化された JSON 形式から選択します
+ **ログレベル** - JSON 形式のログの場合、Lambda が CloudWatch に送信するログの詳細レベル (ERROR、DEBUG、INFO など) を選択します。
+ **ロググループ** - 関数がログを送信する CloudWatch ロググループを選択します

これらのログ記録オプションの詳細と、それらのオプションを使用するように関数を設定する方法については、「[Lambda 関数の高度なログ記録コントロールの設定](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)」を参照してください。

Java Lambda 関数でログ形式とログレベルのオプションを使用するには、以下のセクションのガイダンスを参照してください。

### Java での構造化された JSON ログ形式の使用
<a name="java-logging-advanced-JSON"></a>

関数のログ形式に JSON を選択した場合、Lambda は `LambdaLogger` クラスを使用してログ出力を構造化された JSON として送信します。各 JSON ログオブジェクトには、以下のキーを含む少なくとも 4 つのキーと値のペアが含まれます。
+ `"timestamp"` - ログメッセージが生成された時刻
+ `"level"` - メッセージに割り当てられたログレベル
+ `"message"` - ログメッセージの内容
+ `"AWSrequestId"` - 関数呼び出しの一意のリクエスト ID

使用するログ記録方法によっては、JSON 形式でキャプチャされた関数からのログ出力に、追加のキーと値のペアが含まれる場合もあります。

`LambdaLogger` ロガーを使用して作成するログにレベルを割り当てるには、次の例に示すように、ログコマンドに `LogLevel` 引数を指定する必要があります。

**Example Java ログ記録コード**  

```
LambdaLogger logger = context.getLogger();
logger.log("This is a debug log", LogLevel.DEBUG);
```

このサンプルコードのログ出力は、次のように CloudWatch Logs にキャプチャされます。

**Example JSON ログレコード**  

```
{
    "timestamp":"2023-11-01T00:21:51.358Z",
    "level":"DEBUG",
    "message":"This is a debug log",
    "AWSrequestId":"93f25699-2cbf-4976-8f94-336a0aa98c6f"
}
```

ログ出力にレベルを割り当てない場合、Lambda は自動的に INFO レベルを割り当てます。

コードで既に別のログ記録ライブラリを使用して JSON 構造化ログを作成している場合、変更を加える必要はありません。Lambda は、既に JSON でエンコードされているログを二重エンコードしません。JSON ログ形式を使用するように関数を設定しても、ログ記録出力は定義した JSON 構造で CloudWatch に表示されます。

### Java でのログレベルフィルタリングの使用
<a name="java-logging-advanced-levels"></a>

AWS Lambda でログレベルに従ってアプリケーションログをフィルタリングするには、関数で JSON 形式のログを使用する必要があります。このためには以下の 2 つの方法があります。
+ 標準的な `LambdaLogger` を使用してログ出力を作成し、JSON ログ形式を使用するように関数を設定する。次に、Lambda は、「[Java での構造化された JSON ログ形式の使用](#java-logging-advanced-JSON)」で説明されている JSON オブジェクトの「level」キーと値のペアを使用してログ出力をフィルタリングします。関数のログ形式を設定する方法については、「[Lambda 関数の高度なログ記録コントロールの設定](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)」を参照してください。
+ 別のログ記録ライブラリまたはメソッドを使用して、ログ出力のレベルを定義する「level」キーと値のペアを含む JSON 構造化ログをコード内に作成する。`stdout` または `stderr` に JSON ログの書き込みを行う任意のログ記録ライブラリを使用できます。例えば、Powertools for AWS Lambda または Log4j2 パッケージを使用して、コードから JSON 構造化ログ出力を生成できます。詳細については、「[AWS Lambda (Java) に Powertools の使用、構造化されたログ記録に AWS SAM の使用](#java-logging-sam)」および「[Log4j2 および SLF4J による高度なログ記録の実装](#java-logging-log4j2)」を参照してください。

ログレベルのフィルタリングを使用するように関数を設定する場合、Lambda が CloudWatch Logs に送信するログのレベルを以下のオプションから選択する必要があります。


| ログレベル | 標準的な使用状況 | 
| --- | --- | 
| TRACE (最も詳細) | コードの実行パスを追跡するために使用される最も詳細な情報 | 
| DEBUG | システムデバッグの詳細情報 | 
| 情報 | 関数の通常の動作を記録するメッセージ | 
| WARN | 対処しないと予期しない動作を引き起こす可能性がある潜在的なエラーに関するメッセージ | 
| エラー | コードが期待どおりに動作しなくなる問題に関するメッセージ | 
| FATAL (詳細度が最も低い) | アプリケーションの機能停止を引き起こす重大なエラーに関するメッセージ | 

Lambda で関数のログをフィルタリングするには、JSON ログ出力に `"timestamp"` のキーと値のペアも含める必要があります。時間は、有効な [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) タイムスタンプ形式で指定する必要があります。有効なタイムスタンプを指定しない場合、Lambda はログに INFO レベルを割り当ててタイムスタンプを追加します。

Lambda は、選択したレベル以下のログを CloudWatch に送信します。例えば、ログレベルを WARN に設定すると、Lambda は WARN、ERROR、FATAL の各レベルに対応するログを送信します。

## Log4j2 および SLF4J による高度なログ記録の実装
<a name="java-logging-log4j2"></a>

**注記**  
 AWS Lambda では、そのマネージドランタイムとベースコンテナイメージに Log4j2 が含まれていません。このため、これらは CVE-2021-44228、CVE-2021-45046、および CVE-2021-45105 で説明されている問題の影響を受けません。  
 お客様の関数に影響を受ける Log4j2 バージョンが含まれているという場合のため、CVE-2021-44228、CVE-2021-45046、および CVE-2021-45105 の問題の緩和に役立つ変更を Lambda Java [マネージドランタイム](lambda-runtimes.md)と[ベースコンテナイメージ](java-image.md)に適用しました。この変更の結果、Log4J2 を使用しているお客様には、「`Transforming org/apache/logging/log4j/core/lookup/JndiLookup (java.net.URLClassLoader@...)`」のような追加のログエントリが表示される場合があります。Log4J2 出力の jndi マッパーを参照するログ文字列は、いずれも「`Patched JndiLookup::lookup()`」に置き換えられます。  
 この変更にかかわらず、Log4j2 が含まれる関数を持つすべてのお客様に、最新バージョンへの更新を強くお勧めします。特に、関数で aws-lambda-java-log4j2 ライブラリを使用しているお客様は、バージョン 1.5.0 (またはそれ以降) に更新して、関数を再デプロイするようにしてください。このバージョンは、基盤となる Log4j2 ユーティリティの依存関係をバージョン 2.17.0 (またはそれ以降) に更新します。更新された aws-lambda-java-log4j2 バイナリは [Maven リポジトリ](https://repo1.maven.org/maven2/com/amazonaws/aws-lambda-java-log4j2/)で、そのソースコードは [GitHub](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2) で入手できます。  
 最後に、**aws-lambda-java-log4j (v1.0.0 または 1.0.1)** に関連するライブラリは、**いかなる**状況でも使用すべきでは**ない**ことに注意してください。これらのライブラリは 2015 年にサポートが終了した log4j のバージョン 1.x に関連しています。これらのライブラリはサポートも保守もパッチも適用されておらず、既知のセキュリティの脆弱性があります。

ログ出力をカスタマイズし、ユニットテスト中のログ記録をサポートし、AWS SDK 呼び出しをログに記録するには、SLF4J で Apache Log4j2 を使用します。Log4j は、ログレベルを設定し、アペンダーライブラリを使用できるようにする Java プログラムのログ記録ライブラリです。SLF4J は、関数コードを変更せずに使用するライブラリを切り替えることができるファサードライブラリです。

関数のログにリクエスト ID を追加するには、[aws-lambda-java-log4j2](java-package.md) ライブラリのアペンダーを使用します。

**Example [src/main/resources/log4j2.xml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java/src/main/resources/log4j2.xml) － アペンダー設定**  

```
<Configuration>
  <Appenders>
    <Lambda name="Lambda" format="${env:AWS_LAMBDA_LOG_FORMAT:-TEXT}">
       <LambdaTextFormat>
         <PatternLayout>
             <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n </pattern>
         </PatternLayout>
       </LambdaTextFormat>
       <LambdaJSONFormat>
         <JsonTemplateLayout eventTemplateUri="classpath:LambdaLayout.json" />
       </LambdaJSONFormat>
     </Lambda>
   </Appenders>
   <Loggers>
     <Root level="${env:AWS_LAMBDA_LOG_LEVEL:-INFO}">
       <AppenderRef ref="Lambda"/>
     </Root>
     <Logger name="software.amazon.awssdk" level="WARN" />
     <Logger name="software.amazon.awssdk.request" level="DEBUG" />
   </Loggers>
 </Configuration>
```

Log4j2 ログをプレーンテキスト出力または JSON 出力用に設定する方法は、`<LambdaTextFormat>` および `<LambdaJSONFormat>` タグの下にレイアウトを指定することで決定できます。

この例では、テキストモードで、各行の先頭に日付、時刻、リクエスト ID、ログレベル、クラス名が追加されます。JSON モードでは、`<JsonTemplateLayout>` が `aws-lambda-java-log4j2` ライブラリに付属する設定で使用されます。

SLF4J は、Java コードでのログ記録のためのファサードライブラリです。関数コードで、SLF4J ロガーファクトリを使用して、`info()` や `warn()` などのログレベルのメソッドにより、ロガーを取得します。ビルド設定で、ログ記録ライブラリと SLF4J アダプターをクラスパスに含めます。ビルド設定のライブラリを変更することで、関数コードを変更せずにロガータイプを切り替えることができます。SDK for Java からログをキャプチャするには SLF4J が必要です。

以下のサンプルコードでは、ハンドラークラスは SLF4J を使用してロガーを取得しています。

**Example [src/main/java/example/HandlerS3.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events/src/main/java/example/HandlerS3.java) - SLF4J を使用したログ記録**  

```
package example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;

import static org.apache.logging.log4j.CloseableThreadContext.put;


public class HandlerS3 implements RequestHandler<S3Event, String>{
    private static final Logger logger = LoggerFactory.getLogger(HandlerS3.class);

    @Override
    public String handleRequest(S3Event event, Context context) {
        for(var record : event.getRecords()) {
            try (var loggingCtx = put("awsRegion", record.getAwsRegion())) {
                loggingCtx.put("eventName", record.getEventName());
                loggingCtx.put("bucket", record.getS3().getBucket().getName());
                loggingCtx.put("key", record.getS3().getObject().getKey());

                logger.info("Handling s3 event");
            }
        }

        return "Ok";
    }
}
```

このコードにより以下のようなログ出力が生成されます。

**Example ログの形式**  

```
{
    "timestamp": "2023-11-15T16:56:00.815Z",
    "level": "INFO",
    "message": "Handling s3 event",
    "logger": "example.HandlerS3",
    "AWSRequestId": "0bced576-3936-4e5a-9dcd-db9477b77f97",
    "awsRegion": "eu-south-1",
    "bucket": "java-logging-test-input-bucket",
    "eventName": "ObjectCreated:Put",
    "key": "test-folder/"
}
```

ビルド設定では、Lambda アペンダーおよび SLF4J アダプターのランタイム依存関係と、Log4j2 の実装依存関係を使用します。

**Example build.gradle － 依存関係のログ記録**  

```
dependencies {
    ...
    'com.amazonaws:aws-lambda-java-log4j2:[1.6.0,)',
    'com.amazonaws:aws-lambda-java-events:[3.11.3,)',
    'org.apache.logging.log4j:log4j-layout-template-json:[2.17.1,)',
    'org.apache.logging.log4j:log4j-slf4j2-impl:[2.19.0,)',
    ...
}
```

テスト用にローカルでコードを実行する場合、Lambda ロガーへのアクセスにコンテキストオブジェクトは使用できず、Lambda アペンダーが使用するリクエスト ID はありません。テスト設定の例については、次のセクションのサンプルアプリケーションを参照してください。

## 他のログ記録ツールとライブラリの使用
<a name="java-tools-libraries"></a>

[Powertools for AWS Lambda (Java)](https://docs.aws.amazon.com/powertools/java/) は、サーバーレスのベストプラクティスを実装し、デベロッパーの作業速度を向上させるためのデベロッパーツールキットです。[ログ記録ユーティリティ](https://docs.aws.amazon.com/powertools/java/latest/core/logging/)には、Lambda に最適化されたロガーを提供し、すべての関数を通して関数コンテキストに関する追加情報が含まれ、JSON 形式で構成した出力を行います。このユーティリティを使用して次のことができます。
+ Lambda の コンテキスト、コールドスタート、構造から主要キーをキャプチャし、JSON 形式でログ出力する
+ 指示された場合 Lambda 呼び出しイベントをログ記録する (デフォルトでは無効)
+ ログサンプリングにより、特定の割合の呼び出しにのみすべてのログを出力する (デフォルトでは無効)
+ 任意のタイミングで、構造化されたログにキーを追加する
+ カスタムログフォーマッター (Bring Your Own Formatter) を使用して、組織の ログ記録 RFC と互換性のある構造でログを出力する

## AWS Lambda (Java) に Powertools の使用、構造化されたログ記録に AWS SAM の使用
<a name="java-logging-sam"></a>

以下の手順に従い、AWS SAM を使用する統合された [Powertools for AWS Lambda (Java)](https://docs.aws.amazon.com/powertools/java/latest/) モジュールを備えた Hello World Java アプリケーションのサンプルをダウンロード、構築、デプロイします。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は `hello world` のメッセージを返します。

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ Java 11
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ 「[AWS SAM CLI バージョン 1.75 以降](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」 AWS SAM CLI のバージョンが古い場合は、「[AWS SAM CLI のアップグレード](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)」を参照してください。

**AWS SAM サンプルアプリケーションをデプロイする**

1. Hello World Java テンプレートを使用してアプリケーションを初期化します。

   ```
   sam init --app-template hello-world-powertools-java --name sam-app --package-type Zip --runtime java11 --no-tracing
   ```

1. アプリケーションを構築します。

   ```
   cd sam-app && sam build
   ```

1. アプリケーションをデプロイします。

   ```
   sam deploy --guided
   ```

1. 画面に表示されるプロンプトに従ってください。インタラクティブな形式で提供されるデフォルトオプションを受け入れるには、`Enter` を押します。
**注記**  
**[HelloWorldFunction には権限が定義されていない場合がありますが、問題ありませんか？]** には、必ず `y` を入力してください。

1. デプロイされたアプリケーションの URL を取得します。

   ```
   aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
   ```

1. API エンドポイントを呼び出します。

   ```
   curl -X GET <URL_FROM_PREVIOUS_STEP>
   ```

   成功すると、次のレスポンスが表示されます。

   ```
   {"message":"hello world"}
   ```

1. 関数のログを取得するには、[sam logs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-logs.html) を実行します。詳細については、「*AWS Serverless Application Model デベロッパーガイド*」の「[ログの使用](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-logging.html)」を参照してください。

   ```
   sam logs --stack-name sam-app
   ```

   ログ出力は次のようになります。

   ```
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.095000 INIT_START Runtime Version: java:11.v15    Runtime Version ARN: arn:aws:lambda:eu-central-1::runtime:0a25e3e7a1cc9ce404bc435eeb2ad358d8fa64338e618d0c224fe509403583ca
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.114000 Picked up JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.793000 Transforming org/apache/logging/log4j/core/lookup/JndiLookup (lambdainternal.CustomerClassLoader@1a6c5a9e)
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:35.252000 START RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 Version: $LATEST
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.531000 {
     "_aws": {
       "Timestamp": 1675416276051,
       "CloudWatchMetrics": [
         {
           "Namespace": "sam-app-powerools-java",
           "Metrics": [
             {
               "Name": "ColdStart",
               "Unit": "Count"
             }
           ],
           "Dimensions": [
             [
               "Service",
               "FunctionName"
             ]
           ]
         }
       ]
     },
     "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765",
     "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1",
     "FunctionName": "sam-app-HelloWorldFunction-y9Iu1FLJJBGD",
     "functionVersion": "$LATEST",
     "ColdStart": 1.0,
     "Service": "service_undefined",
     "logStreamId": "2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81",
     "executionEnvironment": "AWS_Lambda_java11"
   }
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.974000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.AWSXRayRecorder <init>
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.config.DaemonConfiguration <init>
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 INFO: Environment variable AWS_XRAY_DAEMON_ADDRESS is set. Emitting to daemon on address XXXX.XXXX.XXXX.XXXX:2000.
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.331000 09:24:37.294 [main] INFO  helloworld.App - {"version":null,"resource":"/hello","path":"/hello/","httpMethod":"GET","headers":{"Accept":"*/*","CloudFront-Forwarded-Proto":"https","CloudFront-Is-Desktop-Viewer":"true","CloudFront-Is-Mobile-Viewer":"false","CloudFront-Is-SmartTV-Viewer":"false","CloudFront-Is-Tablet-Viewer":"false","CloudFront-Viewer-ASN":"16509","CloudFront-Viewer-Country":"IE","Host":"XXXX.execute-api.eu-central-1.amazonaws.com","User-Agent":"curl/7.86.0","Via":"2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q==","X-Amzn-Trace-Id":"Root=1-63dcd2d1-25f90b9d1c753a783547f4dd","X-Forwarded-For":"XX.XXX.XXX.XX, XX.XXX.XXX.XX","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"multiValueHeaders":{"Accept":["*/*"],"CloudFront-Forwarded-Proto":["https"],"CloudFront-Is-Desktop-Viewer":["true"],"CloudFront-Is-Mobile-Viewer":["false"],"CloudFront-Is-SmartTV-Viewer":["false"],"CloudFront-Is-Tablet-Viewer":["false"],"CloudFront-Viewer-ASN":["16509"],"CloudFront-Viewer-Country":["IE"],"Host":["XXXX.execute-api.eu-central-1.amazonaws.com"],"User-Agent":["curl/7.86.0"],"Via":["2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)"],"X-Amz-Cf-Id":["t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q=="],"X-Amzn-Trace-Id":["Root=1-63dcd2d1-25f90b9d1c753a783547f4dd"],"X-Forwarded-For":["XXX, XXX"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"accountId":"XXX","stage":"Prod","resourceId":"at73a1","requestId":"ba09ecd2-acf3-40f6-89af-fad32df67597","operationName":null,"identity":{"cognitoIdentityPoolId":null,"accountId":null,"cognitoIdentityId":null,"caller":null,"apiKey":null,"principalOrgId":null,"sourceIp":"54.240.197.236","cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,"userAgent":"curl/7.86.0","user":null,"accessKey":null},"resourcePath":"/hello","httpMethod":"GET","apiId":"XXX","path":"/Prod/hello/","authorizer":null},"body":null,"isBase64Encoded":false}
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.351000 09:24:37.351 [main] INFO  helloworld.App - Retrieving https://checkip.amazonaws.com
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.313000 {
     "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765",
     "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1",
     "xray_trace_id": "1-63dcd2d1-25f90b9d1c753a783547f4dd",
     "functionVersion": "$LATEST",
     "Service": "service_undefined",
     "logStreamId": "2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81",
     "executionEnvironment": "AWS_Lambda_java11"
   }
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 END RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765
   2025/09/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 REPORT RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765    Duration: 4118.98 ms    Billed Duration: 5275 ms    Memory Size: 512 MB    Max Memory Used: 152 MB    Init Duration: 1155.47 ms    
   XRAY TraceId: 1-63dcd2d1-25f90b9d1c753a783547f4dd    SegmentId: 3a028fee19b895cb    Sampled: true
   ```

1. これは、インターネット経由でアクセス可能なパブリック API エンドポイントです。テスト後にエンドポイントを削除することを推奨します。

   ```
   sam delete
   ```

### ログ保持の管理
<a name="java-log-retention"></a>

関数を削除しても、ロググループは自動的には削除されません。ログを無期限に保存しないようにするには、ロググループを削除するか、CloudWatch がログを自動的に削除するまでの保持期間を設定します。ログ保持を設定するには、AWS SAM テンプレートに以下を追加します。

```
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      # Omitting other properties

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/${HelloWorldFunction}"
      RetentionInDays: 7
```

## Lambda コンソールでログを表示する
<a name="java-logging-console"></a>

Lambda コンソールを使用して、Lambda 関数を呼び出した後のログ出力を表示できます。

組み込み **Code** エディタからコードがテスト可能である場合、**[実行結果]** でログを確認できます。コンソールのテスト機能を使用して関数を呼び出すと、**[詳細]** セクションで **[ログ出力]** を確認できます。

## CloudWatch コンソールでの ログの表示
<a name="java-logging-cwconsole"></a>

Amazon CloudWatch コンソールを使用して、すべての Lambda 関数呼び出しのログを表示できます。

**CloudWatch コンソールでログを表示するには**

1. CloudWatch コンソールの [[Log groups (ロググループ)] ページ](https://console.aws.amazon.com/cloudwatch/home?#logs:)を開きます。

1. 機能のロググループを選択します( **/aws/lambda/*関数名***)

1. ログストリームを選択します

各ログストリームは、[関数のインスタンス](lambda-runtime-environment.md)に相当します。ログストリームは、Lambda 関数を更新したとき、および同時呼び出しを処理するために追加のインスタンスが作成されたときに表示されます。特定の呼び出しのログを検索するために、AWS X-Ray を使って関数をインストルメント化することをお勧めします。　 X-Ray は、リクエストとログストリームの詳細をトレースに記録します。

## AWS Command Line Interface (AWS CLI) を使用してログを表示する
<a name="java-logging-cli"></a>

AWS CLI は、コマンドラインシェルでコマンドを使用して AWS サービスとやり取りするためのオープンソースツールです。このセクションの手順を完了するには、[AWS CLIバージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) が必要です。

[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) および `--log-type` コマンドオプションを使用して、呼び出しのログを取得します。レスポンスには、`LogResult`フィールドが含まれ、このフィールドには、呼び出しから base64 コードされた最大 4 KB のログが含まれます。

**Example ログ ID を取得します**  
次の例は、`LogResult`という名前の関数の`my-function`フィールドから*ログ ID * を取得する方法を示しています。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
次のような出力が表示されます。  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example ログをデコードします**  
同じコマンドプロンプトで、`base64` ユーティリティを使用してログをデコードします。次の例は、`my-function`の base64 でエンコードされたログを取得する方法を示しています 。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。  
以下の出力が表示されます。  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64`このユーティリティは、Linux、macOS、および [ Windows の Ubuntu ](https://docs.microsoft.com/en-us/windows/wsl/install-win10) で使用できます。macOS ユーザーは、`base64 -D`を使用する必要があります 。

**Example get-logs.sh スクリプト**  
同じコマンドプロンプトで、次のスクリプトを使用して、最後の 5 つのログイベントをダウンロードします。このスクリプトは `sed` を使用して出力ファイルから引用符を削除し、ログが使用可能になるまで 15 秒待機します。この出力には Lambda からのレスポンスと、`get-log-events` コマンドからの出力が含まれます。  
次のコードサンプルの内容をコピーし、Lambda プロジェクトディレクトリに `get-logs.sh` として保存します。  
AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS および Linux (専用)**  
同じコマンドプロンプトで、macOS と Linux ユーザーが次のコマンドを実行して、スクリプトが実行可能であることを確認する必要があります。  

```
chmod -R 755 get-logs.sh
```

**Example 最後の 5 つのログイベントを取得します**  
同じコマンドプロンプトで、次のスクリプトを実行して、最後の 5 つのログイベントを取得します。  

```
./get-logs.sh
```
次のような出力が表示されます。  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## ログの削除
<a name="java-logging-delete"></a>

関数を削除しても、ロググループは自動的には削除されません。ログが無期限に保存されないようにするには、ロググループを削除するか、ログが自動的に削除されるまでの[保存期間を設定](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)します。

## サンプルログ記録コード
<a name="java-logging-samples"></a>

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

**Java のサンプル Lambda アプリケーション**
+ [example-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/example-java) – Lambda を使用して注文処理を行う Java 関数。この関数は、カスタム入力イベントオブジェクトの定義と逆シリアル化、 AWS SDK の使用方法、および出力ログ記録の方法を示しています。
+ [java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。
+ [java-events](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events) - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの [aws-lambda-java-events](java-package.md) ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。
+ [s3-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java) － Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。
+ [layer-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-java) – Lambda レイヤーを使用して、コアとなる関数コードから分離して依存関係をパッケージ化する方法を示す Java 関数。

`java-basic` サンプルアプリケーションは、ログ記録テストをサポートする最小限のログ記録設定を示しています。ハンドラーコードは、コンテキストオブジェクトによって提供される `LambdaLogger` ロガーを使用します。テストでは、アプリケーションは、Log4j2 ロガーとの `LambdaLogger` インターフェイスを実装するカスタム `TestLogger` クラスを使用します。また、AWS SDK との互換性のためのファサードとして SLF4J を使用します。ログ記録ライブラリは、デプロイパッケージを小さく保つために、ビルド出力から除外しています。

# AWS Lambda での Java コードの作成
<a name="java-tracing"></a>

Lambda アプリケーションのトレース、デバッグ、および最適化を行うために、Lambda は AWS X-Ray と統合されています。X-Ray を使用すると、Lambda 関数や他の AWS のサービスが含まれるアプリケーション内で、リソースを横断するリクエストをトレースできます。

トレースされたデータを X-Ray に送信するには、以下の 2 つの SDK ライブラリのいずれかを使用します。
+ [AWS Distro for OpenTelemetry (ADOT)](https://aws.amazon.com/otel) – 安全で、本番環境に対応し、AWS でサポートされている OpenTelemetry (OTel) SDK のディストリビューションです。
+ [AWS X-Ray SDK for Java](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html) - トレースデータを生成して X-Ray に送信するための SDK です。
+ [Powertools for AWS Lambda (Java)](https://docs.aws.amazon.com/powertools/java/latest/) - サーバーレスのベストプラクティスを実装し、デベロッパーの作業速度を向上させるためのデベロッパーツールキットです。

各 SDK は、テレメトリデータを X-Ray サービスに送信する方法を提供します。続いて、X-Ray を使用してアプリケーションのパフォーマンスメトリクスの表示やフィルタリングを行い、インサイトを取得することで、問題点や最適化の機会を特定できます。

**重要**  
X-Ray および Powertools for AWS Lambda SDK は、AWS が提供する、密接に統合された計測ソリューションの一部です。ADOT Lambda レイヤーは、一般的により多くのデータを収集するトレーシング計測の業界標準の一部ですが、すべてのユースケースに適しているわけではありません。これらのソリューションのいずれかを使用して、X-Ray でエンドツーエンドのトレーシングを実装することができます。選択方法の詳細については、「[Choosing between the AWS Distro for Open Telemetry and X-Ray SDKs](https://docs.aws.amazon.com/xray/latest/devguide/xray-instrumenting-your-app.html#xray-instrumenting-choosing)」( Distro for Open Telemetry または X-Ray SDK の選択) を参照してください。

**Topics**
+ [AWS Lambda (Java) に Powertools の使用、トレースに AWS SAM の使用](#java-tracing-sam)
+ [AWS Lambda (Java) に Powertools の使用、トレースに AWS CDK の使用](#java-tracing-cdk)
+ [Java 関数の計測への ADOT の使用](#java-adot)
+ [Java 関数の計測のための X-Ray SDK の使用](#java-xray-sdk)
+ [Lambda コンソールを使用してトレースを有効化する](#java-tracing-console)
+ [Lambda API でのトレースのアクティブ化](#java-tracing-api)
+ [CloudFormation によるトレースのアクティブ化](#java-tracing-cloudformation)
+ [X-Ray トレースの解釈](#java-tracing-interpretation)
+ [ランタイムの依存関係をレイヤー (X-Ray SDK) に保存する](#java-tracing-layers)
+ [サンプルアプリケーションでの X-Ray トレース (X-Ray SDK)](#java-tracing-samples)

## AWS Lambda (Java) に Powertools の使用、トレースに AWS SAM の使用
<a name="java-tracing-sam"></a>

以下の手順に従い、AWS SAM を使用する統合された [Powertools for AWS Lambda (Java)](https://docs.powertools.aws.dev/lambda-java) モジュールを備えた Hello World Java アプリケーションのサンプルをダウンロード、構築、デプロイします。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は `hello world` のメッセージを返します。

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ Java 11 以降
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ 「[AWS SAM CLI バージョン 1.75 以降](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」 AWS SAM CLI のバージョンが古い場合は、「[AWS SAM CLI のアップグレード](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)」を参照してください。

**AWS SAM サンプルアプリケーションをデプロイする**

1. Hello World Java テンプレートを使用してアプリケーションを初期化します。

   ```
   sam init --app-template hello-world-powertools-java --name sam-app --package-type Zip --runtime java11 --no-tracing
   ```

1. アプリケーションを構築します。

   ```
   cd sam-app && sam build
   ```

1. アプリケーションをデプロイします。

   ```
   sam deploy --guided
   ```

1. 画面に表示されるプロンプトに従ってください。インタラクティブな形式で提供されるデフォルトオプションを受け入れるには、`Enter` を押します。
**注記**  
**[HelloWorldFunction には権限が定義されていない場合がありますが、問題ありませんか？]** には、必ず `y` を入力してください。

1. デプロイされたアプリケーションの URL を取得します。

   ```
   aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
   ```

1. API エンドポイントを呼び出します。

   ```
   curl -X GET <URL_FROM_PREVIOUS_STEP>
   ```

   成功すると、次のレスポンスが表示されます。

   ```
   {"message":"hello world"}
   ```

1. 関数のトレースを取得するには、[sam traces](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-traces.html) を実行します。

   ```
   sam traces
   ```

   トレース出力は次のようになります。

   ```
   New XRay Service Graph
     Start time: 2025-02-03 14:31:48+01:00
     End time: 2025-02-03 14:31:48+01:00
     Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-y9Iu1FLJJBGD - Edges: []
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 5.587
     Reference Id: 1 - client - sam-app-HelloWorldFunction-y9Iu1FLJJBGD - Edges: [0]
      Summary_statistics:
        - total requests: 0
        - ok count(2XX): 0
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0
   
   XRay Event [revision 3] at (2025-02-03T14:31:48.500000) with id (1-63dd0cc4-3c869dec72a586875da39777) and duration (5.603s)
    - 5.587s - sam-app-HelloWorldFunction-y9Iu1FLJJBGD [HTTP: 200]
    - 4.053s - sam-app-HelloWorldFunction-y9Iu1FLJJBGD
      - 1.181s - Initialization
      - 4.037s - Invocation
        - 1.981s - ## handleRequest
          - 1.840s - ## getPageContents
      - 0.000s - Overhead
   ```

1. これは、インターネット経由でアクセス可能なパブリック API エンドポイントです。テスト後にエンドポイントを削除することを推奨します。

   ```
   sam delete
   ```

## AWS Lambda (Java) に Powertools の使用、トレースに AWS CDK の使用
<a name="java-tracing-cdk"></a>

以下の手順に従い、AWS CDK を使用する統合された [Powertools for AWS Lambda (Java)](https://docs.powertools.aws.dev/lambda-java) モジュールを備えた Hello World Java アプリケーションのサンプルをダウンロード、構築、デプロイします。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は「hello world」メッセージを返します。

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ Java 11 以降
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK バージョン 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ 「[AWS SAM CLI バージョン 1.75 以降](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」 AWS SAM CLI のバージョンが古い場合は、「[AWS SAM CLI のアップグレード](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)」を参照してください。

**AWS CDK サンプルアプリケーションをデプロイする**

1. 新しいアプリケーション用のプロジェクトディレクトリを作成します。

   ```
   mkdir hello-world
   cd hello-world
   ```

1. アプリケーションを初期化します。

   ```
   cdk init app --language java
   ```

1. 次のコマンドを備えた Maven プロジェクトを作成します。

   ```
   mkdir app
   cd app
   mvn archetype:generate -DgroupId=helloworld -DartifactId=Function -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
   ```

1. `hello-world\app\Function` ディレクトリで `pom.xml` を開き、既存のコードを、Powertools の依存関係および Maven プラグインを含む次のコードで置き換えます。

   ```
   <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/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>helloworld</groupId>
     <artifactId>Function</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>Function</name>
     <url>http://maven.apache.org</url>
   <properties>
       <maven.compiler.source>11</maven.compiler.source>
       <maven.compiler.target>11</maven.compiler.target>
       <log4j.version>2.17.2</log4j.version>
   </properties>
       <dependencies>
           <dependency>
               <groupId>junit</groupId>
               <artifactId>junit</artifactId>
               <version>3.8.1</version>
               <scope>test</scope>
           </dependency>
           <dependency>
               <groupId>software.amazon.lambda</groupId>
               <artifactId>powertools-tracing</artifactId>
               <version>1.3.0</version>
           </dependency>
           <dependency>
               <groupId>software.amazon.lambda</groupId>
               <artifactId>powertools-metrics</artifactId>
               <version>1.3.0</version>
           </dependency>
           <dependency>
               <groupId>software.amazon.lambda</groupId>
               <artifactId>powertools-logging</artifactId>
               <version>1.3.0</version>
           </dependency>
           <dependency>
               <groupId>com.amazonaws</groupId>
               <artifactId>aws-lambda-java-core</artifactId>
               <version>1.2.2</version>
           </dependency>
           <dependency>
               <groupId>com.amazonaws</groupId>
               <artifactId>aws-lambda-java-events</artifactId>
               <version>3.11.1</version>
           </dependency>
     </dependencies>
   <build>
       <plugins>
           <plugin>
               <groupId>org.codehaus.mojo</groupId>
               <artifactId>aspectj-maven-plugin</artifactId>
               <version>1.14.0</version>
               <configuration>
                   <source>${maven.compiler.source}</source>
                   <target>${maven.compiler.target}</target>
                   <complianceLevel>${maven.compiler.target}</complianceLevel>
                   <aspectLibraries>
                       <aspectLibrary>
                           <groupId>software.amazon.lambda</groupId>
                           <artifactId>powertools-tracing</artifactId>
                       </aspectLibrary>
                       <aspectLibrary>
                           <groupId>software.amazon.lambda</groupId>
                           <artifactId>powertools-metrics</artifactId>
                       </aspectLibrary>
                       <aspectLibrary>
                           <groupId>software.amazon.lambda</groupId>
                           <artifactId>powertools-logging</artifactId>
                       </aspectLibrary>
                   </aspectLibraries>
               </configuration>
               <executions>
                   <execution>
                       <goals>
                           <goal>compile</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
           <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-shade-plugin</artifactId>
                   <version>3.4.1</version>
                   <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>
                               <createDependencyReducedPom>false</createDependencyReducedPom>
                               <finalName>function</finalName>
   
                           </configuration>
                       </execution>
                   </executions>
                   <dependencies>
                       <dependency>
                           <groupId>com.github.edwgiz</groupId>
                           <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
                           <version>2.15</version>
                       </dependency>
                   </dependencies>
           </plugin>
       </plugins>
   </build>
   </project>
   ```

1. `hello-world\app\src\main\resource` ディレクトリを作成し、ログ設定に `log4j.xml` を作成します。

   ```
   mkdir -p src/main/resource
   cd src/main/resource
   touch log4j.xml
   ```

1. `log4j.xml` を開いて次のコード追加します。

   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <Configuration>
       <Appenders>
           <Console name="JsonAppender" target="SYSTEM_OUT">
               <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" />
           </Console>
       </Appenders>
       <Loggers>
           <Logger name="JsonLogger" level="INFO" additivity="false">
               <AppenderRef ref="JsonAppender"/>
           </Logger>
           <Root level="info">
               <AppenderRef ref="JsonAppender"/>
           </Root>
       </Loggers>
   </Configuration>
   ```

1. `hello-world\app\Function\src\main\java\helloworld` ディレクトリから `App.java` を開き、既存コードを次のコードで置き換えます。これは Lambda 関数のコードです。

   ```
   package helloworld;
   
   import java.io.BufferedReader;
   import java.io.IOException;
   import java.io.InputStreamReader;
   import java.net.URL;
   import java.util.HashMap;
   import java.util.Map;
   import java.util.stream.Collectors;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
   import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
   import org.apache.logging.log4j.LogManager;
   import org.apache.logging.log4j.Logger;
   import software.amazon.lambda.powertools.logging.Logging;
   import software.amazon.lambda.powertools.metrics.Metrics;
   import software.amazon.lambda.powertools.tracing.CaptureMode;
   import software.amazon.lambda.powertools.tracing.Tracing;
   
   import static software.amazon.lambda.powertools.tracing.CaptureMode.*;
   
   /**
    * Handler for requests to Lambda function.
    */
   public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
       Logger log = LogManager.getLogger(App.class);
   
   
       @Logging(logEvent = true)
       @Tracing(captureMode = DISABLED)
       @Metrics(captureColdStart = true)
       public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
           Map<String, String> headers = new HashMap<>();
           headers.put("Content-Type", "application/json");
           headers.put("X-Custom-Header", "application/json");
   
           APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
                   .withHeaders(headers);
           try {
               final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
               String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
   
               return response
                       .withStatusCode(200)
                       .withBody(output);
           } catch (IOException e) {
               return response
                       .withBody("{}")
                       .withStatusCode(500);
           }
       }
       @Tracing(namespace = "getPageContents")
       private String getPageContents(String address) throws IOException {
           log.info("Retrieving {}", address);
           URL url = new URL(address);
           try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
               return br.lines().collect(Collectors.joining(System.lineSeparator()));
           }
       }
   }
   ```

1. `hello-world\src\main\java\com\myorg` ディレクトリから `HelloWorldStack.java` を開き、既存コードを次のコードで置き換えます。このコードは、「[Lambda Constructor](https://docs.aws.amazon.com/cdk/api/v1/java/aws_cdk.aws_lambda.html)」および「[Apigatewayv2 Constructor](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigatewayv2-readme.html)」を使用して REST API および Lambda 関数を作成します。

   ```
   package com.myorg;
   
   import software.amazon.awscdk.*;
   import software.amazon.awscdk.services.apigatewayv2.alpha.*;
   import software.amazon.awscdk.services.apigatewayv2.integrations.alpha.HttpLambdaIntegration;
   import software.amazon.awscdk.services.apigatewayv2.integrations.alpha.HttpLambdaIntegrationProps;
   import software.amazon.awscdk.services.lambda.Code;
   import software.amazon.awscdk.services.lambda.Function;
   import software.amazon.awscdk.services.lambda.FunctionProps;
   import software.amazon.awscdk.services.lambda.Runtime;
   import software.amazon.awscdk.services.lambda.Tracing;
   import software.amazon.awscdk.services.logs.RetentionDays;
   import software.amazon.awscdk.services.s3.assets.AssetOptions;
   import software.constructs.Construct;
   
   import java.util.Arrays;
   import java.util.List;
   
   import static java.util.Collections.singletonList;
   import static software.amazon.awscdk.BundlingOutput.ARCHIVED;
   
   public class HelloWorldStack extends Stack {
       public HelloWorldStack(final Construct scope, final String id) {
           this(scope, id, null);
       }
   
       public HelloWorldStack(final Construct scope, final String id, final StackProps props) {
           super(scope, id, props);
   
           List<String> functionPackagingInstructions = Arrays.asList(
                   "/bin/sh",
                   "-c",
                   "cd Function " +
                           "&& mvn clean install " +
                           "&& cp /asset-input/Function/target/function.jar /asset-output/"
           );
           BundlingOptions.Builder builderOptions = BundlingOptions.builder()
                   .command(functionPackagingInstructions)
                   .image(Runtime.JAVA_11.getBundlingImage())
                   .volumes(singletonList(
                           // Mount local .m2 repo to avoid download all the dependencies again inside the container
                           DockerVolume.builder()
                                   .hostPath(System.getProperty("user.home") + "/.m2/")
                                   .containerPath("/root/.m2/")
                                   .build()
                   ))
                   .user("root")
                   .outputType(ARCHIVED);
   
           Function function = new Function(this, "Function", FunctionProps.builder()
                   .runtime(Runtime.JAVA_11)
                   .code(Code.fromAsset("app", AssetOptions.builder()
                           .bundling(builderOptions
                                   .command(functionPackagingInstructions)
                                   .build())
                           .build()))
                   .handler("helloworld.App::handleRequest")
                   .memorySize(1024)
                   .tracing(Tracing.ACTIVE)
                   .timeout(Duration.seconds(10))
                   .logRetention(RetentionDays.ONE_WEEK)
                   .build());
   
           HttpApi httpApi = new HttpApi(this, "sample-api", HttpApiProps.builder()
                   .apiName("sample-api")
                   .build());
   
           httpApi.addRoutes(AddRoutesOptions.builder()
                   .path("/")
                   .methods(singletonList(HttpMethod.GET))
                   .integration(new HttpLambdaIntegration("function", function, HttpLambdaIntegrationProps.builder()
                           .payloadFormatVersion(PayloadFormatVersion.VERSION_2_0)
                           .build()))
                   .build());
   
           new CfnOutput(this, "HttpApi", CfnOutputProps.builder()
                   .description("Url for Http Api")
                   .value(httpApi.getApiEndpoint())
                   .build());
       }
   }
   ```

1. `hello-world` ディレクトリから `pom.xml` を開き、既存コードを次のコードで置き換えます。

   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
            xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <modelVersion>4.0.0</modelVersion>
   
       <groupId>com.myorg</groupId>
       <artifactId>hello-world</artifactId>
       <version>0.1</version>
   
       <properties>
           <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
           <cdk.version>2.70.0</cdk.version>
           <constructs.version>[10.0.0,11.0.0)</constructs.version>
           <junit.version>5.7.1</junit.version>
       </properties>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-compiler-plugin</artifactId>
                   <version>3.8.1</version>
                   <configuration>
                       <source>1.8</source>
                       <target>1.8</target>
                   </configuration>
               </plugin>
   
               <plugin>
                   <groupId>org.codehaus.mojo</groupId>
                   <artifactId>exec-maven-plugin</artifactId>
                   <version>3.0.0</version>
                   <configuration>
                       <mainClass>com.myorg.HelloWorldApp</mainClass>
                   </configuration>
               </plugin>
           </plugins>
       </build>
   
       <dependencies>
           <!-- AWS Cloud Development Kit -->
           <dependency>
               <groupId>software.amazon.awscdk</groupId>
               <artifactId>aws-cdk-lib</artifactId>
               <version>${cdk.version}</version>
           </dependency>
           <dependency>
               <groupId>software.constructs</groupId>
               <artifactId>constructs</artifactId>
               <version>${constructs.version}</version>
           </dependency>
           <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
             <version>${junit.version}</version>
             <scope>test</scope>
           </dependency>
           <dependency>
               <groupId>software.amazon.awscdk</groupId>
               <artifactId>apigatewayv2-alpha</artifactId>
               <version>${cdk.version}-alpha.0</version>
           </dependency>
           <dependency>
               <groupId>software.amazon.awscdk</groupId>
               <artifactId>apigatewayv2-integrations-alpha</artifactId>
               <version>${cdk.version}-alpha.0</version>
           </dependency>
       </dependencies>
   </project>
   ```

1. `hello-world` ディレクトリ内に移動していることを確認し、アプリケーションをデプロイしてください。

   ```
   cdk deploy
   ```

1. デプロイされたアプリケーションの URL を取得します。

   ```
   aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?OutputKey==`HttpApi`].OutputValue' --output text
   ```

1. API エンドポイントを呼び出します。

   ```
   curl -X GET <URL_FROM_PREVIOUS_STEP>
   ```

   成功すると、次のレスポンスが表示されます。

   ```
   {"message":"hello world"}
   ```

1. 関数のトレースを取得するには、[sam traces](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-traces.html) を実行します。

   ```
   sam traces
   ```

   トレース出力は次のようになります。

   ```
   New XRay Service Graph
     Start time: 2025-02-03 14:59:50+00:00
     End time: 2025-02-03 14:59:50+00:00
     Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [1]
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0.924
     Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: []
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0.016
     Reference Id: 2 - client - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [0]
      Summary_statistics:
        - total requests: 0
        - ok count(2XX): 0
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0
   
   XRay Event [revision 1] at (2025-02-03T14:59:50.204000) with id (1-63dd2166-434a12c22e1307ff2114f299) and duration (0.924s)
    - 0.924s - sam-app-HelloWorldFunction-YBg8yfYtOc9j [HTTP: 200]
    - 0.016s - sam-app-HelloWorldFunction-YBg8yfYtOc9j
      - 0.739s - Initialization
      - 0.016s - Invocation
        - 0.013s - ## lambda_handler
          - 0.000s - ## app.hello
      - 0.000s - Overhead
   ```

1. これは、インターネット経由でアクセス可能なパブリック API エンドポイントです。テスト後にエンドポイントを削除することを推奨します。

   ```
   cdk destroy
   ```

## Java 関数の計測への ADOT の使用
<a name="java-adot"></a>

ADOT は、Otel SDK を使用してテレメトリデータを収集するために必要なすべてをパッケージ化した、フルマネージド型の Lambda [レイヤー](chapter-layers.md)を提供します。このレイヤーを使用すると、関数コードを変更する必要はなしで、Lambda 関数を計測できます。また、このレイヤーは、OTel でのカスタムな初期化を実行するように構成することもできます。詳細については、ADOT のドキュメントの「[Custom configuration for the ADOT Collector on Lambda](https://aws-otel.github.io/docs/getting-started/lambda#custom-configuration-for-the-adot-collector-on-lambda)」(Lambda 上での ADOT Collector のカスタム設定) 参照してください。

Java ランタイムの場合、使用するレイヤーを以下の 2 つの中から選択できます。
+ **AWS ADOT Java 向けのマネージド Lambda レイヤー (自動計測エージェント)** – このレイヤーは、起動時に関数コードを自動的に変換し、トレーシングデータを収集できるようにします。このレイヤーを ADOT Java エージェントとともに使用する方法の詳細については、「ADOT ドキュメント」の「[AWS Distro for OpenTelemetry Lambda Support for Java (Auto-instrumentation Agent)](https://aws-otel.github.io/docs/getting-started/lambda/lambda-java-auto-instr)」を参照してください。
+ **ADOT Java 用の AWS マネージド型 Lambda レイヤー** – このレイヤーによっても、Lambda 関数の組み込み型の計測機能が提供されます。ただし、OTel SDK を初期化するために、手動によるコード変更がいくつか必要となります。このレイヤーを使用する方法の詳細については、「ADOT ドキュメント」の「[AWS Distro for OpenTelemetry Lambda Support for Java](https://aws-otel.github.io/docs/getting-started/lambda/lambda-java)」を参照してください。

## Java 関数の計測のための X-Ray SDK の使用
<a name="java-xray-sdk"></a>

関数が、アプリケーション内で他のリソースやサービスに対して行う呼び出しのデータを記録するには、X-Ray SDK for Java をビルド設定に追加します。以下に、AWS SDK for Java 2.x クライアントの自動計測をアクティブ化するライブラリを含む Gradle ビルド設定の例を示します。

**Example [build.gradle](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java/build.gradle) － 依存関係のトレース**  

```
dependencies {
    implementation platform('software.amazon.awssdk:bom:2.16.1')
    implementation platform('com.amazonaws:aws-xray-recorder-sdk-bom:2.11.0')
    ...
    implementation 'com.amazonaws:aws-xray-recorder-sdk-core'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-aws-sdk'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor'
    ...
}
```

正しい依存関係を追加し、必要なコード変更を行った後、Lambda コンソールまたはAPIを介して関数の構成でトレースをアクティブにします。

## Lambda コンソールを使用してトレースを有効化する
<a name="java-tracing-console"></a>

コンソールを使用して、Lambda 関数のアクティブトレースをオンにするには、次のステップに従います。

**アクティブトレースをオンにするには**

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. **[設定]** を選択してから、**[モニタリングおよび運用ツール]** を選択します。

1. **[その他の監視ツール]** で、**[編集]** を選択します。

1. **[CloudWatch Application Signals と AWS X-Ray]** で、**[Lambda サービストレース]** の **[有効]** を選択します。

1. **[保存]** を選択します。

## Lambda API でのトレースのアクティブ化
<a name="java-tracing-api"></a>

AWS CLI または AWS SDK で Lambda 関数のトレースを設定するには、次の API オペレーションを使用します。
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html)
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)

以下の例の AWS CLI コマンドは、**my-function** という名前の関数に対するアクティブトレースを有効にします。

```
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
```

トレースモードは、関数のバージョンを公開するときのバージョン固有の設定の一部です。公開後のバージョンのトレースモードを変更することはできません。

## CloudFormation によるトレースのアクティブ化
<a name="java-tracing-cloudformation"></a>

CloudFormation テンプレート内で `AWS::Lambda::Function` リソースに対するアクティブトレースを有効化するには、`TracingConfig` プロパティを使用します。

**Example [function-inline.yml](https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/templates/function-inline.yml) － トレース設定**  

```
Resources:
  function:
    Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
    Properties:
      TracingConfig:
        Mode: Active
      ...
```

AWS Serverless Application Model (AWS SAM) `AWS::Serverless::Function` リソースに、`Tracing` プロパティを使用します。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-nodejs/template.yml) － トレース設定**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Tracing: Active
      ...
```

## X-Ray トレースの解釈
<a name="java-tracing-interpretation"></a>

関数には、トレースデータを X-Ray にアップロードするためのアクセス許可が必要です。Lambda コンソールでトレースを有効にすると、Lambda は必要な権限を関数の [[実行ロール]](lambda-intro-execution-role.md) に追加します。それ以外の場合は、[AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess) ポリシーを実行ロールに追加します。

アクティブトレースの設定後は、アプリケーションを通じて特定のリクエストの観測が行えるようになります。[[X-Ray サービスグラフ]](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts-servicegraph) には、アプリケーションとそのすべてのコンポーネントに関する情報が表示されます。次の例は、2 つの関数を持つアプリケーションを示しています。プライマリ関数はイベントを処理し、エラーを返す場合があります。上位 2 番目の関数は、最初のロググループに表示されるエラーを処理し、AWS SDK を使用して X-Ray、Amazon Simple Storage Service (Amazon S3)、および Amazon CloudWatch Logs を呼び出します。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sample-errorprocessor-servicemap.png)


X-Ray は、アプリケーションへのすべてのリクエストをトレースするわけではありません。X-Ray は、サンプリングアルゴリズムを適用することで効率的なトレースを行うと同時に、すべてのリクエストについての代表的なサンプルを示します。サンプルレートは 1 秒あたり 1 回のリクエストで、追加リクエストの 5％ です。関数の X-Ray サンプルレートを設定することはできません。

X-Ray では、*トレース*は 1 つ以上の*サービス*によって処理されるリクエストに関する情報を記録します。Lambda はトレースごとに 2 つのセグメントを記録します。これにより、サービスグラフに 2 つのノードが作成されます。次の図は、これら 2 つのノードを強調表示しています。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/xray-servicemap-function.png)


左に示された 1 つめのノードは、呼び出しリクエストを受信する Lambda サービスを表しています。2 つめのノードは、特定の Lambda 関数を表しています。次の例は、これら 2 つのセグメントを使用したトレースを示しています。いずれも **my-function** と名付けられていますが、1 つは `AWS::Lambda` の起点があり、もう 1 つは `AWS::Lambda::Function` の起点があります。`AWS::Lambda` セグメントにエラーが表示される場合は、Lambda サービスに問題があります。`AWS::Lambda::Function` セグメントにエラーが表示される場合、関数に問題があります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


この例では、`AWS::Lambda::Function` セグメントを展開して、それの 3 つのサブセグメントが表示されています。

**注記**  
AWS は現在、Lambda サービスに変更を実装しています。これらの変更により、AWS アカウント のさまざまな Lambda 関数によって出力されるシステムログメッセージとトレースセグメントの構造と内容にわずかな違いが生じる場合があります。  
ここで示すトレースの例は、古いスタイルの関数セグメントを示しています。古いスタイルのセグメントと新しいスタイルのセグメントの違いについては、次の段落で説明します。  
これらの変更は今後数週間に実装され、中国および GovCloud リージョンを除くすべての AWS リージョンのすべての関数は、新しい形式のログメッセージとトレースセグメントを使用するように移行されます。

古いスタイルの関数セグメントには、次のサブセグメントが含まれます。
+ **初期化** － 関数のロードと[初期化コード](foundation-progmodel.md)の実行に要した時間を表します。このサブセグメントは、関数の各インスタンスが処理する最初のイベントに対してのみ表示されます。
+ **[呼び出し]** - ハンドラーコードの実行に要した時間を表します。
+ **[オーバーヘッド]** - Lambda ランタイムが次のイベントを処理するための準備に要する時間を表します。

新しいスタイルの関数セグメントには `Invocation` サブセグメントが含まれていません。代わりに、顧客サブセグメントが関数セグメントに直接アタッチされます。古いスタイルの関数セグメントと新しいスタイルの関数セグメントの構造の詳細については、「」を参照してください[X-Ray トレースを理解する](services-xray.md#services-xray-traces)。

**注記**  
[Lambda SnapStart](snapstart.md) 関数には `Restore` サブセグメントも含まれます。`Restore` サブセグメントは、Lambda がスナップショットを復元し、ランタイムをロードして、復元後の[ランタイムフック](snapstart-runtime-hooks.md)を実行するのにかかる時間を表しています。スナップショットを復元するプロセスには、MicroVM 外部でのアクティビティに費やす時間が含まれる場合があります。この時間は、`Restore` サブセグメントで報告されます。MicroVM 外部でスナップショットの復元に費やした時間については課金されません。

HTTP クライアントをインストルメント化し、SQL クエリを記録して、注釈とメタデータからカスタムサブセグメントを作成することもできます。詳細については、「*AWS X-Ray デベロッパーガイド*」の 「[AWS X-Ray SDK for Java](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html)」を参照してください。

**料金**  
X-Ray トレースは、毎月、AWS 無料利用枠で設定された一定限度まで無料で利用できます。X-Ray の利用がこの上限を超えた場合は、トレースによる保存と取得に対する料金が発生します。詳細については、「[AWS X-Ray 料金表](https://aws.amazon.com/xray/pricing/)」を参照してください。

## ランタイムの依存関係をレイヤー (X-Ray SDK) に保存する
<a name="java-tracing-layers"></a>

X-Ray SDK を使用して AWS SDK クライアントを関数コードに埋め込むと、デプロイパッケージが巨大になる可能性があります。機能コードを更新するたびに実行時の依存関係がアップロードされないようにするには、X-Ray SDK を [[Lambda layer]](chapter-layers.md) (Lambda レイヤー) にパッケージ化します。

以下の例では、AWS SDK for Java および X-Ray SDK for Java を保存する `AWS::Serverless::LayerVersion` リソースを示しています。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-java/template.yml) － 依存関係レイヤー**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      CodeUri: build/distributions/blank-java.zip
      Tracing: Active
      Layers:
        - !Ref libs
      ...
  libs:
    Type: [AWS::Serverless::LayerVersion](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html)
    Properties:
      LayerName: blank-java-lib
      Description: Dependencies for the blank-java sample app.
      ContentUri: build/blank-java-lib.zip
      CompatibleRuntimes:
        - java25
```

この設定では、ランタイム依存関係を変更した場合にのみ、ライブラリレイヤーの更新が必要です。関数のデプロイパッケージにはユーザーのコードのみが含まれるため、アップロード時間を短縮できます。

依存関係のレイヤーを作成するには、デプロイ前にレイヤーアーカイブを生成するようにビルド設定を変更する必要があります。実際の例については、GitHub のサンプルアプリケーション、[java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) を参照してください。

## サンプルアプリケーションでの X-Ray トレース (X-Ray SDK)
<a name="java-tracing-samples"></a>

このガイドで参照する GitHub リポジトリには、X-Ray トレースの使用方法を示すサンプルアプリケーションが含まれています。各サンプルアプリケーションには、簡易のデプロイとクリーンアップ用のスクリプト、AWS SAM テンプレート、サポートリソースが含まれています。

**Java のサンプル Lambda アプリケーション**
+ [example-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/example-java) – Lambda を使用して注文処理を行う Java 関数。この関数は、カスタム入力イベントオブジェクトの定義と逆シリアル化、 AWS SDK の使用方法、および出力ログ記録の方法を示しています。
+ [java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。
+ [java-events](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events) - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの [aws-lambda-java-events](java-package.md) ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。
+ [s3-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java) － Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。
+ [layer-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-java) – Lambda レイヤーを使用して、コアとなる関数コードから分離して依存関係をパッケージ化する方法を示す Java 関数。

すべてのサンプルアプリケーションでは、Lambda 関数に対するアクティブトレースが有効になっています。例えば、`s3-java` アプリケーションは、AWS SDK for Java 2.x クライアントの自動インストルメンテーション、テストのセグメント管理、カスタムのサブセグメント、Lambda レイヤーによるラインタイムの依存関係の保存を示しています。

# AWS Lambda の Java サンプルアプリケーション
<a name="java-samples"></a>

このガイドの GitHub リポジトリには、AWS Lambda での Java の使用方法を示すサンプルアプリケーションが用意されています。各サンプルアプリケーションには、簡易のデプロイとクリーンアップ用のスクリプト、CloudFormation テンプレート、サポートリソースが含まれています。

**Java のサンプル Lambda アプリケーション**
+ [example-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/example-java) – Lambda を使用して注文処理を行う Java 関数。この関数は、カスタム入力イベントオブジェクトの定義と逆シリアル化、 AWS SDK の使用方法、および出力ログ記録の方法を示しています。
+ [java-basic](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic) - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。
+ [java-events](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-events) - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの [aws-lambda-java-events](java-package.md) ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。
+ [s3-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/s3-java) － Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。
+ [layer-java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-java) – Lambda レイヤーを使用して、コアとなる関数コードから分離して依存関係をパッケージ化する方法を示す Java 関数。

**Lambda で一般的な Java フレームワークを実行する**
+ [spring-cloud-function-samples](https://github.com/spring-cloud/spring-cloud-function/tree/3.2.x/spring-cloud-function-samples/function-sample-aws) — [Spring クラウド関数](https://spring.io/projects/spring-cloud-function)フレームワークを使用して AWS Lambda 関数を作成する方法を示す Spring の例。
+ [サーバーレス Spring Boot アプリケーションのデモ](https://github.com/aws-samples/serverless-java-frameworks-samples/tree/main/springboot) — 一般的なSpring Bootアプリケーションを、SnapStart を使用または使用しないマネージド Java ランタイムでセットアップする方法、またはカスタムランタイムを使用した GraalVM ネイティブイメージとしてセットアップする方法を示す例。
+ [サーバーレス Micronaut アプリケーションのデモ](https://github.com/aws-samples/serverless-java-frameworks-samples/tree/main/micronaut) — SnapStart を使用または使用しないマネージド Java ランタイムで Micronaut を使用する方法、またはカスタムランタイムを使用した GraalVM ネイティブイメージとして Micronaut を使用する方法を示す例。詳細については、「[Micronaut/Lambda guides](https://guides.micronaut.io/latest/tag-lambda.html)」を参照してください。
+ [サーバーレス Quarkus アプリケーションのデモ](https://github.com/aws-samples/serverless-java-frameworks-samples/tree/main/quarkus) — SnapStart を使用または使用しないマネージド Java ランタイムで Quarkus を使用する方法、またはカスタムランタイムを使用した GraalVM ネイティブイメージとして Quarkus を使用する方法を示す例。詳細については、「[Quarkus/Lambda guide](https://quarkus.io/guides/aws-lambda)」および「[Quarkus/SnapStart guide](https://quarkus.io/guides/aws-lambda-snapstart)」を参照してください。

Java での Lambda 関数を初めて使用する場合は、まず `java-basic` の例で始めます。Lambda イベントソースの使用を開始するには、`java-events` の例を参照してください。これらの両方の例では、Lambda の Java ライブラリ、環境変数、AWS SDK、AWS X-Ray SDK の使用を示しています。これらの例では、必要なセットアップは最小限となっており、コマンドラインから 1 分未満でデプロイできます。