Spring Cloud AWS は、Spring および Spring Boot アプリケーションでの AWS マネージドサービスの使用を簡素化します。これは、よく知られた Spring イディオムと API を使用して AWS が提供するサービスと対話する便利な方法を提供します。

3.0.2

Spring Cloud AWS は、制限のない Apache 2.0 ライセンスでリリースされています。ドキュメントのこのセクションに貢献したい場合、またはエラーを見つけた場合は、github (英語) のプロジェクトでソースコードと課題追跡ツールを見つけてください。

1. Amazon Web Services の使用

AWS は、Amazon Web Service プラットフォームによって提供されるすべてのサービスに対するリクエストを発行するための Java SDK [Amazon] を提供します。SDK は AWS で利用可能なすべての機能を提供しますが、Spring の慣用的な方法で使用するにはかなりの量の低レベルコードが必要になります。Spring Cloud AWS は、最も人気のある AWS サービスを利用し、低レベルのコードを可能な限り回避するために、すでに統合されている Spring ベースのモジュールをアプリケーション開発者に提供します。

Spring Cloud AWS のモジュール性のおかげで、統合したい特定の AWS サービスに関連する依存関係のみを含めることができます。

また、リージョンと認証情報プロバイダーを自動構成することで、統合されていない AWS SDK クライアントの作成も簡素化されます。

そうは言っても、Spring Cloud AWS を使用せずに AWS SDK を使用することは完全に有効なオプションです。

Spring は、次のプロジェクトで他の AWS サービスのサポートを提供することに注意してください。

2. 入門

このセクションでは、Spring Cloud AWS ライブラリを使用する方法について説明します。

2.1. 部品表

Spring Cloud AWS 部品表 (BOM) は、Spring Cloud AWS の特定のリリースで使用されるすべての依存関係の推奨バージョンを宣言します。アプリケーションのビルドスクリプトから BOM を使用すると、依存関係のバージョンを自分で指定して管理する必要がなくなります。代わりに、使用している BOM のバージョンによって、使用される依存関係のバージョンが決まります。また、オーバーライドすることを選択しない限り、サポートされテストされたバージョンの依存関係をデフォルトで使用していることも保証されます。

Maven ユーザーの場合は、pom.xml ファイルに以下を追加することで BOM を使用できます。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.awspring.cloud</groupId>
            <artifactId>spring-cloud-aws-dependencies</artifactId>
            <version>{project-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Gradle ユーザーは、Maven BOM を使用して依存関係制約を宣言するための Gradle (5.0+) ネイティブサポートを活用することにより、Spring Cloud AWS BOM を使用することもできます。これは、Gradle ビルドスクリプトの依存関係セクションに「プラットフォーム」依存関係ハンドラーメソッドを追加することで実装されます。以下のスニペットに示すように、この後に、使用したい 1 つ以上のフレームワークモジュールのスターターの依存関係のバージョンレス宣言を続けることができます。SQS。

dependencies {
  implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:${springCloudAwsVersion}")
  // Replace the following with the starter dependencies of specific modules you wish to use
  implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs'
}

2.2. スターターの依存関係

Spring Cloud AWS は、ライブラリのさまざまなモジュールに簡単に依存できるように、Maven を通じてスターター依存関係 [GitHub] (英語) を提供します。各スターターには、対応する Spring Cloud AWS モジュールの使用を開始するために必要なすべての依存関係と推移的な依存関係が含まれています。

例: S3 を使用して Spring アプリケーションを作成する場合は、プロジェクトに spring-cloud-aws-starter-s3 依存関係を含めます。starter 依存関係には基礎となる spring-cloud-aws-s3 依存関係が含まれるため、これを含める必要はありません。

これらのアーティファクトの概要を以下に示します。

Spring Cloud AWS スターター 説明 Maven アーティファクト名

コア

認証と領域選択を自動的に構成する

io.awspring.cloud:spring-cloud-aws-starter

DynamoDB

DynamoDB との統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-dynamodb

S3

S3 との統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-s3

SES

SES との統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-ses

SNS

SNS との連携を実現

io.awspring.cloud:spring-cloud-aws-starter-sns

SQS

SQS との統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-sqs

パラメーターストア

AWS パラメーターストアとの統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-parameter-store

秘密マネージャー

AWS Secrets Manager との統合を提供します

io.awspring.cloud:spring-cloud-aws-starter-secrets-manager

2.3. AWS SDK バージョンの選択

AWS SDK は、Spring Cloud AWS よりも頻繁にリリースされます。Spring Cloud AWS によって構成された SDK よりも新しいバージョンの SDK を使用する必要がある場合は、SDK BOM を依存関係管理セクションに追加して、AWS SDK の依存関係を構成する他の BOM 依存関係よりも前に宣言されていることを確認してください。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>${aws-java-sdk.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3. Spring Cloud AWS コア

各 Spring Cloud AWS モジュールは、AwsCredentialsProvider および AwsRegionProvider を使用して AWS リージョンを取得し、認証情報にアクセスします。

Spring Cloud AWS は、コアコンポーネントを自動構成するための Spring Boot スターターを提供します。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter</artifactId>
</dependency>

3.1. 資格情報

software.amazon.awssdk.auth.credentials.AwsCredentialsProvider は、AWS サービスへの呼び出しを認証および認可するための認証情報を返す関数インターフェースです。

public interface AwsCredentialsProvider {
    AwsCredentials resolveCredentials();
}

Spring Cloud AWS の AwsCredentialsProvider を設定するには 3 つの方法があります。

  1. DefaultCredentialsProvider

  2. StsWebIdentityTokenFileCredentialsProvider - EKS に推奨

  3. カスタム AwsCredentialsProvider

資格情報の構成で問題が発生した場合は、詳細情報を得るためにデバッグログを有効にすることを検討してください。

logging.level.io.awspring.cloud=debug

3.1.1. DefaultCredentialsProvider

デフォルトでは、Spring Cloud AWS スターターは DefaultCredentialsProvider を自動構成し、次の順序で AWS 認証情報を検索します。

  1. Java システムのプロパティ - aws.accessKeyId および aws.secretAccessKey

  2. 環境変数 - AWS_ACCESS_KEY_ID および AWS_SECRET_ACCESS_KEY

  3. システムプロパティまたは環境変数からの Web ID トークン資格情報

  4. すべての AWS SDK および AWS CLI によって共有されるデフォルトの場所 (~/.aws/credentials) にある認証情報プロファイルファイル

  5. `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` 環境変数が設定されており、セキュリティマネージャーがその変数にアクセスする権限を持っている場合、Amazon EC2 コンテナーサービスを通じて配信される認証情報。

  6. Amazon EC2 メタデータサービスを通じて配信されるインスタンスプロファイル認証情報

プロジェクトのニーズを満たさない場合は、追加のプロパティを設定することでこの動作を変更できます。

プロパティ 説明

spring.cloud.aws.credentials.access-key

AKIAIOSFODNN7EXAMPLE

静的プロバイダーで使用されるアクセスキー

spring.cloud.aws.credentials.secret-key

wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

静的プロバイダーで使用される秘密鍵

spring.cloud.aws.credentials.instance-profile

true

追加の構成を行わずに InstanceProfileCredentialsProvider (英語) を構成します

spring.cloud.aws.credentials.profile.name

default

指定された構成ファイル内の構成プロファイルの名前

spring.cloud.aws.credentials.profile.path

~/.aws/credentials

プロファイル構成ファイルが配置されているファイルパス。値が指定されていない場合、デフォルトは ~/.aws/credentials になります。

3.1.2. StsWebIdentityTokenFileCredentialsProvider

StsWebIdentityTokenFileCredentialsProvider を使用すると、アプリケーションは Web ID トークンファイルを使用して AWS IAM ロールを引き受けることができます。これは、Kubernetes および AWS EKS 環境で特に便利です。

前提条件
  1. 引き受けるロールを作成します。

  2. アプリケーションの Web ID トークンファイルを作成します。

EKS では、このガイドに従ってサービスアカウント docs.aws.amazon.com/eks/latest/userguide/pod-configuration.html を設定してください。

StsWebIdentityTokenFileCredentialsProvider サポートはオプションであるため、次の Maven 依存関係を含める必要があります。

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>sts</artifactId>
</dependency>
設定

EKS では、サービスアカウントがすでに正しい環境変数を構成しているため、追加の構成は必要ありません。ただし、これらはオーバーライドできます。

STS 資格情報の構成は、次のプロパティをサポートします。

名前

説明

必須

デフォルト値

spring.cloud.aws.credentials.sts.role-arn

STS に関連付けられた IAM ロールの ARN。

いいえ

null (falls back to SDK default)

spring.cloud.aws.credentials.sts.web-identity-token-file

資格情報プロバイダーによって使用される Web ID トークンファイルへの絶対パス。

いいえ

null (falls back to SDK default)

spring.cloud.aws.credentials.sts.is-async-credentials-update

プロバイダーがバックグラウンドで資格情報を非同期に取得できるようにします。

いいえ

false

spring.cloud.aws.credentials.sts.role-session-name

資格情報プロバイダーによって使用されるロールのセッション名。

いいえ

null (falls back to SDK default)

3.1.3. Custom AwsCredentialsProvider

It is also possible to configure custom AwsCredentialsProvider bean which will prevent Spring Cloud AWS from auto-configuring credentials provider:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;

@Configuration
class CustomCredentialsProviderConfiguration {

    @Bean
    public AwsCredentialsProvider customAwsCredentialsProvider() {
        return new CustomAWSCredentialsProvider();
    }
}

3.2. Region

software.amazon.awssdk.regions.providers.AwsRegionProvider is a functional interface that returns the region AWS clients issue requests to.

public interface AwsRegionProvider {
    Region getRegion();
}

By default, Spring Cloud AWS starter auto-configures a DefaultAwsRegionProviderChain, which looks resolves AWS region in this order:

  1. Check the aws.region system property for the region.

  2. Check the AWS_REGION environment variable for the region.

  3. Check the {user.home}/.aws/credentials and {user.home}/.aws/config files for the region.

  4. If running in EC2, check the EC2 metadata service for the region.

If it does not serve your project needs, this behavior can be changed by setting additional properties:

property example description

spring.cloud.aws.region.static

eu-west-1

A static value for region used by auto-configured AWS clients

spring.cloud.aws.region.instance-profile

true

Configures an InstanceProfileRegionProvider (英語) with no further configuration

spring.cloud.aws.region.profile.name

default

The name of a configuration profile in the specified configuration file

spring.cloud.aws.region.profile.path

~/.aws/credentials

プロファイル構成ファイルが配置されているファイルパス。値が指定されていない場合、デフォルトは ~/.aws/credentials です。

Spring Cloud AWS によるリージョンプロバイダーの自動構成を防ぐカスタム AwsRegionProvider Bean を構成することもできます。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import software.amazon.awssdk.regions.providers.AwsRegionProvider;

@Configuration
class CustomRegionProviderConfiguration {

    @Bean
    public AwsRegionProvider customRegionProvider() {
        return new CustomRegionProvider();
    }
}

3.3. エンドポイント

AWS 互換 API を使用したサービスの使用、または Localstack (英語) に対するアプリケーションの実行を簡素化するために、自動構成されたすべての AWS クライアントでエンドポイントセットを構成できます。

プロパティ 説明

spring.cloud.aws.endpoint

localhost:4566

自動構成された AWS クライアントに適用されるエンドポイント URL

3.4. AWS クライアントのカスタマイズ

カスタム HTTP クライアントまたは ClientOverrideConfiguration を使用して AWS クライアントを構成するには、構成されたクライアントビルダーを示す型 パラメーターを使用して、型 AwsClientConfigurer の Bean を定義します。

import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer;
import org.springframework.context.annotation.Bean;

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.sns.SnsClientBuilder;

import java.time.Duration;

@Configuration
class S3AwsClientConfigurerConfiguration {

    @Bean
    AwsClientCustomizer<S3ClientBuilder> s3ClientBuilderAwsClientConfigurer() {
        return new S3AwsClientClientConfigurer();
    }

    static class S3AwsClientClientConfigurer implements AwsClientCustomizer<S3ClientBuilder> {
        @Override
        public ClientOverrideConfiguration overrideConfiguration() {
            return ClientOverrideConfiguration.builder().apiCallTimeout(Duration.ofMillis(500)).build();
        }

        @Override
        public SdkHttpClient httpClient() {
            return ApacheHttpClient.builder().connectionTimeout(Duration.ofMillis(1000)).build();
        }
    }
}

4. DynamoDb 統合

DynamoDb [Amazon] は、高パフォーマンスを実現するように設計された、フルマネージドのサーバーレスキー / 値 Nosql データベースです。DynamoDb 統合 Bean を自動構成するために、Spring Boot スターターが提供されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-dynamodb</artifactId>
</dependency>

DynamoDb 統合では、DynamoDb との通信、リポジトリの構築などに使用できる自動構成と単純な DynamoDbOperations のみが提供されます。

4.1. DynamoDbOperations

スターターは、DynamoDbOperations Bean を自動的に構成および登録し、DynamoDb を操作するためのより高いレベルの抽象化を提供します。DynamoDbTemplate (デフォルトの DynamoDbOperations 実装) は、DynamoDbEnhancedClient 上に構築されており、AWS が提供するアノテーションを使用します。サポートされているアノテーションのリストは、ここにあります。

DynamoDbEnchancedClient は、JPA と同様のプログラミングモデルをサポートしています。このモデルでは、特定のアノテーションを適用することでクラスがエンティティに変換されます。

import java.util.UUID;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;

@DynamoDbBean
public class Person {
    private UUID id;
    private String name;
    private String lastName;

    @DynamoDbPartitionKey
    public UUID getId() {
        return id;
    }

    ...
}

DynamoDbTemplate は、そのようなエンティティに対して一般的な CRUD 操作を実行するメソッドを提供し、さらに DynamoDb をクエリするための便利なメソッドを追加します。

import io.awspring.cloud.dynamodb.DynamoDbTemplate;

...
@Autowired
DynamoDbTemplate dynamoDbTemplate;
...
Person person = new Person(...)
dynamoDbTemplate.save(person);

4.1.1. テーブル名の解決

エンティティのテーブル名を解決するために、DynamoDbTemplate は型 DynamoDbTableNameResolver の Bean を使用します。デフォルトの実装では、エンティティクラス名がスネークケース表現に変換され、テーブル名プレフィックス (オプション) が使用される機能があります。テーブル名プレフィックスを提供するには、spring.cloud.aws.dynamodb.table-prefix を指定します。プレフィックスはテーブル名の前に付加されます。例: spring.cloud.aws.dynamodb.table-prefix が foo_ として構成され、エンティティクラスが Person である場合、デフォルトの実装はテーブル名を foo_person として解決します。ただし、spring.cloud.aws.dynamodb.table-prefix を指定しない場合、テーブル名は person として解決されます。

カスタム実装を使用するには、DynamoDbTableNameResolver 型の Bean を宣言すると、自動構成中に自動的に DynamoDbTemplate に挿入されます。

4.1.2. テーブルスキーマの解決

エンティティのテーブルスキーマを解決するために、DynamoDbTemplate は DynamoDbTableSchemaResolver 型の Bean を使用します。デフォルトの実装では、TableSchema オブジェクトが内部マップにキャッシュされます。カスタム実装を使用するには、DynamoDbTableSchemaResolver 型の Bean を宣言します。これは、自動構成中に自動的に DynamoDbTemplate に挿入されます。

AWS SDK DynamoDB Enhanced クライアントのクラスローダー関連の課題 [GitHub] (英語) のため、Spring Cloud AWS DynamoDB モジュールを Spring Boot DevTools とともに使用するには、カスタムテーブルスキーマリゾルバーを作成し、StaticTableSchema を使用してスキーマを定義する必要があります。

4.2. DynamoDb クライアントの使用

自動構成では、低レベル API 呼び出しに使用できる DynamoDbClient が自動的に構成され、DynamoDbOperations では不十分な場合は DynamoDbEnhancedClient が構成されます。

自動構成された DynamoDbClient または DynamoDbEnhancedClient Bean 構成がニーズを満たさない場合は、カスタム Bean を作成することで置き換えることができます。

import java.util.Collections;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;

public class DynamoDbService {
    private final DynamoDbClient dynamoDbClient;

    public DynamoDbService(DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    void deletePerson(String uuid) {
        dynamoDbClient.deleteItem(DeleteItemRequest.builder().key(Collections.singletonMap("uuid", AttributeValue.builder().s(uuid).build())).build());
    }
}

4.3. DynamoDB アクセラレータの使用

スターターは、プロジェクトに次のものが追加されたことを検出すると、software.amazon.dax.ClusterDaxClient Bean を自動的に構成して登録します。

<dependency>
    <groupId>software.amazon.dax</groupId>
    <artifactId>amazon-dax-client</artifactId>
</dependency>

4.4. 構成

DynamoDb 用の Spring Boot スターターには、次の構成オプションが用意されています。

名前

説明

必須

デフォルト値

spring.cloud.aws.dynamodb.enabled

DynamoDb 統合を有効にします。

いいえ

true

spring.cloud.aws.dynamodb.endpoint

DynamoDbClient によって使用されるエンドポイントを構成します。

いいえ

spring.cloud.aws.dynamodb.region

DynamoDbClient によって使用される領域を構成します。

いいえ

spring.cloud.aws.dynamodb.table-prefix

デフォルトの DynamoDbTableNameResolver 実装で使用されるテーブル名のプレフィックス。

いいえ

spring.cloud.aws.dynamodb.dax.idle-timeout-millis

DAX クラスターとのアイドル接続のタイムアウト。

いいえ

30000

spring.cloud.aws.dynamodb.dax.url

DAX クラスターのエンドポイント。

はい

spring.cloud.aws.dynamodb.dax.connection-ttl-millis

接続存続時間。

いいえ

0

spring.cloud.aws.dynamodb.dax.connect-timeout-millis

接続タイムアウト

いいえ

1000

spring.cloud.aws.dynamodb.dax.request-timeout-millis

DAX クラスターとの接続のリクエストタイムアウト。

いいえ

1000

spring.cloud.aws.dynamodb.dax.write-retries

書き込みを再試行する回数。最初の試行はカウントされません。

いいえ

2

spring.cloud.aws.dynamodb.dax.read-retries

読み取りを再試行する回数。最初の試行はカウントされません。

いいえ

2

spring.cloud.aws.dynamodb.dax.cluster-update-interval-millis

メンバーシップの変更についてクラスターメンバーをポーリングする間隔。

いいえ

4000

spring.cloud.aws.dynamodb.dax.endpoint-refresh-timeout-millis

エンドポイントリフレッシュのタイムアウト。

いいえ

6000

spring.cloud.aws.dynamodb.dax.max-concurrency

同時リクエストの最大数。

いいえ

1000

spring.cloud.aws.dynamodb.dax.max-pending-connection-acquires

取得する保留中の接続の最大数。

いいえ

10000

spring.cloud.aws.dynamodb.dax.skip-host-name-verification

URL のホスト名の検証をスキップします。

いいえ

4.5. IAM パーミッション

DynamoDb 統合の使用方法に依存するため、最小権限モデルを使用する必要があるため、IAM ポリシーのリストを提供することは無意味です。DynamoDb が使用する IAM ポリシーを確認し、どれを使用する必要があるかを確認するには、IAM ポリシー [Amazon] を確認してください。

5. S3 統合

S3 [Amazon] を使用すると、ファイルをクラウドに保存できます。Spring Boot スターターは、さまざまな S3 統合関連コンポーネントを自動構成するために提供されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-s3</artifactId>
</dependency>

5.1. S3 クライアントを使用する

スターターは、S3Client Bean を自動的に構成し、Spring アプリケーションコンテキストに登録します。S3Client Bean を使用して、S3 バケットおよびオブジェクトに対する操作を実行できます。

import java.io.IOException;
import java.nio.charset.StandardCharsets;

import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;

import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

@Component
class S3ClientSample {
    private final S3Client s3Client;

    S3ClientSample(S3Client s3Client) {
        this.s3Client = s3Client;
    }

    void readFile() throws IOException {
        ResponseInputStream<GetObjectResponse> response = s3Client.getObject(
            request -> request.bucket("bucket-name").key("file-name.txt"));

        String fileContent = StreamUtils.copyToString(response, StandardCharsets.UTF_8);

        System.out.println(fileContent);
    }
}

5.2. S3TransferManager および CRT ベースの S3 クライアントの使用

AWS は、Transfer Manager と呼ばれる高レベルのファイル転送ユーティリティと CRT ベースの S3 クライアントを開始しました [Amazon]

次の依存関係がプロジェクトに追加される場合、スターターは software.amazon.awssdk.transfer.s3.S3TransferManager Bean を自動的に構成して登録します。

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3-transfer-manager</artifactId>
</dependency>

Transfer Manager は、CRT S3 クライアントで最適に動作します。CRT ベースの S3AsyncClient を自動構成するには、次の依存関係をプロジェクトに追加します。

<dependency>
  <groupId>software.amazon.awssdk.crt</groupId>
  <artifactId>aws-crt</artifactId>
</dependency>

S3AsyncClient Bean が作成されない場合は、AWS SDK を通じて作成されたデフォルトの S3AsyncClient が使用されます。最大のスループット、マルチパートのアップロード / ダウンロード、再開可能なファイルのアップロードを活用するには、CRT ベースの S3AsyncClient の使用を検討してください。

5.3. クロスリージョン S3 クライアントの使用

AWS SDK で提供される S3Client 実装はリージョン固有です。つまり、クライアントが使用するように設定されているリージョンに保存されているバケットとオブジェクトを操作するためにのみ使用できます。

例: DefaultAwsRegionProviderChain がリージョン us-east-1 を解決すると仮定すると、別のリージョンで作成されたバケットを使用する S3 オペレーションを実行すると例外が発生します。

software.amazon.awssdk.services.s3.model.S3Exception: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint. (Service: S3, Status Code: 301, Request ID: ..., Extended Request ID: ...)

Spring Cloud AWS は、領域ごとに S3Client オブジェクトの内部辞書を維持することで、この問題を解決する CrossRegionS3Client を提供します。これらのクライアントをカスタマイズする必要がある場合は、CrossRegionS3Client で領域固有の S3 クライアントを作成するためのテンプレートとして機能するカスタム S3ClientBuilder Bean を作成できます。クロスリージョン S3 クライアントを使用するために追加の作業は必要ありません。これは、Spring Cloud AWS によって自動構成された S3Client です。

CrossRegionS3Client の作成を無効にして、代わりに通常の領域固有の S3Client を使用するには、カスタム S3Client Bean を作成するか、spring-cloud-aws-s3-cross-region-client 依存関係を除外します。

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-s3</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.awspring.cloud</groupId>
            <artifactId>spring-cloud-aws-s3-cross-region-client</artifactId>
        </exclusion>
    </exclusions>
</dependency>

5.4. Spring リソースとしての S3 オブジェクト

Spring リソースは、ファイルシステムファイル、クラスパスファイル、サーブレットコンテキスト相対ファイルなど、多数の低レベルリソースの抽象化です。Spring Cloud AWS は、新しいリソース型である S3Resource オブジェクトを追加します。

S3 の Spring リソース抽象化により、@Value アノテーションを使用して S3 URL によって S3 オブジェクトにアクセスできるようになります。

@Value("s3://[S3_BUCKET_NAME]/[FILE_NAME]")
private Resource s3Resource;

…または Spring アプリケーションコンテキスト

SpringApplication.run(...).getResource("s3://[S3_BUCKET_NAME]/[FILE_NAME]");

これにより、ファイルの読み取りなどの可能な操作に使用できる Resource オブジェクトが作成されます。

WriteableResource が必要ですが、Resource に書き込むことも可能です。

@Value("s3://[S3_BUCKET_NAME]/[FILE_NAME]")
private Resource s3Resource;
...
try (OutputStream os = ((WritableResource) s3Resource).getOutputStream()) {
  os.write("content".getBytes());
}

Resource を S3 リソースとして操作するには、それを io.awspring.cloud.s3.S3Resource にキャストします。S3Resource を直接使用すると、S3 オブジェクトのメタデータ [Amazon] を設定できます。

@Value("s3://[S3_BUCKET_NAME]/[FILE_NAME]")
private Resource s3Resource;
...
ObjectMetadata objectMetadata = ObjectMetadata.builder()
    .contentType("application/json")
    .serverSideEncryption(ServerSideEncryption.AES256)
    .build();
s3Resource.setObjectMetadata(objectMetadata);
try (OutputStream outputStream = s3Resource.getOutputStream()) {
    outputStream.write("content".getBytes(StandardCharsets.UTF_8));
}

5.4.1. S3 出力ストリーム

内部では、デフォルトで S3Resource は io.awspring.cloud.s3.InMemoryBufferingS3OutputStream を使用します。データがリソースに書き込まれると、マルチパートアップロードを使用して S3 に送信されます。アップロード中にネットワークエラーが発生した場合、S3Client には失敗した各部分を再試行する再試行メカニズムが組み込まれています。再試行後にアップロードが失敗した場合、マルチパートアップロードは中止され、S3Resource は io.awspring.cloud.s3.S3Exception をスローします。

InMemoryBufferingS3OutputStream の動作がニーズに合わない場合は、デフォルトの出力ストリームプロバイダーをオーバーライドする DiskBufferingS3OutputStreamProvider 型の Bean を定義することで、io.awspring.cloud.s3.DiskBufferingS3OutputStream を使用できます。DiskBufferingS3OutputStream では、データがリソースに書き込まれると、まず、OS の tmp ディレクトリ内のディスクに保存されます。ストリームが閉じられると、ファイルは S3Client#putObject (英語) メソッドでアップロードされます。アップロード中にネットワークエラーが発生した場合、S3Client には再試行メカニズムが組み込まれています。再試行後にアップロードが失敗した場合、S3Resource は、ファイルシステムの一時ディレクトリ内のファイルの場所を含む io.awspring.cloud.s3.UploadFailed 例外をスローします。

try (OutputStream outputStream = s3Resource.getOutputStream()) {
    outputStream.write("content".getBytes(StandardCharsets.UTF_8));
} catch (UploadFailedException e) {
    // e.getPath contains a file location in temporary folder
}

S3TransferManager を使用している場合、デフォルトの実装は io.awspring.cloud.s3.TransferManagerS3OutputStream に切り替わります。この OutputStream も、S3 にアップロードする前に一時ファイルを使用してディスクに書き込みますが、内部でマルチパートアップロードを使用するため、高速になる可能性があります。

5.4.2. リソースの検索

Spring リソースローダーは、Ant スタイルのパス仕様に基づいたリソースの収集もサポートしています。Spring Cloud AWS は、バケット内およびバケット全体のリソースを解決するための同じサポートを提供します。S3 バケットを検索するには、実際のリソースローダーを Spring Cloud AWS でラップする必要があります。S3 バケット以外の場合、リソースローダーは元のリソースローダーにフォールバックします。次の例は、さまざまなパターンを使用したリソース解決を示しています。

import org.springframework.context.ApplicationContext;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.Resource;

import io.awspring.cloud.s3.S3PathMatchingResourcePatternResolver;

import software.amazon.awssdk.services.s3.S3Client;

public class SimpleResourceLoadingBean {

    private final ResourcePatternResolver resourcePatternResolver;

    @Autowired
    public void setupResolver(S3Client s3Client, ApplicationContext applicationContext) {
        this.resourcePatternResolver = new S3PathMatchingResourcePatternResolver(s3Client, applicationContext);
    }

    public void resolveAndLoad() throws IOException {
        Resource[] allTxtFilesInFolder =  this.resourcePatternResolver.getResources("s3://bucket/name/*.txt");
        Resource[] allTxtFilesInBucket =  this.resourcePatternResolver.getResources("s3://bucket...
        Resource[] allTxtFilesGlobally =  this.resourcePatternResolver.getResources("s3:/...
    }
}

ユーザーが所有するバケットの数によっては、すべてのバケット全体でリソースを解決するのに非常に時間がかかる場合があります。

5.5. S3Template の使用

Spring Cloud AWS は、S3Client に加えてより高度な抽象化を提供し、S3 を使用する場合の最も一般的なユースケース用のメソッドを提供します。

S3Template は、バケットを作成および削除するための一目瞭然のメソッドに加えて、ファイルをアップロードおよびダウンロードするための簡単なメソッドを提供します。

@Autowired
private S3Template s3Template;

InputStream is = ...
// uploading file without metadata
s3Template.upload(BUCKET, "file.txt", is);

// uploading file with metadata
s3Template.upload(BUCKET, "file.txt", is, ObjectMetadata.builder().contentType("text/plain").build());

S3Template のもう 1 つの機能は、単一のメソッド呼び出しで S3 オブジェクトを取得 / 配置するための署名付き URL を生成できることです。

URL signedGetUrl = s3Template.createSignedGetUrl("bucket_name", "file.txt", Duration.ofMinutes(5));

S3Template では、Java オブジェクトの保存と取得も可能です。

Person p = new Person("John", "Doe");
s3Template.store(BUCKET, "person.json", p);

Person loadedPerson = s3Template.read(BUCKET, "person.json", Person.class);

デフォルトでは、Jackson がクラスパス上にある場合、S3Template は ObjectMapper ベースの Jackson2JsonS3ObjectConverter を使用して、S3 オブジェクトから Java オブジェクトへ、またはその逆に変換します。この動作は、型 S3ObjectConverter のカスタム Bean を提供することで上書きできます。

5.6. S3 オブジェクトのコンテンツ型の決定

S3TemplateS3Resource または S3OutputStream を通じて S3 に保存されているすべての S3 オブジェクトは、S3 オブジェクトキー (ファイル名) に基づいて、S3 オブジェクトのメタデータに contentType プロパティを自動的に設定します。

デフォルトでは、PropertiesS3ObjectContentTypeResolver (800 を超えるファイル拡張子をサポートするコンポーネント) がコンテンツ型の解決を担当します。このコンテンツ型の解決がニーズを満たさない場合は、ファイルのアップロードを担当するすべてのコンポーネントで自動的に使用される、型 S3ObjectContentTypeResolver のカスタム Bean を提供できます。

5.7. 構成

S3 用 Spring Boot スターターには、次の構成オプションが用意されています。

名前

説明

必須

デフォルト値

spring.cloud.aws.s3.enabled

S3 統合を有効にします。

いいえ

true

spring.cloud.aws.s3.endpoint

S3Client によって使用されるエンドポイントを構成します。

いいえ

localhost:4566

spring.cloud.aws.s3.region

S3Client によって使用される領域を構成します。

いいえ

eu-west-1

spring.cloud.aws.s3.accelerate-mode-enabled

S3 へのアクセス時に加速エンドポイントの使用を有効にするオプション。エンドポイントの高速化により、Amazon CloudFront のグローバルに分散されたエッジロケーションを使用して、オブジェクトの転送を高速化できます。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.checksum-validation-enabled

S3 に保存されているオブジェクトのチェックサムの検証を無効にするオプション。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.chunked-encoding-enabled

PutObjectRequest および UploadPartRequest のリクエストペイロードに署名するときにチャンクエンコーディングの使用を有効にするオプション。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.path-style-access-enabled

S3 オブジェクトへのアクセスに、DNS スタイルのアクセスではなくパススタイルのアクセスを使用できるようにするオプション。S3 にアクセスする際の負荷分散が向上するため、DNS スタイルのアクセスが推奨されます。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.use-arn-region-enabled

S3 リソース ARN が、クライアントが設定されたリージョンとは異なるリージョンを持つ S3 オペレーションのターゲットとして渡される場合、クライアントがクロスリージョン呼び出しを行うことを許可するには、このフラグを "true" に設定する必要があります。ARN で指定されたリージョン、それ以外の場合は例外がスローされます。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.crt.minimum-part-size-in-bytes

転送パーツの最小パーツサイズを設定します。最小パートサイズを小さくすると、マルチパート転送がより多くの小さなパートに分割されます。この値の設定が低すぎると、転送速度に悪影響が生じ、各部分で余分な遅延やネットワーク通信が発生します。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.crt.initial-read-buffer-size-in-bytes

クライアントが S3 からダウンロードされた部分をバッファリングするために使用する開始バッファサイズを構成します。高いダウンロードスループットを維持するには、より大きなウィンドウを維持します。ウィンドウが複数のパーツを保持できるほど大きくない限り、パーツを並行してダウンロードすることはできません。メモリ内にバッファリングされるデータ量を制限するには、ウィンドウを小さくしてください。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.crt.target-throughput-in-gbps

転送リクエストのゴールスループット。値が大きいほど、より多くの S3 接続が開かれることを意味します。転送マネージャーが設定されたゴールスループットを達成できるかどうかは、環境のネットワーク帯域幅や設定された max-concurrency などのさまざまな要因によって決まります。

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.crt.max-concurrency

転送中に確立する必要がある S3 接続の最大数を指定します

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.transfer-manager.max-depth

S3TransferManager#uploadDirectory 操作でアクセスするディレクトリの最大レベル数を指定します

いいえ

null (falls back to SDK default)

spring.cloud.aws.s3.transfer-manager.follow-symbolic-links

S3TransferManager#uploadDirectory 操作でファイルツリーを移動するときにシンボリックリンクをたどるかどうかを指定します

いいえ

null (falls back to SDK default)

5.8. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

Downloading files

s3:GetObject

ファイルの検索

s3:ListObjects

ファイルのアップロード

s3:PutObject

spring-cloud-aws-demo バケットへのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::spring-cloud-aws-demo"
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::spring-cloud-aws-demo/*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::spring-cloud-aws-demo/*"
        }
    ]
}

6. SES の統合

Spring には、Java メール API [Oracle] (英語) に基づいてメールを送信するための組み込みサポートがあり、Java Mail API の使用中に静的メソッド呼び出しを回避して、アプリケーションのテスト容易性をサポートします。Spring Cloud AWS は、Spring メール抽象化の実装として Amazon SES をサポートします。

その結果、Spring Cloud AWS ユーザーは、Amazon SES サービスの Spring Cloud AWS 実装を使用するか、SMTP 経由で Amazon SES にメールを送信する標準の JavaMailAPI ベースの実装を使用するかを決定できます。

主にパフォーマンス上の理由から、SMTP の代わりに Spring Cloud AWS 実装を使用することをお勧めします。Spring Cloud AWS は 1 つの API 呼び出しを使用してメールメッセージを送信しますが、SMTP プロトコルは、メールを送信するまで複数のリクエスト(EHLO、MAIL FROM、RCPT TO、DATA、QUIT)を行います。

SES 統合 Bean を自動構成するために、Spring Boot スターターが提供されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-ses</artifactId>
</dependency>

6.1. 簡単なメールの送信

アプリケーション開発者は、MailSender をアプリケーションコードに挿入して、単純なテキストベースのメールメッセージを直接送信できます。以下のサンプルは、簡単なメールメッセージの作成を示しています。

import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;

class MailSendingService {

    private final MailSender mailSender;

    public MailSendingService(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void sendMailMessage() {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setFrom("foo@bar.com");
        simpleMailMessage.setTo("bar@baz.com");
        simpleMailMessage.setSubject("test subject");
        simpleMailMessage.setText("test content");
        this.mailSender.send(simpleMailMessage);
    }
}

6.2. 添付ファイルや HTML メールの送信

メールまたは HTML メールで添付ファイルを送信するには、MIME メッセージを作成して送信する必要があります。MIME メッセージを作成するには、Java Mail API の依存関係と実装がクラスパスに存在する必要があります。Spring Cloud AWS は依存関係を検出し、MIME メッセージを作成および構築して送信できる org.springframework.mail.javamail.JavaMailSender 実装を作成します。以下に示すように、必要な構成変更は Java Mail API と実装の依存関係のみです。

<dependency>
    <groupId>jakarta.mail</groupId>
    <artifactId>jakarta.mail-api</artifactId>
</dependency>
<dependency>
    <groupId>org.eclipse.angus</groupId>
    <artifactId>jakarta.mail</artifactId>
</dependency>

Java Mail API への依存関係はありますが、メールメッセージの送信に使用される Amazon SESAPI は引き続き存在します。Amazon AWS 側には SMTP セットアップ [Amazon] は必要ありません。

メールを送信するには、以下の例に示すように、アプリケーション開発者が JavaMailSender を使用してメールを送信する必要があります。

import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;

class MailSendingService {

    private final JavaMailSender mailSender;

    public MailSendingService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void sendMailMessage() {
        this.mailSender.send(new MimeMessagePreparator() {

            @Override
            public void prepare(MimeMessage mimeMessage) throws Exception {
                MimeMessageHelper helper =
                    new MimeMessageHelper(mimeMessage, true, "UTF-8");
                helper.addTo("foo@bar.com");
                helper.setFrom("bar@baz.com");
                helper.addAttachment("test.txt", ...);
                helper.setSubject("test subject with attachment");
                helper.setText("mime body", false);
            }
        });
    }
}

6.3. メールの認証

Amazon SES メールサービスへのスパム攻撃を回避するために、本番アクセスのないアプリケーションは、各メール受信者を確認する [Amazon] 必要があります。そうしないと、メール送信者は software.amazon.awssdk.services.ses.model.MessageRejectedException をスローします。

本番アクセス [Amazon] をリクエストすることができ、メールアドレス検証の必要性を無効にします。

6.4. 構成

SES 用 Spring Boot スターターには、次の構成オプションが用意されています。

名前

説明

必須

デフォルト値

spring.cloud.aws.ses.enabled

SES 統合を有効にします。

いいえ

true

spring.cloud.aws.ses.endpoint

SesClient によって使用されるエンドポイントを構成します。

いいえ

spring.cloud.aws.ses.region

SesClient によって使用される領域を構成します。

いいえ

spring.cloud.aws.ses.sourceArn

送信認可のみに使用されるソース ARN を設定します。

いいえ

Amazon SES は、Amazon Web Services クラウドのすべてのリージョン [Amazon] で利用できるわけではありません。メールサービスをサポートしていない領域でホストおよび運用されているアプリケーションでは、メールサービスの使用中にエラーが発生します。メール送信者の構成に対してリージョンをオーバーライドする必要があります。以下の例は、有効なリージョン (EU-WEST-1) を使用するようにクライアントがオーバーライドされる、SES サービスを提供しないリージョン (EU-CENTRAL-1) の一般的な組み合わせを示しています。

sourceArn は、送信認可ポリシーに関連付けられている ID の ARN です。このパラメーターをいつ使用するかについては、"Amazon SES 開発者ガイド " の説明を参照してください。

spring.cloud.aws.ses.region=eu-west-1
spring.cloud.aws.ses.sourceArn=arn:aws:ses:eu-west-1:123456789012:identity/example.com

6.5. IAM パーミッション

Spring Cloud AWS には、次の IAM 権限が必要です。

添付ファイルなしでメールを送信する

ses:SendEmail

添付ファイル付きのメールを送信する

ses:SendRawEmail

SES へのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail"
            ],
            "Resource": "arn:aws:ses:your:arn"
        }
    ]
}

7. SNS 連携

SNS [Amazon] は、クライアントが特定のトピックに通知を発行できるようにする pub/sub メッセージングサービスです。Spring Boot スターターは、SNS 統合 Bean を自動構成するために提供されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-sns</artifactId>
</dependency>

7.1. 通知の送信

7.1.1. SNS テンプレート

スターターは、SnsTemplate Bean を自動的に構成および登録し、SNS 通知を送信するためのより高いレベルの抽象化を提供します。SnsTemplate は Spring メッセージングの抽象化を実装しており、Spring メッセージングと互換性のある他のメッセージングテクノロジと簡単に組み合わせることができます。

次の型のペイロードを含む通知の送信をサポートします。

  • String - org.springframework.messaging.converter.StringMessageConverter を使用する

  • Object - これは、org.springframework.messaging.converter.MappingJackson2MessageConverter および Spring Boot によって自動構成された Jackson の com.fasterxml.jackson.databind.ObjectMapper を使用して JSON に直列化されます。

さらに、org.springframework.messaging.Message をサポートするいくつかのメソッドを公開します。

import io.awspring.cloud.sns.core.SnsTemplate;

import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

class NotificationService {
    private final SnsTemplate snsTemplate;

    NotificationService(SnsTemplate snsTemplate) {
        this.snsTemplate = snsTemplate;
    }

    void sendNotification() {
        // sends String payload
        snsTemplate.sendNotification("topic-arn", "payload", "subject");
        // sends object serialized to JSON
        snsTemplate.sendNotification("topic-arn", new Person("John", "Doe"), "subject");
        // sends a Spring Messaging Message
        Message<String> message = MessageBuilder.withPayload("payload")
            .setHeader("header-name", "header-value")
            .build();
        snsTemplate.send("topic-arn", message);
    }
}

自動構成コンバーターがニーズを満たさない場合は、任意のメッセージコンバーターを備えたカスタム SnsTemplate Bean を提供できます。

SNS 通知を送信する場合は、トピック ARN を提供する必要があります。Spring Cloud AWS はこれを簡素化し、その名前のトピックがすでに作成されているという条件で、代わりにトピック名を指定できるようにします。それ以外の場合、Spring Cloud AWS は最初の呼び出しでこの名前のトピックを作成しようとします。

トピック名によってトピック ARN を解決する動作は、型 io.awspring.cloud.sns.core.TopicArnResolver のカスタム Bean を提供することで変更できます。

トピック作成呼び出しによるトピック名の解決が不可能な場合は、Bean または io.awspring.cloud.sns.core.TopicsListingTopicArnResolver を自動構成できます。自動構成により、SnsTemplate と TopicArnResolverConfiguration が自動的に構成されます。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.services.sns.SnsClient;

import io.awspring.cloud.sns.core.TopicArnResolver;
import io.awspring.cloud.sns.core.TopicsListingTopicArnResolver;

@Configuration
public class TopicArnResolverConfiguration {

    @Bean
    public TopicArnResolver topicArnResolver(SnsClient snsClient) {
        return new TopicsListingTopicArnResolver(snsClient);
    }
}

7.1.2. SNS 運営

Spring メッセージングとの互換性のため、SnsTemplate は、Spring メッセージングの抽象化が必要ない場合には不要になる可能性のある多くのメソッドを公開します。このような場合は、SnsOperations を使用することをお勧めします。これは、SnsTemplate によって実装されたインターフェースであり、FIFO トピックのサポートを含む、SNS 通知を送信するための便利な方法を公開します。

import io.awspring.cloud.sns.core.SnsNotification;
import io.awspring.cloud.sns.core.SnsOperations;
import io.awspring.cloud.sns.core.SnsTemplate;

class NotificationService {
    private final SnsOperations snsOperations;

    NotificationService(SnsOperations snsOperations) {
        this.snsOperations = snsOperations;
    }

    void sendNotification() {
        SnsNotification<Person> notification = SnsNotification.builder(new Person("John", "Doe"))
            .deduplicationId("..")
            .groupId("..")
            .build();
        snsOperations.sendNotification("topic-arn", notification);
    }
}

7.2. SMS メッセージの送信

スターターは、SnsSmsTemplate Bean を自動的に構成および登録し、SMS メッセージを SNS トピックまたは電話番号に直接送信するためのより高いレベルの抽象化を提供します。

SnsSmsTemplate#send と SnsSmsTemplate#sendToTopic はどちらも、MessageAttributes [Amazon] を設定するための流れるような型 セーフインターフェースを提供するオプションのパラメーター SnsMessageAttributes を受け取ります。

import io.awspring.cloud.sns.sms.SmsMessageAttributes;
import io.awspring.cloud.sns.sms.SmsType;
import io.awspring.cloud.sns.sms.SnsSmsTemplate;

class NotificationService {
    private SnsSmsTemplate smsTemplate;

    NotificationService(SnsSmsTemplate smsTemplate) {
        this.smsTemplate = smsTemplate;
    }

    void sendSms() {
        smsTemplate.send("+1XXX5550100", "the message", SmsMessageAttributes.builder()
                .smsType(SmsType.PROMOTIONAL).senderID("mySenderID").maxPrice("0.50").build());
    }
}

7.3. SNS クライアントの使用

すべての下位レベルの SNS オペレーションにアクセスするには、AWS SDK の SnsClient を使用することをお勧めします。SnsClient Bean は SnsAutoConfiguration によって自動構成されます。

自動構成された SnsClient Bean 構成がニーズを満たさない場合は、SnsClient 型のカスタム Bean を作成することで置き換えることができます。

import software.amazon.awssdk.services.sns.SnsClient;

class NotificationService {
    private final SnsClient snsClient;

    public NotificationService(SnsClient snsClient) {
        this.snsClient = snsClient;
    }

    void sendNotification() {
        snsClient.publish(request -> request.topicArn("sns-topic-arn").message("payload"));
    }
}

7.4. アノテーション駆動型 HTTP 通知エンドポイント

SNS は複数のエンドポイント型(SQS、メール、HTTP、HTTPS)をサポートし、Spring Cloud AWS は HTTP(S) エンドポイントのサポートを提供します。SNS は、HTTP トピックリスナーエンドポイントに 3 種類のリクエストを送信し、それぞれにアノテーションが提供されます。

  • サブスクリプションリクエスト→ @NotificationSubscriptionMapping

  • 通知リクエスト→ @NotificationMessageMapping

  • 退会依頼→ @NotificationUnsubscribeMapping

HTTP エンドポイントは Spring MVC コントローラーに基づいています。Spring Cloud AWS は、通知リクエストからメッセージと件名を抽出するために、いくつかのカスタム引数リゾルバーを追加しました。

統合の例:

import io.awspring.cloud.sns.annotation.endpoint.NotificationMessageMapping;
import io.awspring.cloud.sns.annotation.endpoint.NotificationSubscriptionMapping;
import io.awspring.cloud.sns.annotation.endpoint.NotificationUnsubscribeConfirmationMapping;
import io.awspring.cloud.sns.annotation.handlers.NotificationMessage;
import io.awspring.cloud.sns.annotation.handlers.NotificationSubject;
import io.awspring.cloud.sns.handlers.NotificationStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/topicName")
public class NotificationTestController {

    @NotificationSubscriptionMapping
    public void handleSubscriptionMessage(NotificationStatus status) {
        //We subscribe to start receive the message
        status.confirmSubscription();
    }

    @NotificationMessageMapping
    public void handleNotificationMessage(@NotificationSubject String subject, @NotificationMessage String message) {
        // ...
    }

    @NotificationUnsubscribeConfirmationMapping
    public void handleUnsubscribeMessage(NotificationStatus status) {
        //e.g. the client has been unsubscribed and we want to "re-subscribe"
        status.confirmSubscription();
    }
}

7.5. 構成

SNS 用 Spring Boot スターターには、次の構成オプションが用意されています。

名前

説明

必須

デフォルト値

spring.cloud.aws.sns.enabled

SNS 連携を有効にします。

いいえ

true

spring.cloud.aws.sns.endpoint

SnsClient によって使用されるエンドポイントを構成します。

いいえ

localhost:4566

spring.cloud.aws.sns.region

SnsClient によって使用される領域を構成します。

いいえ

eu-west-1

7.6. IAM パーミッション

Spring Cloud AWS には、次の IAM 権限が必要です。

トピックに通知を公開するには

sns:Publish

通知を公開するには、次も必要になります

sns:ListTopics

アノテーション駆動型 HTTP 通知エンドポイントを使用するには

sns:ConfirmSubscription

トピック名を ARN に解決する場合

sns:CreateTopic

SNS へのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish",
                "sns:ConfirmSubscription"
            ],
            "Resource": "yourArn"
        },
        {
            "Effect": "Allow",
            "Action": "sns:ListTopics",
            "Resource": "*"
        },
        {
        "Effect": "Allow",
        "Action": "sns:CreateTopic",
        "Resource": "*"
        }
    ]
}

8. SQS の統合

Amazon Simple Queue Service は、キューとのポイントツーポイント通信を提供するメッセージングサービスです。Spring Cloud AWS SQS 統合は、@SqsListenerMessageListenerContainerMessageListenerContainerFactory などの一般的な Spring 抽象化を使用したメッセージの送受信のサポートを提供します。

JMS や他のメッセージサービスと比較して、Amazon SQS には考慮すべき制限があります。

  • Amazon SQS は String ペイロードのみを許可するため、Object はすべて文字列表現に変換する必要があります。Spring Cloud AWS は、Java オブジェクトを JSON に変換することにより、Amazon SQS メッセージを含む Java オブジェクトを転送するための専用サポートを備えています。

  • Amazon SQS の最大メッセージサイズはメッセージあたり 256kb であるため、より大きなメッセージは送信されません。

SQS 統合 Bean を自動構成するために、Spring Boot スターターが提供されています。Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-sqs</artifactId>
</dependency>

8.1. サンプルリスナーアプリケーション

以下は、Spring Boot の自動構成を活用した最小限のサンプルアプリケーションです。

@SpringBootApplication
public class SqsApplication {

    public static void main(String[] args) {
        SpringApplication.run(SqsApplication.class, args);
    }

    @SqsListener("myQueue")
    public void listen(String message) {
        System.out.println(message);
    }
}

Spring Boot がない場合は、@Configuration に SqsBootstrapConfiguration クラスをインポートし、SqsMessageListenerContainerFactory Bean を宣言する必要があります。

public class Listener {

    @SqsListener("myQueue")
    public void listen(String message) {
        System.out.println(message);
    }

}

@Import(SqsBootstrapConfiguration.class)
@Configuration
public class SQSConfiguration {

    @Bean
    public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
        return SqsMessageListenerContainerFactory
            .builder()
            .sqsAsyncClient(sqsAsyncClient())
            .build();
    }

    @Bean
    public SqsAsyncClient sqsAsyncClient() {
        return SqsAsyncClient.builder().build();
    }

    @Bean
    public Listener listener() {
        return new Listener();
    }

}

8.2. メッセージ送信

Spring Cloud AWS は、SQS にメッセージを送信するための SqsTemplate を提供します。

8.2.1. SqsTemplate

Spring Boot と自動構成を使用する場合、コンテキスト内に他のテンプレート Bean が見つからない場合に備えて、SqsTemplate インスタンスがデフォルトで自動接続されます。このテンプレートインスタンスは、提供された構成を備えた自動構成された SqsAsyncClient によってサポートされています。SqsTemplate インスタンスは不変でスレッドセーフです。

メッセージの送信先のエンドポイントは、キュー名または URL のいずれかになります。

8.2.2. SqsTemplate インスタンスの作成

SqsTemplate は 2 つの Operations インターフェースを実装します。SqsOperations にはブロッキングメソッドが含まれ、SqsAsyncOperations には CompletableFuture インスタンスを返す非同期メソッドが含まれます。同期または非同期操作のみを使用する場合は、対応するインターフェースを利用して不要なメソッドを排除できます。

次のメソッドを使用して、デフォルトのオプションで新しい SqsTemplate インスタンスを作成できます。

SqsTemplate template = SqsTemplate.newTemplate(sqsAsyncClient);

SqsOperations blockingTemplate = SqsTemplate.newSyncTemplate(sqsAsyncClient);

SqsAsyncOperations asyncTemplate = SqsTemplate.newAsyncTemplate(sqsAsyncClient);
返されるオブジェクトは常に SqsTemplate であり、別個のメソッドはインターフェースの戻り値の型の便宜のためのみです。

より複雑な構成が必要な場合には、ビルダーと一連のオプションも提供されています。

SqsTemplate template = SqsTemplate.builder()
    .sqsAsyncClient(this.asyncClient)
        .configure(options -> options
                .acknowledgementMode(TemplateAcknowledgementMode.MANUAL)
                .defaultEndpointName("my-queue"))
        .build();

ビルダーは、テンプレートを SqsOperations として返す buildSyncTemplate() メソッドと、テンプレートを SqsAsyncOperations として返す buildAsyncTemplate() メソッドも提供します。

8.2.3. テンプレートのオプション

次のオプションは、options オブジェクトを通じて構成できます。操作メソッドのパラメーターとして他の値が指定されていない場合は、デフォルトが適用されます。

TemplateOptions の説明
名前 タイプ デフォルト 説明

acknowledgementMode

TemplateAcknowledgementMode

TemplateAcknowledgementMode #ACKNOWLEDGE_ON_RECEIVE

メッセージを受信した後、テンプレートによってメッセージを確認するかどうか。メッセージは、後で Acknowledgement#acknowledge メソッドを使用して確認応答できます。詳細については、"SqsTemplate 確認応答" を参照してください。

sendBatchFailureHandlingStrategy

SendBatchFailureStrategy

SendBatchFailureStrategy # スロー

送信されたバッチから少なくとも 1 つのメッセージが配信されなかった場合に、SendResult.Batch インスタンスを含む SendBatchOperationFailedException をスローするかどうか。SendBatchFailureStrategy#DO_NOT_THROW を使用すると、SendResult.Batch オブジェクトが返されます。

defaultPollTimeout

持続時間

10 秒

SQS への受信リクエストを実行するときにメッセージを待機するデフォルトの最大時間。詳細については、"SqsTemplate" を参照してください。

defaultMaxNumberOfMessages

整数

10

SQS への受信リクエストによって返されるメッセージのデフォルトの最大数。詳細については、"SqsTemplate" を参照してください。

defaultEndpointName

String

ブランク

テンプレートで使用されるデフォルトのエンドポイント名。詳細については、"SqsTemplate" を参照してください。

defaultPayloadClass

クラス

null

ペイロードの変換先となるデフォルトのクラス。SqsTemplate で送信されるメッセージには、デフォルトで型情報を含むヘッダーが含まれるため、構成は必要ないことに注意してください。詳細については、"テンプレートメッセージの変換" を参照してください。

additionalHeaderForReceive

文字列、オブジェクト

このテンプレートで受信するすべてのメッセージに追加される単一のヘッダーを設定します。

additionalHeadersForReceive

マップ < 文字列、オブジェクト>

このテンプレートで受信するすべてのメッセージに追加されるヘッダーを設定します。

queueNotFoundStrategy

QueueNotFoundStrategy

QueueNotFoundStrategy # 作成

キューが見つからない場合に使用する戦略を設定します。QueueNotFoundStrategy#FAIL では、キューが見つからない場合に例外がスローされます。

queueAttributeNames

コレクション < 属性名>

取得するキュー属性名を設定します。このような属性は、受信メッセージで MessageHeaders として使用できます。

messageAttributeNames

コレクション <String>

すべて

受信操作時にメッセージとともに取得されるメッセージ属性名を設定します。このような属性は、受信メッセージで MessageHeaders として使用できます。

messageSystemAttributeNames

コレクション < メッセージシステム属性名>

すべて

受信操作時にメッセージとともに取得されるメッセージシステム属性名を設定します。このような属性は、受信メッセージで MessageHeaders として使用できます。

8.2.4. メッセージ送信

SqsTemplate を使用して SQS キューにメッセージを送信する方法は多数あります。次のメソッドは SqsOperations インターフェースを通じて使用でき、対応する async は SqsAsyncOperations で使用できます。

// Send a message to the configured default endpoint.
SendResult<T> send(T payload);

// Send a message to the provided queue with the given payload.
SendResult<T> send(String queue, T payload);

// Send the given Message to the provided queue.
SendResult<T> send(String queue, Message<T> message);

// Send a message with the provided options.
SendResult<T> send(Consumer<SqsSendOptions> to);

// Send a batch of Messages to the provided queue
SendResult.Batch<T> sendMany(String queue, Collection<Message<T>> messages);

options バリアントを使用した例は次のとおりです。

SendResult<String> result = template.send(to -> to.queue("myQueue")
    .payload("myPayload")
    .header("myHeaderName", "myHeaderValue")
    .headers(Map.of("myOtherHeaderName", "myOtherHeaderValue"))
    .delaySeconds(10)
);
メッセージを Fifo キューに送信するには、オプションに messageDeduplicationId プロパティと messageGroupId プロパティが含まれます。messageGroupId が提供されていない場合、フレームワークによってランダムな UUID が生成されます。messageDeduplicationId が提供されておらず、AWS でコンテンツの重複排除が無効になっている場合、ランダムな UUID が生成されます。生成された値は、SendResult オブジェクトに含まれる Message のヘッダーで取得できます。
SendResult

SendResult レコードには、送信操作に関する有用な情報が含まれています。

public record SendResult<T>(UUID messageId, String endpoint, Message<T> message, Map<String, Object> additionalInformation) {

    public record Batch<T>(Collection<SendResult<T>> successful, Collection<SendResult.Failed<T>> failed) {}

    public record Failed<T> (String errorMessage, String endpoint, Message<T> message, Map<String, Object> additionalInformation) {}

}

送信操作が成功すると、SendResult オブジェクトが次のように作成されます。

  • メッセージに対して SQS から返された messageId 

  • メッセージの送信先 endpoint 

  • フレームワークによって追加された可能性のある追加ヘッダーを含む、送信された Message インスタンス

  • Fifo キュー内のメッセージに対して生成された sequenceNumber を含む additionalInformation マップ。

単一メッセージ操作の送信操作が失敗すると、メッセージを含む MessagingOperationFailedException がスローされます。

Batch 送信操作の場合、SendResult.Batch オブジェクトが返されます。このオブジェクトには、successful および failed の結果の Collection が含まれます。

バッチ内で送信に失敗したメッセージがある場合、対応する SendResult.Failed オブジェクトが生成されます。SendBatch.Failed オブジェクトには次のものが含まれます。

  • SQS から返された errorMessage 

  • メッセージの送信先となる endpoint 

  • フレームワークによって追加された可能性のある追加ヘッダーを含む、送信しようとした Message インスタンス

  • SQS によって返された code および senderFault パラメーターを含む additionalInformation マップ。

デフォルトでは、送信バッチ操作に少なくとも 1 つの失敗したメッセージがある場合、SendBatchOperationFailedException がスローされます。このような例外には、成功メッセージと失敗メッセージの両方を含む SendResult.Batch<?> プロパティが含まれます。

この動作は、テンプレートの作成時に sendBatchFailureHandlingStrategy オプションを使用して構成できます。SendBatchFailureStrategy#DO_NOT_THROW が構成されている場合、例外はスローされず、成功メッセージと失敗メッセージの両方を含む SendResult.Batch オブジェクトが返されます。

便宜上、additionalInformation パラメーターは SqsTemplateParameters クラスの定数として見つけることができます。

8.2.5. テンプレートメッセージの変換

デフォルトのメッセージ変換は、以下を含む SqsMessagingMessageConverter インスタンスによって処理されます。

  • SqsHeaderMapper ヘッダーを messageAttributes との間でマッピングするための

  • ペイロードと JSON 間の変換を行うための CompositeMessageConverter と StringMessageConverter および MappingJackson2MessageConverter

カスタム MessagingMessageConverter 実装は SqsTemplate.builder() で提供できます。

SqsOperations template = SqsTemplate
    .builder()
    .sqsAsyncClient(sqsAsyncClient)
    .messageConverter(converter)
    .buildSyncTemplate();

デフォルトの SqsMessagingMessageConverter インスタンスもビルダーで構成できます。

SqsOperations template = SqsTemplate
    .builder()
    .sqsAsyncClient(sqsAsyncClient)
    .configureDefaultConverter(converter -> {
            converter.setObjectMapper(objectMapper);
            converter.setHeaderMapper(headerMapper);
            converter.setPayloadTypeHeader("my-custom-type-header");
        }
    )
    .buildSyncTemplate();
受信操作のペイロードクラスの指定

デフォルトでは、SqsTemplate は、ペイロードクラスの完全修飾名を含む JavaType という名前のヘッダーを、送信されるすべてのメッセージに追加します。このようなヘッダーは、ペイロードをどのクラスに逆直列化する必要があるかを識別するために、SqsTemplateSqsMessageListenerContainer@SqsListener による受信操作で使用されます。

この動作は、setPayloadTypeHeaderValueFunction メソッドを使用して SqsMessagingMessageConverter で構成できます。この関数は Message オブジェクトを受け取り、ヘッダーで使用される値 (デフォルトではペイロードのクラス FQCN ) を含む String を返します。関数によって null が返された場合、型情報を含むヘッダーは追加されません。

typeHeaderName は、setPayloadTypeHeader 方式を使用して構成できます。

型 マッピング情報が利用できない場合は、ペイロードクラスをテンプレートのオプションまたは receive() メソッドバリアントで指定できます。

Optional<Message<SampleRecord>> receivedMessage = template
            .receive(queue, SampleRecord.class);

8.3. メッセージの受信

フレームワークは、キューからメッセージを受信するための次のオプションを提供します。

8.3.1. SqsTemplate

SqsTemplate は、Standard および Fifo SQS キューからメッセージを受信する便利な方法を提供します。これらのメソッドは、SqsTemplate によって実装される 2 つのインターフェース (SqsOperations および SqsAsyncOperations) に分かれています。sync または async 操作のみを使用する場合、特定のインターフェースを使用することでメソッドを絞り込むことができます。

インターフェース SqsTemplate インスタンスの作成およびテンプレートのオプションの詳細については、"SqsTemplate" を参照してください。

次のメソッドは SqsOperations インターフェースを通じて使用でき、対応する async は SqsAsyncOperations で使用できます。

// Receive a message from the configured default endpoint and options.
Optional<Message<?>> receive();

// Receive a message from the provided queue and convert the payload to the provided class.
<T> Optional<Message<T>> receive(String queue, Class<T> payloadClass);

// Receive a message with the provided options.
Optional<Message<?>> receive(Consumer<SqsReceiveOptions> from);

// Receive a message with the provided options and convert the payload to the provided class.
<T> Optional<Message<T>> receive(Consumer<SqsReceiveOptions> from, Class<T> payloadClass);

// Receive a batch of messages from the configured default endpoint and options.
Collection<Message<?>> receiveMany();

// Receive a batch of messages from the provided queue and convert the payloads to the provided class.
<T> Collection<Message<T>> receiveMany(String queue, Class<T> payloadClass);

// Receive a batch of messages with the provided options.
Collection<Message<?>> receiveMany(Consumer<SqsReceiveOptions> from);

// Receive a batch of messages with the provided options and convert the payloads to the provided class.
<T> Collection<Message<T>> receiveMany(Consumer<SqsReceiveOptions> from, Class<T> payloadClass);

以下は、オプション付きのメッセージを受信する例です。

Optional<Message<SampleRecord>> receivedMessage = template
        .receive(from -> from.queue("my-queue")
                .visibilityTimeout(Duration.ofSeconds(10))
                .pollTimeout(Duration.ofSeconds(5))
                .additionalHeaders(Map.of("my-custom-header-name", "my-custom-header-value")),
        SampleRecord.class);
Fifo キューからメッセージを受信するには、オプションに receiveRequestAttemptId パラメーターが含まれます。そのようなパラメーターが指定されていない場合は、ランダムなパラメーターが生成されます。
SqsTemplate 確認応答

SqsTemplate はデフォルトですべての受信メッセージを確認します。これは、テンプレートオプションで TemplateAcknowledgementMode.MANUAL を設定することで変更できます。

SqsTemplate.builder().configure(options -> options.acknowledgementMode(TemplateAcknowledgementMode.MANUAL));

確認応答中にエラーが発生した場合、正常に確認応答されたメッセージと失敗したメッセージの両方を含む SqsAcknowledgementException がスローされます。

MANUAL 確認応答で受信したメッセージを確認するには、Acknowledgement#acknowledge および Acknowledgement#acknowledgeAsync メソッドを使用できます。

8.3.2. メッセージリスナー

手動で作成したコンテナーでメッセージを受信するには、MessageListener または AsyncMessageListener を指定する必要があります。どちらのインターフェースにも single message メソッドと batch メソッドが付属しています。これらは関数型インターフェースであり、単一メッセージメソッドに対してラムダまたはメソッド参照を提供できます。

単一メッセージ / バッチモードおよびメッセージペイロード変換は、SqsContainerOptions を介して設定できます。詳細については、"メッセージ変換とペイロードの逆直列化" を参照してください。

@FunctionalInterface
public interface MessageListener<T> {

    void onMessage(Message<T> message);

    default void onMessage(Collection<Message<T>> messages) {
        throw new UnsupportedOperationException("Batch not implemented by this MessageListener");
    }

}
@FunctionalInterface
public interface AsyncMessageListener<T> {

    CompletableFuture<Void> onMessage(Message<T> message);

    default CompletableFuture<Void> onMessage(Collection<Message<T>> messages) {
        return CompletableFutures
                .failedFuture(new UnsupportedOperationException("Batch not implemented by this AsyncMessageListener"));
    }

}

8.3.3. SqsMessageListenerContainer

MessageListenerContainer は、ポーリングから処理、確認応答まで、メッセージのライフサイクル全体を管理します。

SqsMessageListenerContainerFactory または @SqsListener アノテーションを使用して、直接インスタンス化できます。@Bean として宣言された場合、Spring コンテキストはそのライフサイクルを管理し、アプリケーションの起動時にコンテナーを開始し、アプリケーションのシャットダウン時にコンテナーを停止します。詳細については、"コンテナーのライフサイクル" を参照してください。

MessageListenerContainer インターフェースを実装します。

public interface MessageListenerContainer<T> extends SmartLifecycle {

    String getId();

    void setId(String id);

    void setMessageListener(MessageListener<T> messageListener);

    void setAsyncMessageListener(AsyncMessageListener<T> asyncMessageListener);

}
ジェネリクスパラメーター <T> は、このコンテナーによって消費されるメッセージの payload type を表します。これにより、コンパイル時に、コンテナーで使用されるすべてのコンポーネントが同じ型であることを確認できます。同じコンテナーまたはファクトリで複数のペイロード型を使用する場合は、単純に Object と入力します。この型はペイロード変換では考慮されません。

コンテナーは、@Configuration アノテーション付きクラスでよく知られた Spring 方法でインスタンス化できます。例:

@Bean
MessageListenerContainer<Object> listenerContainer(SqsAsyncClient sqsAsyncClient) {
    SqsMessageListenerContainer<Object> container = new SqsMessageListenerContainer<>(sqsAsyncClient);
    container.setMessageListener(System.out::println);
    container.setQueueNames("myTestQueue");
    return container;
}

このフレームワークは、次のような別のアプローチを可能にする便利な Builder も提供します。

@Bean
MessageListenerContainer<Object> listenerContainer(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainer
            .builder()
            .sqsAsyncClient(sqsAsyncClient)
            .messageListener(System.out::println)
            .queueNames("myTestQueue")
            .build();
}

コンテナーのライフサイクルは手動で管理することもできます。

void myMethod(SqsAsyncClient sqsAsyncClient) {
    SqsMessageListenerContainer<Object> container = SqsMessageListenerContainer
            .builder()
            .sqsAsyncClient(sqsAsyncClient)
            .messageListener(System.out::println)
            .queueNames("myTestQueue")
            .build();
    container.start();
    container.stop();
}

8.3.4. SqsMessageListenerContainerFactory

MessageListenerContainerFactory は、直接または @SqsListener アノテーションを介して、MessageListenerContainer インスタンスを作成するために使用できます。

これは、次のようなおなじみの Spring 方法で作成できます。

@Bean
SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
    SqsMessageListenerContainerFactory<Object> factory = new SqsMessageListenerContainerFactory<>();
    factory.setSqsAsyncClient(sqsAsyncClient);
    return factory;
}

または Builder 経由:

@Bean
SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainerFactory
            .builder()
            .sqsAsyncClient(sqsAsyncClient)
            .build();
}
このメソッドを使用してファクトリで SqsAsyncClient インスタンスを設定すると、このファクトリによって作成されたすべてのコンテナーが同じ SqsAsyncClient インスタンスを共有します。高スループットのアプリケーションの場合は、代わりにファクトリの setSqsAsyncClientSupplier またはビルダーの sqsAsyncSupplier メソッドを通じて Supplier<SqsAsyncClient> を提供できます。この場合、各コンテナーは SqsAsyncClient インスタンスを受け取ります。あるいは、単一の SqsAsyncClient インスタンスを構成してスループットを高めることもできます。各アプローチのトレードオフの詳細については、AWS のドキュメントを参照してください。

次のように、ファクトリを使用してコンテナーを直接作成することもできます。

@Bean
MessageListenerContainer<Object> myListenerContainer(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainerFactory
            .builder()
            .sqsAsyncClient(sqsAsyncClient)
            .messageListener(System.out::println)
            .build()
            .createContainer("myQueue");
}

8.3.5. @SqsListener アノテーション

SQS メッセージを使用する最も簡単な方法は、@Component クラスのメソッドに @SqsListener アノテーションを付けることです。次に、フレームワークは MessageListenerContainer を作成し、メッセージの受信時にメソッドを呼び出すように MessagingMessageListenerAdapter を設定します。

Spring Boot を auto-configuration とともに使用する場合、設定は必要ありません。

アノテーションのほとんどの属性は、SpEL (#{…​}) またはプロパティプレースホルダー (${…​}) から解決できます。

キュー名

queueNames または value プロパティを介してアノテーションで 1 つ以上のキューを指定できます。2 つのプロパティには区別がありません。

キュー名の代わりに、キューの URL を指定することもできます。キュー名の代わりに URL を使用すると、コンテナーの起動時にフレームワークがキュー URL を検索することがなくなるため、起動時間がわずかに速くなる可能性があります。

@SqsListener({"${my.queue.url}", "myOtherQueue"})
public void listenTwoQueues(String message) {
    System.out.println(message);
}

Bean クラスでは任意の数の @SqsListener アノテーションを使用でき、アノテーションが付けられた各メソッドは個別の MessageListenerContainer によって処理されます。

同じアノテーションで宣言されたキューはコンテナーを共有しますが、それぞれに個別のスループットと確認応答の制御があります。
MessageListenerContainerFactory の指定

MessageListenerContainerFactory は、factory プロパティを通じて指定できます。このようなファクトリは、アノテーション付きメソッドのコンテナーを作成するために使用されます。

指定しない場合は、defaultSqsListenerContainerFactory という名前のファクトリが検索されます。このデフォルト名の変更については、@SqsListeners のグローバル構成を参照してください。

@SqsListener(queueNames = "myQueue", factory = "myFactory")
public void listen(String message) {
    System.out.println(message);
}

Spring Boot アプリケーションを auto-configuration とともに使用する場合、コンテキスト内で宣言された他のファクトリ Bean がない場合は、デフォルトのファクトリが提供されます。

その他のアノテーションプロパティ

@SqsListener アノテーションでは以下のプロパティを指定できます。このようなプロパティは、結果として得られる MessageListenerContainer の同等の SqsContainerOptions をオーバーライドします。

  • id - 結果のコンテナーの ID を指定します。これは、MessageListenerContainerRegistry からコンテナーをフェッチするために使用でき、コンテナーとそのコンポーネントによって一般的なロギングとスレッドの名前付けに使用されます。

  • maxConcurrentMessages - いつでも inflight できるメッセージの最大数を設定します。詳細については、"メッセージ処理スループット" を参照してください。

  • pollTimeoutSeconds - SQS からポーリングが返されるまでに待機する最大時間を設定します。利用可能なメッセージがある場合、この設定より早く呼び出しが返される可能性があることに注意してください。

  • messageVisibilitySeconds - 投票で取得されたメッセージの最小公開範囲を設定します。FIFO 単一メッセージリスナーメソッドの場合、この可視性は各メッセージがリスナーに送信される前にバッチ全体に適用されることに注意してください。詳細については、"FIFO サポート" を参照してください。

リスナーメソッドの引数

リスナーメソッドのシグネチャーでは、多くの引数の型を使用できます。

  • MyPojo - POJO 型は、JSON から自動的に逆直列化されます。

  • Message<MyPojo> - 逆直列化されたペイロードと MessageHeaders を含む Message<MyPojo> インスタンスを提供します。

  • List<MyPojo> - バッチモードを有効にし、SQS からポーリングされたバッチを受信します。

  • List<Message<MyPojo>> - バッチモードを有効にし、SQS からポーリングされたバッチをヘッダーとともに受信します。

  • @Header(String headerName) - 指定されたヘッダーを提供します。

  • @Headers - MessageHeaders または Map<String, Object> を提供します

  • Acknowledgement - 単一のメッセージリスナーに対して手動でメッセージを確認するためのメソッドを提供します。AcknowledgementMode は MANUAL に設定する必要があります ( メッセージの確認を参照してください)

  • BatchAcknowledgement - バッチリスナーのメッセージバッチの一部または全体を手動で承認するためのメソッドを提供します。AcknowledgementMode は MANUAL に設定する必要があります ( メッセージの確認を参照してください)

  • Visibility - は、メッセージの可視性を指定された値に変更できる changeTo() メソッドを提供します。

  • QueueAttributes - メッセージを受信したキューのキュー属性を提供します。SQS からフェッチされるキュー属性を指定する方法については、SQS からの属性の取得を参照してください。

  • software.amazon.awssdk.services.sqs.model.Message - SQS からオリジナルの Message を提供します

多くの引数を含むサンプルを次に示します。

@SqsListener("${my-queue-name}")
public void listen(Message<MyPojo> message, MyPojo pojo, MessageHeaders headers, Acknowledgement ack, Visibility visibility, QueueAttributes queueAttributes, software.amazon.awssdk.services.sqs.model.Message originalMessage) {
    Assert.notNull(message);
    Assert.notNull(pojo);
    Assert.notNull(headers);
    Assert.notNull(ack);
    Assert.notNull(visibility);
    Assert.notNull(queueAttributes);
    Assert.notNull(originalMessage);
}
バッチリスナーは、単一の List<MyPojo> および List<Message<MyPojo>> メソッド引数と、オプションの BatchAcknowledgement または AsyncBatchAcknowledgement 引数をサポートします。MessageHeaders は、getHeaders() メソッドを通じて Message インスタンスから抽出する必要があります。

8.3.6. バッチ処理

すべてのメッセージ処理インターフェースには、single message メソッドと batch メソッドの両方があります。これは、同じコンポーネントのセットを使用して単一メソッドとバッチメソッドの両方を処理し、該当する場合にはロジックを共有できることを意味します。

バッチモードが有効な場合、フレームワークはポーリングの結果全体をリスナーに提供します。maxMessagesPerPoll に 10 より大きい値を指定すると、複数のポーリングの結果が結合され、それぞれの量までのメッセージがリスナーに提供されます。

@SqsListener を使用したバッチ処理を有効にするには、単一の List<MyPojo> または List<Message<MyPojo>> メソッド引数をリスナーメソッドに指定する必要があります。リスナーメソッドには、AcknowledgementMode.MANUAL のオプションの BatchAcknowledgement 引数を指定することもできます。

あるいは、ファクトリまたはコンテナーの SqsContainerOptions で SqsContainerOptions を ListenerMode.BATCH に設定することもできます。

同じファクトリを使用して、@SqsListener メソッドの single message コンテナーと batch コンテナーの両方を作成できます。
同じファクトリが両方の配信方法で共有される場合、提供される ErrorHandlerMessageInterceptor または MessageListener は適切なメソッドを実装する必要があります。

8.3.7. コンテナーオプション

各 MessageListenerContainer には、異なるオプションのセットを含めることができます。MessageListenerContainerFactory インスタンスには、作成するコンテナーのテンプレートとして使用される SqsContainerOptions.Builder インスタンスプロパティがあります。

ファクトリとコンテナーの両方で、オプションの変更に使用できる configure メソッドが提供されています。

@Bean
SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainerFactory
            .builder()
            .configure(options -> options
                    .messagesPerPoll(5)
                    .pollTimeout(Duration.ofSeconds(10)))
            .sqsAsyncClient(sqsAsyncClient)
            .build();
}
@Bean
MessageListenerContainer<Object> listenerContainer(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainer
            .builder()
            .configure(options -> options
                    .messagesPerPoll(5)
                    .pollTimeout(Duration.ofSeconds(10)))
            .sqsAsyncClient(sqsAsyncClient)
            .messageListener(System.out::println)
            .queueNames("myTestQueue")
            .build();
}

SqsContainerOptions インスタンスは不変であり、container.getContainerOptions() メソッドを介して取得できます。より複雑な構成が必要な場合は、toBuilder および fromBuilder メソッドでオプションの新しいコピーを作成し、それをファクトリまたはコンテナーに戻す方法が提供されます。

void myMethod(MessageListenerContainer<Object> container) {
    SqsContainerOptions.Builder modifiedOptions = container.getContainerOptions()
            .toBuilder()
            .pollTimeout(Duration.ofSeconds(5))
            .shutdownTimeout(Duration.ofSeconds(20));
    container.configure(options -> options.fromBuilder(modifiedOptions));
}

オプションのコピーは、containerOptions.createCopy() または containerOptionsBuilder.createCopy() を使用して作成することもできます。

自動構成の使用

SQS 用 Spring Boot スターターは、次の自動構成プロパティを提供します。

名前

説明

必須

デフォルト値

spring.cloud.aws.sqs.enabled

SQS 統合を有効にします。

いいえ

true

spring.cloud.aws.sqs.endpoint

SqsAsyncClient によって使用されるエンドポイントを構成します。

いいえ

localhost:4566

spring.cloud.aws.sqs.region

SqsAsyncClient によって使用される領域を構成します。

いいえ

eu-west-1

spring.cloud.aws.sqs.listener.max-inflight-messages-per-queue

キューごとのインフライトメッセージの最大数。

いいえ

10

spring.cloud.aws.sqs.listener.max-messages-per-poll

ポーリングごとに受信されるメッセージの最大数。

いいえ

10

spring.cloud.aws.sqs.listener.poll-timeout

ポーリングでメッセージを待機する最大時間。

いいえ

10 秒

SqsContainerOptions の説明
プロパティ 範囲 デフォルト 説明

maxConcurrentMessages

1 - Integer.MAX_VALUE

10

このコンテナーで同時に処理できる各キューからのメッセージの最大数。この数値は、(maxConcurrentMessages * キューの数) に従ってコンテナーのスレッドプールサイズを定義するために使用されます。確認応答をバッチ処理する場合、メッセージは確認応答キューに渡された時点で送信中ではないとみなされます。メッセージの確認を参照してください。

maxMessagesPerPoll

1 - Integer.MAX_VALUE

10

このコンテナー内の SQS キューへのポーリングによって受信されるメッセージの最大数。10 より大きい値を指定すると、複数のポーリングの結果が結合されるため、バッチリスナーに役立ちます。

詳細については、AWS のドキュメントを参照してください。

pollTimeout

1 - 10 秒

10 秒

空を返すまでの SQS キューへのポーリングの最大期間。ポーリングが長いと、メッセージが利用可能な場合に空のポーリングが発生する可能性が低くなります。詳細については、AWS のドキュメントを参照してください。

maxDelayBetweenPolls

1 - 10 秒

10 秒

フレームワークが次のポーリングを試行する前に、キューで許可が利用可能になるまで待機する最大時間。その期間が経過すると、フレームワークは利用可能な許可を使用して部分的な取得を実行しようとします。その結果、特に設定されていない限り、ポーリングされるメッセージは maxMessagesPerPoll メッセージより少なくなります。メッセージ処理スループットを参照してください。

autoStartup

真 / 偽

true

コンテナーが自動的に開始される場所を決定します。false に設定すると、コンテナーは起動時に起動せず、コンテナーを起動するには手動介入が必要になります。コンテナーのライフサイクルを参照してください。

listenerShutdownTimeout

0 - 未定義

10 秒

強制的にシャットダウンを試行する前に、コンテナーがキューのメッセージ処理の完了を待機する時間。コンテナーのライフサイクルを参照してください。

acknowledgementShutdownTimeout

0 - 未定義

10 秒

メッセージ処理が終了した後、コンテナーがキューに対する確認応答が完了するまで待機する時間。コンテナーのライフサイクルを参照してください。

backPressureMode

AUTO, ALWAYS_POLL_MAX_MESSAGES, FIXED_HIGH_THROUGHPUT

AUTO

コンテナーで使用されるバックプレッシャー戦略を構成します。BackPressureMode の構成を参照してください。

listenerMode

SINGLE_MESSAGE, BATCH

SINGLE_MESSAGE

このコンテナーが single message リスナーを使用するか batch リスナーを使用するかを構成します。この値は、リスナーメソッドに List 引数が含まれるかどうかに応じて、@SqsListener によってオーバーライドされます。バッチ処理を参照してください。

queueAttributeNames

Collection<QueueAttributeName>

リストが空です

コンテナーの起動時に SQS から取得される QueueAttributes を構成します。SQS からの属性の取得を参照してください。

messageAttributeNames

Collection<String>

ALL

メッセージごとに SQS から取得される MessageAttributes を構成します。SQS からの属性の取得を参照してください。

messageSystemAttributeNames

Collection<String>

ALL

メッセージごとに SQS から取得される MessageSystemAttribute を構成します。SQS からの属性の取得を参照してください。

messageConverter

MessagingMessageConverter

SqsMessagingMessageConverter

SQS メッセージを Spring メッセージングメッセージに変換するために使用される MessagingMessageConverter を構成します。メッセージ変換とペイロードの逆直列化を参照してください。

acknowledgementMode

ON_SUCCESS, ALWAYS, MANUAL

ON_SUCCESS

メッセージの自動確認をトリガーする処理結果を構成します。メッセージの確認を参照してください。

acknowledgementInterval

0 - 未定義

1 second for Standard SQS, Duration.ZERO for FIFO SQS

バッチ処理の確認応答間の間隔を設定します。immediate acknowledgement を有効にするには、acknowledgementThreshold をゼロに設定するとともに Duration.ZERO に設定します。メッセージの確認を参照してください。

acknowledgementThreshold

0 - 未定義

10 for Standard SQS, 0 for FIFO SQS

バッチの確認応答をトリガーするための確認応答キュー内のメッセージの最小量を構成します。immediate acknowledgement を有効にするには、acknowledgementInterval ~ Duration.ZERO とともにゼロに設定します。メッセージの確認を参照してください。

acknowledgementOrdering

PARALLEL, ORDERED

PARALLEL for Standard SQS and FIFO queues with immediate acknowledgement, ORDERED for FIFO queues with acknowledgement batching enabled.

Configures the order acknowledgements should be made. Fifo queues can be acknowledged in parallel for immediate acknowledgement since the next message for a message group will only start being processed after the previous one has been acknowledged. See Acknowledging Messages.

componentsTaskExecutor

TaskExecutor

null

MessageListenerContainer 内部コンポーネントによって使用される TaskExecutor インスタンスを提供します。TaskExecutor の提供を参照してください。

acknowledgementResultTaskExecutor

TaskExecutor

null

AcknowledgementResultCallback をブロックするために AcknowledgementProcessor によって使用される TaskExecutor インスタンスを提供します。TaskExecutor の提供を参照してください。

messageVisibility

Duration

null

このコンテナーでポーリングされるメッセージのメッセージ表示期間を指定します。FIFO キューの場合、各メッセージが処理される前に、メッセージグループ内のすべてのメッセージの可視性が拡張されます。FIFO サポートを参照してください。それ以外の場合、可視性は SQS のポーリング時に 1 回指定されます。

queueNotFoundStrategy

FAIL, CREATE

CREATE

コンテナー起動時にキューが見つからなかった場合の動作を設定します。コンテナーのライフサイクルを参照してください。

8.3.8. SQS からの属性の取得

QueueAttributesMessageAttributesMessageSystemAttributes は SQS から入手可能です。これらは SqsContainerOptions queueAttributeNamesmessageAttributeNamesmessageSystemAttributeNames メソッドを使用して設定できます。

キューの QueueAttributes はコンテナーの起動時に取得され、@SqsListener メソッドに QueueAttributes メソッドパラメーターを追加するか、SqsHeaders.SQS_QUEUE_ATTRIBUTES_HEADER ヘッダーを取得することで検索できます。

MessageAttributes および MessageSystemAttributes は各メッセージとともに取得され、メッセージヘッダーにマップされます。これらは、@Header パラメーターを使用して取得することも、Message で直接取得することもできます。メッセージヘッダーには、メッセージ属性の場合は SqsHeaders.SQS_MA_HEADER_PREFIX ("Sqs_MA_" ) が、メッセージシステム属性の場合は SqsHeaders.SQS_MSA_HEADER_PREFIX ("Sqs_MSA_" ) がプレフィックスとして付けられます。

デフォルトでは、QueueAttributes および ALL MessageAttributesMessageSystemAttributes は取得されません。

8.3.9. コンテナーのライフサイクル

MessageListenerContainer インターフェースは SmartLifecycle を継承し、コンテナーのライフサイクルを制御するメソッドを提供します。

@SqsListener アノテーションから作成されたコンテナーは、フレームワークによって登録される MessageListenerContainerRegistry Bean に登録されます。コンテナー自体は Spring 管理の Bean ではなく、レジストリはアプリケーションの起動およびシャットダウンにおけるこれらのコンテナーのライフサイクルを管理する責任があります。

DefaultListenerContainerRegistry ` implementation provided by the framework allows the phase value to be set through the `setPhase 方式。デフォルト値は MessageListenerContainer.DEFAULT_PHASE です。

起動時に、コンテナーは、指定されたキュー名または ARN のキュー URL を取得するため、およびそのように構成されている場合は QueueAttributes を取得するために、SQS にリクエストを作成します。名前の代わりにキュー URL を指定し、キュー属性をリクエストしないと、そのようなリクエストが必要ないため、起動時間がわずかに短縮される可能性があります。

キューが存在しないためにキュー URL の取得が失敗した場合、キューを作成するか失敗するようにフレームワークを構成できます。キュー名の代わりに URL が指定された場合、フレームワークは起動時にこのリクエストを行わないため、キューが存在しない場合は実行時に失敗します。この構成は SqsContainerOptions queueNotFoundStrategy. で利用可能です

シャットダウン時に、デフォルトでコンテナーは、SqsContainerOptions.getShutdownTimeout() までのすべてのポーリング、処理、確認操作が完了するまで待機します。この期間が経過すると、操作はキャンセルされ、コンテナーは強制的にシャットダウンを試みます。

Spring Bean としてのコンテナー

手動で作成したコンテナーは Bean として登録できます。@Configuration アノテーション付きクラスで @Bean を宣言することによって。このような場合、コンテナーのライフサイクルは、アプリケーションの起動時とシャットダウン時に Spring コンテキストによって管理されます。

@Bean
MessageListenerContainer<Object> listenerContainer(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainer
            .builder()
            .sqsAsyncClient(sqsAsyncClient)
            .messageListener(System.out::println)
            .queueNames("myTestQueue")
            .build();
}
SqsMessageListenerContainer.builder() では、SmartLifecycle.phase を指定して、MessageListenerContainer.DEFAULT_PHASE で定義されたデフォルト値をオーバーライドできます。
レジストリからのコンテナーの取得

コンテナーは、コンテナーから MessageListenerContainer Bean をフェッチし、getListenerContainers および getContainerById メソッドを使用して取得できます。その後、ライフサイクルメソッドを使用してインスタンスを開始および停止できます。

@Autowired
MessageListenerContainerRegistry registry;

public void myLifecycleMethod() {
    MessageListenerContainer container = registry.getContainerById("myId");
    container.stop();
    container.start();
}
ライフサイクルの実行

デフォルトでは、MessageListenerContainerRegistry および MessageListenerContainer インスタンスによって内部的に実行されるすべてのライフサイクルアクションは並行して実行されます。

この動作は、LifecycleHandler.get().setParallelLifecycle(false) を設定することで無効にできます。

Spring 管理の MessageListenerContainer Bean のライフサイクルアクションは、常に順番に実行されます。

8.3.10. FIFO サポート

FIFO SQS キューはメッセージの受信を完全にサポートしています。.fifo で終わる名前のキューは、そのように自動的にセットアップされます。

  • メッセージは receiveRequestAttemptId でポーリングされ、受信されたメッセージのバッチはメッセージの MessageGroupId に従って分割されます。

  • 指定されたグループからの各メッセージは順番に処理され、各グループは並行して処理されます。

  • メッセージの処理が失敗した場合、同じメッセージグループからの後続のメッセージは破棄されるため、message visibility の有効期限が切れた後に再び処理されます。

  • すでに正常に処理され、確認応答されたメッセージは再度提供されません。

  • batch リスナーが使用されている場合、ポーリングからの各メッセージグループはリスナーメソッドへのバッチとして提供されます。

  • FIFO キューには、メッセージの確認応答に関するさまざまなデフォルトもあります。詳細については、"確認応答のデフォルト" を参照してください。

  • message visibility が @SqsListener または SqsContainerOptions を通じて設定されている場合、各メッセージが処理される前に、メッセージグループ内のすべてのメッセージの可視性が拡張されます。

MessageListenerContainer は、Standard キューまたは FIFO キューのいずれかのみを持つことができます。両方を持つことはできません。これは、手動で作成されたコンテナーと @SqsListener アノテーション付きメソッドの両方に有効です。

8.4. メッセージインターセプター

このフレームワークは、MessageInterceptor インターフェースと AsyncMessageInterceptor インターフェースを提供します。

public interface MessageInterceptor<T> {

    default Message<T> intercept(Message<T> message) {
        return message;
    }

    default Collection<Message<T>> intercept(Collection<Message<T>> messages) {
        return messages;
    }

    default void afterProcessing(Message<T> message, Throwable t) {
    }

    default void afterProcessing(Collection<Message<T>> messages, Throwable t) {
    }

}
public interface AsyncMessageInterceptor<T> {

    default CompletableFuture<Message<T>> intercept(Message<T> message) {
        return CompletableFuture.completedFuture(message);
    }

    default CompletableFuture<Collection<Message<T>>> intercept(Collection<Message<T>> messages) {
        return CompletableFuture.completedFuture(messages);
    }

    default CompletableFuture<Void> afterProcessing(Message<T> message, Throwable t) {
        return CompletableFuture.completedFuture(null);
    }

    default CompletableFuture<Void> afterProcessing(Collection<Message<T>> messages, Throwable t) {
        return CompletableFuture.completedFuture(null);
    }

}

自動構成ファクトリを使用する場合、@Bean を宣言するだけでインターセプターが設定されます。

@Bean
public MessageInterceptor<Object> messageInterceptor() {
    return new MessageInterceptor<Object>() {
            @Override
            public Message<Object> intercept(Message<Object> message) {
                return MessageBuilder
                    .fromMessage(message)
                    .setHeader("newHeader", "newValue")
                    .build();
            }
        };
}

あるいは、実装を MessageListenerContainerFactory で設定するか、MessageListenerContainer で直接設定することもできます。

@Bean
public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
    return SqsMessageListenerContainerFactory
        .builder()
        .sqsAsyncClientSupplier(BaseSqsIntegrationTest::createAsyncClient)
        .messageInterceptor(new MessageInterceptor<Object>() {
            @Override
            public Message<Object> intercept(Message<Object> message) {
                return MessageBuilder
                    .fromMessage(message)
                    .setHeader("newHeader", "newValue")
                    .build();
            }
        })
        .build();
}
複数のインターセプタを同じファクトリまたはコンテナーに追加できます。

intercept メソッドが実行され、before メッセージが処理され、別のメッセージが返されることがあります。

別のメッセージが返された場合に備えて、元のハンドラーの値を含む SqsHeaders.SQS_RECEIPT_HANDLE_HEADER を追加して、処理後に元のメッセージが確認されるようにすることが重要です。また、SqsHeaders.SQS_MESSAGE_ID_HEADER は常に存在する必要があります。
intercept メソッドは null を返してはなりません。

afterProcessing メソッドは、メッセージが処理されて ErrorHandler が呼び出された後、メッセージが確認応答される前に実行されます。

8.5. エラー処理

デフォルトでは、リスナーによってスローされたエラーのあるメッセージは確認されず、visibility timeout の有効期限が切れた後にメッセージを再度ポーリングできます。

あるいは、フレームワークは、リスナーの実行が失敗した後に呼び出される ErrorHandler および AsyncErrorHandler インターフェースを提供します。

public interface ErrorHandler<T> {

    default void handle(Message<T> message, Throwable t) {
    }

    default void handle(Collection<Message<T>> messages, Throwable t) {
    }

}
public interface AsyncErrorHandler<T> {

    default CompletableFuture<Void> handle(Message<T> message, Throwable t) {
        return CompletableFutures.failedFuture(t);
    }

    default CompletableFuture<Void> handle(Collection<Message<T>> messages, Throwable t) {
        return CompletableFutures.failedFuture(t);
    }

}

自動構成ファクトリを使用する場合は、@Bean を宣言するだけでエラーハンドラーが設定されます。

@Bean
public ErrorHandler<Object> errorHandler() {
    return new ErrorHandler<Object>() {
        @Override
        public void handle(Message<Object> message, Throwable t) {
            // error handling logic
            // throw if the message should not be acknowledged
        }
    }}

あるいは、実装を MessageListenerContainerFactory で設定するか、MessageListenerContainer で直接設定することもできます。

@Bean
public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
    return SqsMessageListenerContainerFactory
        .builder()
        .sqsAsyncClientSupplier(BaseSqsIntegrationTest::createAsyncClient)
        .errorHandler(new ErrorHandler<Object>() {
            @Override
            public void handle(Message<Object> message, Throwable t) {
                // error handling logic
            }
        })
        .build();
}

エラーハンドラーの実行が成功した場合、つまりエラーハンドラーからエラーがスローされなかった場合、メッセージは回復されたとみなされ、確認応答構成に従って確認応答されます。

メッセージを承認すべきではなく、ON_SUCCESS 承認モードが設定されている場合は、エラーを伝播することが重要です。エラーが発生した場合に単純にアクションを実行する場合は、代わりに interceptor を使用し、失敗した実行を検出するために throwable 引数の存在をチェックする必要があります。

8.6. メッセージ変換とペイロードの逆直列化

ペイロードは、MappingJackson2MessageConverter を使用して、@SqsListener アノテーション付きメソッド用に JSON から自動的に逆直列化されます。

Spring Boot の自動構成を使用する場合、Spring コンテキストに単一の ObjectMapper がある場合、そのようなオブジェクトマッパーがメッセージの変換に使用されます。これには、Spring Boot の自動構成自体によって提供されるものも含まれます。別の ObjectMapper の構成については、"@SqsListeners のグローバル構成" を参照してください。

手動で作成された MessageListenersMessageInterceptorErrorHandler コンポーネント、またはリスナーメソッドでの interfaces または inheritance の使用などのよりきめ細かい変換の場合、ペイロードの逆直列化には型マッピングが必要です。

デフォルトでは、フレームワークは、ペイロードを逆直列化する必要がある完全修飾クラス名 (FQCN) を含む Sqs_MA_JavaType という名前の MessageHeader を検索します。そのようなヘッダーが見つかった場合、メッセージは提供されたクラスに自動的に逆直列化されます。

SqsContainerOptions 内に構成済みの MessagingMessageConverter インスタンスを提供することで、さらに構成を実現できます。

型マッピングが設定されている場合、または型情報がヘッダーに追加されている場合、ペイロードはメッセージがポーリングされた直後に逆直列化されます。それ以外の場合、@SqsListener アノテーション付きメソッドの場合、メッセージがリスナーに送信される直前にペイロードが逆直列化されます。@SqsListener メソッドで使用されるカスタム MessageConverter インスタンスの提供については、"@SqsListeners のグローバル構成" を参照してください。

8.6.1. MessagingMessageConverter の構成

このフレームワークは、MessagingMessageConverter インターフェースを実装する SqsMessagingMessageConverter を提供します。

public interface MessagingMessageConverter<S> {

    Message<?> toMessagingMessage(S source);

    S fromMessagingMessage(Message<?> message);

}

デフォルトのヘッダーベースの型 マッピングは、setPayloadTypeHeader メソッドを使用して、別のヘッダー名を使用するように構成できます。

より複雑なマッピングは、デフォルトのヘッダーベースのマッピングをオーバーライドする setPayloadTypeMapper メソッドを使用して実現できます。このメソッドは、受信メッセージに適用される Function<Message<?>, Class<?>> payloadTypeMapper を受け取ります。

デフォルトの MappingJackson2MessageConverter は、setPayloadMessageConverter メソッドを使用して置き換えることができます。

このフレームワークは、HeaderMapper インターフェースを実装し、SqsMessagingMessageConverter によって呼び出される SqsHeaderMapper も提供します。別の HeaderMapper 実装を提供するには、setHeaderMapper メソッドを使用します。

このような構成の例は次のとおりです。

// Create converter instance
SqsMessagingMessageConverter messageConverter = new SqsMessagingMessageConverter();

// Configure Type Header
messageConverter.setPayloadTypeHeader("myTypeHeader");

// Configure Header Mapper
SqsHeaderMapper headerMapper = new SqsHeaderMapper();
headerMapper.setAdditionalHeadersFunction(((sqsMessage, accessor) -> {
    accessor.setHeader("myCustomHeader", "myValue");
    return accessor.toMessageHeaders();
}));
messageConverter.setHeaderMapper(headerMapper);

// Configure Payload Converter
MappingJackson2MessageConverter payloadConverter = new MappingJackson2MessageConverter();
payloadConverter.setPrettyPrint(true);
messageConverter.setPayloadMessageConverter(payloadConverter);

// Set MessageConverter to the factory or container
factory.configure(options -> options.messageConverter(messageConverter));

8.6.2. リスナーメソッドのインターフェースとサブクラス

インターフェースとサブクラスは、type mapper を構成することで、@SqsListener アノテーション付きメソッドで使用できます。

messageConverter.setPayloadTypeMapper(message -> {
    String eventTypeHeader = message.getHeaders().get("myEventTypeHeader", String.class);
    return "eventTypeA".equals(eventTypeHeader)
        ? MyTypeA.class
        : MyTypeB.class;
});

そして、リスナーメソッドで次のようにします。

@SpringBootApplication
public class SqsApplication {

    public static void main(String[] args) {
        SpringApplication.run(SqsApplication.class, args);
    }

    // Retrieve the converted payload
    @SqsListener("myQueue")
    public void listen(MyInterface message) {
        System.out.println(message);
    }

    // Or retrieve a Message with the converted payload
    @SqsListener("myOtherQueue")
    public void listen(Message<MyInterface> message) {
        System.out.println(message);
    }
}

8.7. メッセージの確認

SQS では、メッセージの承認はキューからメッセージを削除することと同じです。多数の Acknowledgement 戦略が利用可能であり、SqsContainerOptions 経由で構成できます。オプションで、成功または失敗した確認応答の後に実行されるコールバックアクションを追加できます。

可能な構成の例を次に示します。

@Bean
SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainerFactory
            .builder()
            .configure(options -> options
                    .acknowledgementMode(AcknowledgementMode.ALWAYS)
                    .acknowledgementInterval(Duration.ofSeconds(3))
                    .acknowledgementThreshold(5)
                    .acknowledgementOrdering(AcknowledgementOrdering.ORDERED)
            )
            .sqsAsyncClient(sqsAsyncClient)
            .build();
}

各オプションについては、次のセクションで説明します。

すべてのオプションは、single message メッセージリスナーと batch メッセージリスナーの両方で使用できます。

8.7.1. 確認応答モード

  • ON_SUCCESS - 処理が成功した後、メッセージまたはメッセージのバッチを確認します。

  • ALWAYS - 処理が成功またはエラーを返した後、メッセージまたはメッセージのバッチを確認します。

  • MANUAL - フレームワークはメッセージを自動的に承認せず、Acknowledgement オブジェクトはリスナーメソッドで受信できます。

8.7.2. 確認応答のバッチ処理

acknowledgementInterval および acknowledgementThreshold オプションは、確認応答のバッチ処理を有効にします。確認応答は、interval で指定された時間、または確認応答するメッセージの数が threshold に達した後に実行されます。

acknowledgementInterval を Duration.ZERO に設定すると、定期的な確認応答が無効になり、確認応答するメッセージの数が指定された acknowledgementThreshold に達した場合にのみ実行されます。

acknowledgementThreshold を 0 に設定すると、メッセージ数ごとの確認応答が無効になり、メッセージは指定された acknowldgementInterval でのみ確認応答されます。

確認応答を使用する場合、バッチメッセージは、それぞれのバッチが確認されるまで SQS の目的で実行中のままになります。この戦略を構成するときは、MessageVisibility を考慮する必要があります。
即時承認

acknowledgementInterval と acknowledgementThreshold の両方をそれぞれ Duration.ZERO と 0 に設定すると、Immediate Acknowledging が有効になります。

この構成では、メッセージは処理後に順次確認応答され、メッセージは正常に確認応答された後にのみ処理されたとみなされます。

即時確認によってエラーが発生した場合、メッセージ処理は失敗したとみなされ、指定された visibilityTimeout の後に再試行されます。

8.7.3. 手動承認

確認応答は、SqsContainerOptions で AcknowledgementMode.MANUAL を設定することによって手動で処理できます。手動確認は確認のバッチ処理と組み合わせて使用できます。メッセージは確認のためにキューに入れられますが、確認のしきい値の 1 つに達するまで実行されません。即時確認と組み合わせて使用することもできます。

Acknowledgement#acknowledge および Acknowledgement#acknowledgeAsync メソッドは、MANUAL 確認応答モードで受信したメッセージを確認するためにも使用できます。

次の引数をリスナーメソッドで使用して、手動で確認応答することができます。

Acknowledgement

Acknowledgement インターフェースは、ListenerMode.SINGLE_MESSAGE でメッセージを確認するために使用できます。

public interface Acknowledgement {

    /**
     * Acknowledge the message.
     */
    void acknowledge();

    /**
     * Asynchronously acknowledge the message.
     */
    CompletableFuture<Void> acknowledgeAsync();

}
BatchAcknowledgement

BatchAcknowledgement インターフェースは、ListenerMode.BATCH でメッセージを確認するために使用できます。

acknowledge(Collection<Message<T>) メソッドを使用すると、部分的なバッチの確認が可能になります。

public interface BatchAcknowledgement<T> {

    /**
     * Acknowledge all messages from the batch.
     */
    void acknowledge();

    /**
     * Asynchronously acknowledge all messages from the batch.
     */
    CompletableFuture<Void> acknowledgeAsync();

    /**
     * Acknowledge the provided messages.
     */
    void acknowledge(Collection<Message<T>> messagesToAcknowledge);

    /**
     * Asynchronously acknowledge the provided messages.
     */
    CompletableFuture<Void> acknowledgeAsync(Collection<Message<T>> messagesToAcknowledge);

}

8.7.4. 確認応答の順序付け

  • PARALLEL - 上記の条件のいずれかが満たされるとすぐにメッセージを確認します - 多くの確認応答呼び出しを並行して行うことができます。

  • ORDERED - 確認応答の 1 つのバッチは、前のバッチが完了した後に実行され、batching 確認応答に対する FIFO の順序が保証されます。

  • ORDERED_BY_GROUP - 確認応答の 1 つのバッチは、同じグループに対する前の確認応答のバッチが完了した後に実行され、メッセージグループ間の並列処理による FIFO 確認応答の順序付けが保証されます。FIFO キューでのみ使用できます。

8.7.5. 確認応答のデフォルト

確認応答のデフォルトは、Standard および FIFO SQS キューで異なります。

標準 SQS
  • 確認応答間隔: 一秒

  • 確認応答のしきい値: 10 件のメッセージ

  • 確認応答の順序付け: PARALLEL

FIFO SQS
  • 確認応答間隔: ゼロ (即時)

  • 確認応答のしきい値: ゼロ (即時)

  • 確認応答の順序付け: 即時確認の場合は PARALLEL、バッチ処理が有効な場合は ORDERED (上記のデフォルトの一方または両方が上書きされます)。

処理の順序が保証されるため、FIFO のデフォルトは PARALLEL です。これにより、前のバッチが確認されるまで、特定の MessageGroup からのメッセージがポーリングされなくなります。このインターフェースの実装は、確認応答の実行が成功または失敗で完了した後に実行されます。

8.7.6. 確認結果コールバック

このフレームワークは、SqsMessageListenerContainer または SqsMessageListenerContainerFactory に追加できる AcknowledgementResultCallback および AsyncAcknowledgementCallback インターフェースを提供します。

public interface AcknowledgementResultCallback<T> {

    default void onSuccess(Collection<Message<T>> messages) {
    }

    default void onFailure(Collection<Message<T>> messages, Throwable t) {
    }

}
public interface AsyncAcknowledgementResultCallback<T> {

    default CompletableFuture<Void> onSuccess(Collection<Message<T>> messages) {
        return CompletableFuture.completedFuture(null);
    }

    default CompletableFuture<Void> onFailure(Collection<Message<T>> messages, Throwable t) {
        return CompletableFuture.completedFuture(null);
    }

}
@Bean
public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
    return SqsMessageListenerContainerFactory
        .builder()
        .sqsAsyncClient(sqsAsyncClient)
        .acknowledgementResultCallback(getAcknowledgementResultCallback())
        .build();
}
immediate acknowledgement が設定されている場合 (FIFO キューのデフォルトと同様)、バッチ内の次のメッセージが処理されるにコールバックが実行され、次のメッセージ処理はコールバックの完了を待ちます。これは、メッセージの削除を再試行したり、FIFO キューで確認応答が失敗した場合に重複処理を防ぐためにコンテナーを停止したりするなどのアクションを実行する場合に役立ちます。batch parallel processing の場合、Standard キューのデフォルトと同様に、コールバックの実行は非同期で行われます。

8.8. @SqsListeners のグローバル構成

SqsListenerConfigurer Bean を提供することで、@SqsListener のすべてのコンテナーに一連の構成を設定できます。

@FunctionalInterface
public interface SqsListenerConfigurer {

    void configure(EndpointRegistrar registrar);

}

次の属性をレジストラで構成できます。

  • setMessageHandlerMethodFactory - リスナーメソッドをラップする invocableHandlerMethod インスタンスの作成に使用される別のファクトリを提供します。

  • setListenerContainerRegistry - MessageListenerContainers の登録に使用される別の MessageListenerContainerRegistry 実装を提供します

  • setMessageListenerContainerRegistryBeanName - MessageListenerContainerRegistry の取得に使用する別の Bean 名を指定します

  • setObjectMapper - リスナーメソッドでペイロードを逆直列化するために使用される ObjectMapper インスタンスを設定します。これが使用される場所の詳細については、"メッセージ変換とペイロードの逆直列化" を参照してください。

  • manageMessageConverters - メッセージの変換に使用されるメッセージコンバーターのリストへのアクセスを提供します。デフォルトでは、StringMessageConverterSimpleMessageConverterMappingJackson2MessageConverter が使用されます。

  • manageArgumentResolvers - リスナーメソッドの引数を解決するために使用される引数リゾルバーのリストへのアクセスを許可します。リゾルバーの順序は重要です。PayloadMethodArgumentResolver はデフォルトとして使用されるため、通常は最後に置く必要があります。

簡単な例は次のとおりです。

@Bean
SqsListenerConfigurer configurer(ObjectMapper objectMapper) {
    return registrar -> registrar.setObjectMapper(objectMapper);
}
任意の数の SqsListenerConfigurer Bean をコンテキストに登録できます。すべてのインスタンスはアプリケーションの起動時に検索され、反復処理されます。

8.9. メッセージ処理スループット

アプリケーションのスループットを調整するには、次のオプションを使用できます。構成が SqsContainerOptions と @SqsListener アノテーションの両方で使用できる場合、アノテーション値があればそれが優先されます。

8.9.1. SqsContainerOptions および @SqsListener プロパティ

maxConcurrentMessages

SqsContainerOptions アノテーションまたは @SqsListener アノテーションのいずれかに設定できます。特定の時点でコンテナーによって処理されるメッセージの最大数を表します。デフォルトは 10 です。

この値はキューごとに適用されるため、コンテナー内のインフライトメッセージの数は最大 (コンテナー内のキューの数 * maxConcurrentMessages) になります。

確認応答のバッチ処理を使用する場合、メッセージは確認応答キューに配信された時点で送信中ではないとみなされます。この場合、AWS SQS コンソール上の実際のインフライトメッセージの数は、設定された値よりも大きくなる可能性があります。即時確認を使用する場合、メッセージは確認された後に送信中でないとみなされるか、エラーがスローされます。
maxMessagesPerPoll

SqsContainerOptions または @SqsListener アノテーションに設定します。1 回のポーリングで SQS キューに返されるメッセージの最大数を表し、最大 10 です。この値は maxConcurrentMessages 以下である必要があります。デフォルトは 10 です。

キューに多くのメッセージがある場合でも、ポーリングによって返されるメッセージが指定よりも少ない場合があることに注意してください。詳細については、AWS のドキュメントを参照してください。

pollTimeout

SqsContainerOptions アノテーションまたは @SqsListener アノテーションのいずれかに設定できます。ポーリングの最大期間を表します。値が大きいほど long polls を表し、メッセージの完全なバッチを受信する確率が高くなります。デフォルトは 10 秒です。

maxDelayBetweenPolls

SqsContainerOptions に設定します。部分バッチの取得を試行する前に、コンテナーが maxMessagesPerPoll 許可が使用可能になるまで待機する最大時間を表します (そのように構成されている場合)。この待機はキューごとに適用され、この点に関して、あるキューが別のキューに干渉することはありません。デフォルトは 10 秒です。

8.9.2. デフォルトのポーリング動作

デフォルトでは、フレームワークはすべてのキューを low throughput mode で開始し、一度に 1 つのメッセージのポーリングを実行します。ポーリングで少なくとも 1 つのメッセージが返されると、キューは high throughput mode に入り、キューに対して (maxConcurrentMessages/maxMessagesPerPoll) 並列ポーリングを実行して maxConcurrentMessages メッセージを実行しようとします。メッセージが返されないポーリングでは、少なくとも 1 つのメッセージが返されるまで low throughput mode が再度トリガーされ、その後 high throughput mode が再度トリガーされます。

maxDelayBetweenPolls の後、maxMessagesPerPoll 許可が利用できない場合は、その差分、つまり、これまでに処理されたメッセージがあればその数をポーリングします。

E.g. コンテナーが maxConcurrentMessages = 20、maxMessagesPerPoll = 10、maxDelayBetweenPolls = 5 秒、pollTimeout = 10 秒に構成されているシナリオを考えてみましょう。

コンテナーは low throughput mode で開始します。これは、10 個のメッセージに対して 1 回のポーリングを試行することを意味します。メッセージが返された場合は high throughput mode に切り替わり、それぞれ 10 個のメッセージに対して最大 2 つの同時ポーリングが行われます。20 件のメッセージがすべて取得された場合、メッセージが処理されるまでポーリングは試行されません。maxDelayBetweenPolls 6 メッセージの 5 秒後に処理が完了すると、フレームワークは 6 つのメッセージをポーリングします。キューが枯渇し、ポーリングでメッセージが返されない場合、再び low throughput モードに入り、一度に 1 つのポーリングのみが実行されます。

8.9.3. BackPressureMode の構成

次の BackPressureMode 値を SqsContainerOptions に設定して、ポーリング動作を構成できます。

  • AUTO - 前のセクションで説明したデフォルトモード。

  • ALWAYS_POLL_MAX_MESSAGES - 部分的なバッチポーリングを無効にします。つまり、コンテナーがポーリングごとに 10 メッセージに対して構成されている場合、コンテナーは 10 メッセージが処理されるまで待機してから、次の 10 メッセージのポーリングを試行します。スループットを犠牲にしてポーリング数を減らして最適化する場合に役立ちます。

  • FIXED_HIGH_THROUGHPUT - 前のセクションで説明したように、部分的なバッチポーリングを試行しながら、low throughput mode を無効にします。最終的に low throughput mode に切り替えるよりも、アイドルキューへの並列ポーリングを行うリスクの方が望ましい、非常に高スループットのシナリオに役立ちます。

AUTO 設定は、高スループットを含むほとんどの使用例に対してバランスがとれている必要があります。

8.10. ブロッキングおよびノンブロッキング (非同期) コンポーネント

SQS 統合は、AWS SDK 2.0 の CompletableFuture ベースの非同期機能を利用して、完全にノンブロッキングのインフラストラクチャを提供します。メッセージのポーリング、メッセージの可視性の変更、メッセージの確認に関わるすべての処理は、非同期のノンブロッキング方式で実行されます。これにより、アプリケーションの全体的なスループットが向上します。

MessageListenerMessageInterceptorErrorHandler 実装が MesssageListenerContainer または MesssageListenerContainerFactory に設定されている場合、これらはフレームワークによって適応されます。このようにして、ブロッキングコンポーネントとノンブロッキングコンポーネントを相互に組み合わせて使用できます。

@SqsListener アノテーションが付けられたリスナーメソッドは、単純な値を返すことができます。void または CompletableFuture<Void>。リスナーメソッドは、それぞれ MessagingMessageListenerAdapter または AsyncMessagingMessageListenerAdapter でラップされます。

より高いスループットを達成するには、少なくともメッセージリスナー interceptors および error handlers のより単純なロジックについては、非同期バリアントを使用することをお勧めします。

8.10.1. コンポーネントのスレッド化とブロック化

メッセージ処理は常に、デフォルトまたは提供された TaskExecutor からフレームワークスレッドで開始されます。

非同期コンポーネントが呼び出され、実行が別のスレッドのフレームワークに戻る場合、そのスレッドは blocking コンポーネントが見つかるまで使用され、その後、ブロック (つまり SqsAsyncClient または HttpClient スレッド) を避けるために実行が TaskExecutor スレッドに戻ります。

実行が blocking コンポーネントに到達するまでにそのコンポーネントがすでにフレームワークスレッド上にある場合は、過度のスレッド割り当てとホッピングを避けるために同じスレッド内に残ります。

async メソッドを使用する場合、受信スレッドをブロックしないことが重要です。これは全体のパフォーマンスに非常に悪影響を与える可能性があります。スレッドブロックロジックを使用する必要がある場合は、ブロックロジックを別のスレッドで実行する必要があります。CompletableFuture.supplyAsync(() → myLogic(), myExecutor) を使用します。それ以外の場合は、sync インターフェースを使用する必要があります。

8.10.2. TaskExecutor の提供

デフォルトの TaskExecutor は ThreadPoolTaskExecutor であり、別の componentTaskExecutor サプライヤーを SqsContainerOptions に設定できます。

カスタムエグゼキュータを提供する場合、作成されるすべてのスレッドをサポートするように構成することが重要です。これは (maxConcurrentMessages * キューの合計数) である必要があります。

ブロッキングコンポーネント間の不要なスレッドホッピングを避けるために、MessageExecutionThreadFactory をエグゼキュータに設定する必要があります。

8.11. IAM パーミッション

Spring Cloud AWS SQS には次の IAM 権限が必要です。

キューにメッセージを送信する

sqs:SendMessage

キューからメッセージを受信する

sqs:ReceiveMessage

キューからメッセージを削除する

sqs:DeleteMessage

sqsListener を SimpleMessageListenerContainerFactory と一緒に使用するには、以下も追加する必要があります。

sqs:GetQueueAttributes

ARN の代わりに Sqs 名で SqsListener を使用するには、次のものが必要です。

sqs:GetQueueUrl

SQS へのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sqs:DeleteMessage",
                "sqs:ReceiveMessage",
                "sqs:SendMessage",
                "sqs:GetQueueAttributes",
                "sqs:GetQueueUrl"
            ],
            "Resource": "yourARN"
        }

9. Secrets Manager の統合

秘密マネージャー [Amazon] は、アプリケーション、サービス、IT リソースへのアクセスに必要な秘密を保護できます。このサービスを使用すると、データベース認証情報、API キー、その他のシークレットをライフサイクル全体にわたって簡単にローテーション、管理、取得できます。

Spring Cloud AWS では、Spring Boot 構成インポート機能を介して Secrets Manager から構成プロパティをロードするためのサポートが追加されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-secrets-manager</artifactId>
</dependency>

9.1. 外部設定のロード

Secrets Manager からシークレットを取得して Spring の環境プロパティに追加するには、spring.config.import プロパティを application.properties に追加します。

例: Secrets Manager のシークレット名が /secrets/database-secrets であると仮定します。

spring.config.import=aws-secretsmanager:/secrets/database-secrets

指定された名前のシークレットが Secrets Manager に存在しない場合、アプリケーションは起動に失敗します。アプリケーションにシークレット値が必要なく、シークレットが欠落している場合でも起動を続行する必要がある場合は、プレフィックスの前に optional を追加します。

spring.config.import=optional:aws-secretsmanager:/secrets/database-secrets

複数のシークレットをロードするには、名前を ; で区切ります。

spring.config.import=aws-secretsmanager:/secrets/database-secrets;/secrets/webclient-secrets

一部のシークレットが必須で、その他のシークレットがオプションである場合は、spring.config.import プロパティに別のエントリとしてリストします。

spring.config.import[0]=optional:aws-secretsmanager=/secrets/required-secret
spring.config.import[1]=aws-secretsmanager=/secrets/optional-secret

フェッチされたシークレットは、@Value で参照したり、@ConfigurationProperties クラスにバインドしたり、application.properties ファイルで参照したりできます。

9.1.1. Key-Value (JSON) シークレットの使用

spring.config.import で解決されたシークレットは、application.properties でも参照できます。JSON 内の SecretString のコンテンツの場合、すべてのトップレベル JSON キーがプロパティとして Spring 環境に追加されます。

例: 次の JSON 構造を含むファイル mycreds.json の場合:

{
      "username": "saanvi",
      "password": "EXAMPLE-PASSWORD"
}

シークレットは次のコマンドで作成されます。

$ aws secretsmanager create-secret --name /secrets/database-secrets --secret-string file://mycreds.json

spring.config.import エントリが application.properties に追加されます。

spring.config.import=aws-secretsmanager:/secrets/database-secrets

シークレット値は、JSON キー名によって参照できます。

@Value("${username}"
private String username;

@Value("${password}"
private String password;

9.1.2. プレーンテキストシークレットの使用

SecretString がプレーンテキストである場合、または SecretBinary を使用している場合は、シークレット名を使用してその値を取得します。例: JDBC を /secrets/my-certificate という名前のプレーンテキストシークレット型として保存します。

$ aws secretsmanager create-secret --name /secrets/prod/jdbc-url --secret-string jdbc:url

spring.config.import エントリが application.properties に追加されます。

spring.config.import=aws-secretsmanager:/secrets/prod/jdbc-url

シークレット値は、シークレット名を参照することで取得できます。

spring.datasource.url=${jdbc-url}

9.1.3. プロパティキーにプレフィックスを追加する

プロパティキーの衝突を回避するために、シークレットから解決された各プロパティに追加されるプロパティキープレフィックスを構成できます。

例として、/secrets/database-secrets という名前の次の JSON シークレットを考えてみましょう。

{
      "username": "saanvi",
      "password": "EXAMPLE-PASSWORD"
}

デフォルトでは、usernmame および password プロパティが Spring 環境に追加されます。プロパティキーにプレフィックスを追加するには、シークレット名に ?prefix= を追加して spring.config.import プロパティを構成します。

spring.config.import=optional:aws-secretsmanager:/secrets/database-secrets?prefix=db.

このような構成では、プロパティ db.username および db.password が Spring 環境に追加されます。

プレフィックスは、Secrets Manager によって返されるすべてのプロパティ名にそのまま追加されます。キー名をプレフィックスとキー名の間にドットで区切る場合は、必ずプレフィックスの末尾にドットを追加してください。

9.2. SecretsManagerClient の使用

スターターは、SecretsManagerClient Bean を自動的に構成し、Spring アプリケーションコンテキストに登録します。SecretsManagerClient Bean を使用すると、シークレットを命令的に作成または取得できます。

import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.CreateSecretRequest;

...
@Autowired
private SecretsManagerClient secretsManagerClient;
...
secretsManagerClient.createSecret(CreateSecretRequest.builder().name(name).secretString(secret).build());

9.3. SecretsManagerClient のカスタマイズ

spring.config.import でカスタム SecretsManagerClient を使用するには、BootstrapRegistryInitializer の実装を提供します。例:

package com.app;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;

import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;

public class SecretsManagerBootstrapConfiguration implements BootstrapRegistryInitializer {

    @Override
    public void initialize(BootstrapRegistry registry) {
        registry.register(SecretsManagerClient.class, context -> {
            AwsCredentialsProvider awsCredentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create("yourAccessKey", "yourSecretKey"));
            return SecretsManagerClient.builder().credentialsProvider(awsCredentialsProvider).region(Region.EU_WEST_2).build();
        });
    }
}

このクラスは META-INF/spring.factories の org.springframework.boot.BootstrapRegistryInitializer キーにリストされている必要があることに注意してください。

org.springframework.boot.BootstrapRegistryInitializer=com.app.SecretsManagerBootstrapConfiguration

自動構成された SecretsManagerClient を使用したいが、基礎となる SDKClient または ClientOverrideConfiguration を変更する場合は、型 AwsClientConfigurerSecretsManager の Bean を登録する必要があります。その後、自動構成により、指定された値で SecretsManagerClient Bean が構成されます。例:

package com.app;

import io.awspring.cloud.autoconfigure.config.secretsmanager.AwsSecretsManagerClientCustomizer;
import java.time.Duration;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder;

class SecretsManagerBootstrapConfiguration implements BootstrapRegistryInitializer {

    @Override
    public void initialize(BootstrapRegistry registry) {
        registry.register(AwsSecretsManagerClientCustomizer.class,
            context -> new AwsSecretsManagerClientCustomizer() {

                @Override
                public ClientOverrideConfiguration overrideConfiguration() {
                    return ClientOverrideConfiguration.builder().apiCallTimeout(Duration.ofMillis(500))
                            .build();
                }

                @Override
                public SdkHttpClient httpClient() {
                    return ApacheHttpClient.builder().connectionTimeout(Duration.ofMillis(1000)).build();
                }
            });
    }
}

9.4. PropertySource リロード

一部のアプリケーションでは、外部プロパティソースの変更を検出し、新しい構成を反映するために内部ステータスを更新する必要がある場合があります。Spring Cloud AWS Secrets Manager 統合のリロード機能は、関連するシークレット値が変更されたときにアプリケーションのリロードをトリガーできます。

デフォルトでは、この機能は無効になっています。これを有効にするには、spring.cloud.aws.secretsmanager.reload.strategy 構成プロパティ (たとえば、application.properties ファイル内) を使用します。

次のレベルのリロードがサポートされています (spring.cloud.aws.secretsmanager.reload.strategy プロパティを設定することにより)。

  • refresh (default): @ConfigurationProperties または @RefreshScope のアノテーションが付けられた構成 Bean のみがリロードされます。このリロードレベルは、Spring Cloud Context のリフレッシュ機能を利用します。

  • restart_context: Spring ApplicationContext 全体が正常に再起動されます。Bean は新しい構成で再作成されます。再起動コンテキスト機能が適切に動作するには、再起動アクチュエーターエンドポイントを有効にして公開する必要があります。

management:
  endpoint:
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: restart

リロード機能がデフォルト設定 (refresh モード) で有効になっていると仮定すると、シークレットが変更されると次の Bean がリフレッシュされます。

@Configuration
@ConfigurationProperties(prefix = "bean")
public class MyConfig {

    private String message = "a message that can be changed live";

    // getter and setters

}

変更が効果的に行われたことを確認するには、次のようにメッセージを定期的に出力する別の Bean を作成します。

@Component
public class MyBean {

    @Autowired
    private MyConfig config;

    @Scheduled(fixedDelay = 5000)
    public void hello() {
        System.out.println("The message is: " + config.getMessage());
    }
}

リロード機能は、構成マップとシークレットから構成を定期的に再作成し、変更されたかどうかを確認します。spring.cloud.aws.secretsmanager.reload.period を使用してポーリング期間を構成できます (デフォルト値は 1 分)。

9.5. 構成

Secrets Manager の Spring Boot スターターには、次の構成オプションが用意されています。

名前

説明

必須

デフォルト値

spring.cloud.aws.secretsmanager.endpoint

SecretsManagerClient によって使用されるエンドポイントを構成します。

いいえ

null

spring.cloud.aws.secretsmanager.region

SecretsManagerClient によって使用される領域を構成します。

いいえ

null

spring.cloud.aws.secretsmanager.reload.strategy

Enum

refresh

リロードを開始するときに使用する戦略 (refreshrestart_context)

spring.cloud.aws.secretsmanager.reload.period

Duration

15s

変更確認期間

spring.cloud.aws.secretsmanager.reload.max-wait-time-for-restart

Duration

2s

restart_context 戦略が使用されている場合の、プロパティソースの変更の検出からアプリケーションコンテキストの再起動までの最大時間。

9.6. IAM パーミッション

Spring Cloud AWS には、次の IAM 権限が必要です。

秘密の価値を得る:

secretsmanager:GetSecretValue

Secrets Manager へのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "yourArn"
        }
    ]
}

10. パラメーターストアの統合

Spring Cloud AWS では、Spring Boot 構成インポート機能を介してパラメーターストアから構成プロパティをロードするためのサポートが追加されています。

Spring Cloud AWS BOM を使用した Maven 座標:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-parameter-store</artifactId>
</dependency>

10.1. 外部設定のロード

パラメーターストアからパラメーターを取得して Spring の環境プロパティに追加するには、spring.config.import プロパティを application.properties に追加します。

例: パラメーターストアのパラメーターがパス /config/spring に保存されていると仮定します。

パラメーター名 パラメーター値

/config/spring/message

Welcome

/config/spring/httpUrl

external-service:3030/ (英語)

spring.config.import ステートメントを追加すると、次のようになります。

spring.config.import=aws-parameterstore:/config/spring

message および httpUrl という 2 つのパラメーターが環境に追加されます。

パラメーターストアに指定されたパスが存在しない場合、アプリケーションは起動に失敗します。パラメーターストアから取得したパラメーターがアプリケーションに必要なく、パスが見つからない場合でも起動を続行する必要がある場合は、プレフィックスの前に optional を追加します。

spring.config.import=optional:aws-parameterstore:/config/spring

複数のパスからパラメーターをロードするには、名前を ; で区切ります。

spring.config.import=aws-parameterstore:/config/spring;/config/app

一部のパラメーターが必須で、その他のパラメーターがオプションである場合は、spring.config.import プロパティの別のエントリとしてリストします。

spring.config.import[0]=optional:aws-parameterstore=/config/spring
spring.config.import[1]=aws-parameterstore=/config/optional-params/

10.2. SsmClient の使用

スターターは、SsmClient Bean を自動的に構成し、Spring アプリケーションコンテキストに登録します。SsmClient Bean を使用して、パラメーターストアからパラメーターを作成または取得できます。

import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.ssm.SsmClient;

...
@Autowired
private SsmClient ssmClient;
...
ssmClient.getParametersByPath(request -> request.path("/config/spring/")).parameters();

10.3. SsmClient のカスタマイズ

spring.config.import でカスタム SsmClient を使用するには、BootstrapRegistryInitializer の実装を提供します。例:

package com.app;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ssm.SsmClient;

import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;

class ParameterStoreBootstrapConfiguration implements BootstrapRegistryInitializer {

    @Override
    public void initialize(BootstrapRegistry registry) {
        registry.register(SsmClient.class, context -> {
            AwsCredentialsProvider awsCredentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create("yourAccessKey", "yourSecretKey"));
            return SsmClient.builder().credentialsProvider(awsCredentialsProvider).region(Region.EU_WEST_2).build();
        });
    }
}

このクラスは META-INF/spring.factories の org.springframework.boot.BootstrapRegistryInitializer キーにリストされている必要があることに注意してください。

org.springframework.boot.BootstrapRegistryInitializer=com.app.ParameterStoreBootstrapConfiguration

自動構成された SsmClient を使用したいが、基礎となる SDKClient または ClientOverrideConfiguration を変更する場合は、型 AwsClientConfigurerParameterStore の Bean を登録する必要があります。その後、自動構成により、指定された値で SsmClient Bean が構成されます。例:

package com.app;

import io.awspring.cloud.autoconfigure.config.parameterstore.AwsParameterStoreClientCustomizer;
import java.time.Duration;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.ssm.SsmClientBuilder;

class ParameterStoreBootstrapConfiguration implements BootstrapRegistryInitializer {

    @Override
    public void initialize(BootstrapRegistry registry) {
        registry.register(AwsParameterStoreClientCustomizer.class,
            context -> new AwsParameterStoreClientCustomizer() {

                @Override
                public ClientOverrideConfiguration overrideConfiguration() {
                    return ClientOverrideConfiguration.builder().apiCallTimeout(Duration.ofMillis(500))
                            .build();
                }

                @Override
                public SdkHttpClient httpClient() {
                    return ApacheHttpClient.builder().connectionTimeout(Duration.ofMillis(1000)).build();
                }
            });
    }
}

10.4. PropertySource リロード

一部のアプリケーションでは、外部プロパティソースの変更を検出し、新しい構成を反映するために内部ステータスを更新する必要がある場合があります。Spring Cloud AWS パラメーターストア統合のリロード機能は、関連するパラメーター値が変更されたときにアプリケーションのリロードをトリガーできます。

デフォルトでは、この機能は無効になっています。これを有効にするには、spring.cloud.aws.parameterstore.reload.strategy 構成プロパティ (たとえば、application.properties ファイル内) を使用します。

次のレベルのリロードがサポートされています (spring.cloud.aws.parameterstore.reload.strategy プロパティを設定することにより)。

  • refresh (default): @ConfigurationProperties または @RefreshScope のアノテーションが付けられた構成 Bean のみがリロードされます。このリロードレベルは、Spring Cloud Context のリフレッシュ機能を利用します。

  • restart_context: Spring ApplicationContext 全体が正常に再起動されます。Bean は新しい構成で再作成されます。再起動コンテキスト機能が適切に動作するには、再起動アクチュエーターエンドポイントを有効にして公開する必要があります。

management:
  endpoint:
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: restart

リロード機能がデフォルト設定 (refresh モード) で有効になっていると仮定すると、シークレットが変更されると次の Bean がリフレッシュされます。

@Configuration
@ConfigurationProperties(prefix = "bean")
public class MyConfig {

    private String message = "a message that can be changed live";

    // getter and setters

}

変更が効果的に行われたことを確認するには、次のようにメッセージを定期的に出力する別の Bean を作成します。

@Component
public class MyBean {

    @Autowired
    private MyConfig config;

    @Scheduled(fixedDelay = 5000)
    public void hello() {
        System.out.println("The message is: " + config.getMessage());
    }
}

リロード機能は、構成マップとシークレットから構成を定期的に再作成し、変更されたかどうかを確認します。spring.cloud.aws.parameter.reload.period を使用してポーリング期間を構成できます (デフォルト値は 1 分)。

10.5. 構成

パラメーターストアの Spring Boot スターターには、次の構成オプションが用意されています。

名前 説明 必須 デフォルト値

spring.cloud.aws.parameterstore.endpoint

SsmClient によって使用されるエンドポイントを構成します。

いいえ

null

spring.cloud.aws.parameterstore.region

SsmClient によって使用される領域を構成します。

いいえ

null

spring.cloud.aws.parameterstore.reload.strategy

Enum

refresh

リロードを開始するときに使用する戦略 (refreshrestart_context)

spring.cloud.aws.parameterstore.reload.period

Duration

15s

変更確認期間

spring.cloud.aws.parameterstore.reload.max-wait-time-for-restart

Duration

2s

restart_context 戦略が使用されている場合の、プロパティソースの変更の検出からアプリケーションコンテキストの再起動までの最大時間。

10.6. IAM パーミッション

Spring Cloud AWS には、次の IAM 権限が必要です。

特定のパスからパラメーターを取得する

ssm:GetParametersByPath

パラメーターストアへのアクセスを許可するサンプル IAM ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ssm:GetParametersByPath",
            "Resource": "yourArn"
        }
    ]
}

11. CloudWatch メトリクス

Spring Cloud AWS は、Micrometer CloudWatch 統合のための Spring Boot 自動構成を提供します。メトリクスを CloudWatch に送信するには、micrometer-registry-cloudwatch モジュールに依存関係を追加します。

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-cloudwatch2</artifactId>
</dependency>

さらに、CloudWatch 統合には、management.cloudwatch.metrics.export.namespace 構成プロパティに指定された値が必要です。

CloudWatch 統合を構成するには、次の構成プロパティを使用できます。

プロパティ default 説明

management.cloudwatch.metrics.export.namespace

メトリクスを CloudWatch に送信するときに使用される名前空間。このプロパティは必須であり、null であってはなりません。

management.cloudwatch.metrics.export.step

1m

メトリクスが CloudWatch に送信される間隔。デフォルトは 1 分です。

spring.cloud.aws.cloudwatch.enabled

true

CloudWatch 統合を有効にする必要がある場合。このプロパティは、ローカル開発プロファイルの場合、false に設定する必要があります。

spring.cloud.aws.cloudwatch.endpoint

デフォルトのエンドポイントを上書きします。

spring.cloud.aws.cloudwatch.region

CloudWatch 統合の特定の領域。

12. 2.x から 3.x への移行

移行ガイドは進行中です。

2.x から 3.x に変更されたプロパティは次のとおりです。

バージョン 2.x バージョン 3.x

cloud.aws.credentials.access-key

spring.cloud.aws.credentials.access-key

cloud.aws.credentials.secret-key

spring.cloud.aws.credentials.secret-key

cloud.aws.region.static

spring.cloud.aws.region.static

aws.paramstore.region

spring.cloud.aws.parameterstore.region

aws.secretsmanager.region

spring.cloud.aws.secretsmanager.region

management.metrics.export.cloudwatch.*

management.cloudwatch.metrics.export.*

3.x で削除されたプロパティを以下に示します。

  • コグニートのプロパティ

    • spring.cloud.aws.security.cognito.app-client-id

    • spring.cloud.aws.security.cognito.user-pool-id

    • spring.cloud.aws.security.algorithm

    • spring.cloud.aws.security.region

    • spring.cloud.aws.security.enabled

Spring Security OAuth2 サポートと Spring Boot の統合を使用すると、同じ動作を有効にすることができます。

spring.security.oauth2.resourceserver.jwt.issuer-uri=http://127.0.0.1:4566/us-east-1_f865f8979c4d4361b6af703db533dbb4
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://127.0.0.1:4566/us-east-1_f865f8979c4d4361b6af703db533dbb4/.well-known/jwks.json

上の例では、URI を LocalStack の Cognito サーバーに設定しています。

13. 構成プロパティ

Spring Cloud AWS に関連するすべての構成プロパティのリストを表示するには、付録ページを確認してください。