Spring Cloud AWS simplifies using AWS managed services in a Spring and Spring Boot applications. It offers a convenient way to interact with AWS provided services using well-known Spring idioms and APIs.

3.0.0-M1

Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.

1. Using Amazon Web Services

AWS provides a Java SDK to issue requests for the all services provided by the Amazon Web Service platform. While the SDK offers all functionality available on AWS, there is a considerable amount of low level code needed to use it in Spring idiomatic way. Spring Cloud AWS provides application developers already integrated Spring-based modules to consume the most popular AWS services and avoid low level code as much as possible.

Thanks to Spring Cloud AWS modularity you can include only dependencies relevant to the particular AWS service you want to integrate with.

Spring Cloud AWS lets you leverage the power and simplicity of the Spring Framework to:

  • Write and read from Spring Resources backed up by S3

  • Send emails using SES

  • Import environment configuration using ConfigDataLoader from Parameter Store and Secrets Manager

  • Send and receive HTTP notifications from SNS

Other integrations are under development.

It also simplifies creating any non-integrated AWS SDK client by auto-configuring region and credentials providers.

That being said, it is perfectly valid option to use AWS SDK without using Spring Cloud AWS.

Note, that Spring provides support for other AWS services in following projects:

2. Getting Started

This section describes how to get up to speed with Spring Cloud AWS libraries.

2.1. Bill of Materials

The Spring Cloud AWS Bill of Materials (BOM) contains the versions of all the dependencies it uses.

If you’re a Maven user, adding the following to your pom.xml file will allow you omit any Spring Cloud AWS dependency version numbers from your configuration. Instead, the version of the BOM you’re using determines the versions of the used dependencies.

<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 users can achieve the same kind of BOM experience using Spring’s dependency-management-plugin Gradle plugin. For simplicity, the Gradle dependency snippets in the remainder of this document will also omit their versions.

2.2. Starter Dependencies

Spring Cloud AWS offers starter dependencies through Maven to easily depend on different modules of the library. Each starter contains all the dependencies and transitive dependencies needed to begin using their corresponding Spring Cloud AWS module.

For example, if you wish to write a Spring application with S3, you would include the spring-cloud-aws-starter-s3 dependency in your project. You do not need to include the underlying spring-cloud-aws-s3 dependency, because the starter dependency includes it.

A summary of these artifacts are provided below.

Spring Cloud AWS Starter Description Maven Artifact Name

Core

Automatically configure authentication and region selection

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

S3

Provides integrations with S3

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

SES

Provides integrations with SES

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

SNS

Provides integrations with SNS

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

Parameter Store

Provides integrations with AWS Parameter Store

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

Secrets Manager

Provides integrations with AWS Secrets manager

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

2.3. Choosing AWS SDK version

The AWS SDK is released more frequently than Spring Cloud AWS. If you need to use a newer version of the SDK than the one configured by Spring Cloud AWS, add the SDK BOM to the dependency management section making sure it is declared before any other BOM dependency that configures AWS SDK dependencies.

<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 Core

Each Spring Cloud AWS module uses AwsCredentialsProvider and AwsRegionProvider to get the AWS region and access credentials.

Spring Cloud AWS provides a Spring Boot starter to auto-configure the core components.

Maven coordinates, using Spring Cloud AWS BOM:

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

3.1. Credentials

software.amazon.awssdk.auth.credentials.AwsCredentialsProvider is a functional interface that returns the credentials to authenticate and authorize calls to AWS services.

public interface AwsCredentialsProvider {
    AwsCredentials resolveCredentials();
}

By default, Spring Cloud AWS starter auto-configures a DefaultCredentialsProvider, which looks for AWS credentials in this order:

  1. Java System Properties - aws.accessKeyId and aws.secretAccessKey

  2. Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY

  3. Web Identity Token credentials from system properties or environment variables

  4. Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI

  5. Credentials delivered through the Amazon EC2 container service if `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`" environment variable is set and security manager has permission to access the variable,

  6. Instance profile credentials delivered through the Amazon EC2 metadata service

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

property example description

spring.cloud.aws.credentials.access-key

AKIAIOSFODNN7EXAMPLE

The access key to be used with a static provider

spring.cloud.aws.credentials.secret-key

wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

The secret key to be used with a static provider

spring.cloud.aws.credentials.instance-profile

true

Configures an InstanceProfileCredentialsProvider with no further configuration

spring.cloud.aws.credentials.profile.name

default

The name of a configuration profile in the specified configuration file

spring.cloud.aws.credentials.profile.path

~/.aws/credentials

The file path where the profile configuration file is located. Defaults to ~/.aws/credentials if value is not provided

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

The file path where the profile configuration file is located. Defaults to ~/.aws/credentials if value is not provided

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

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. Endpoint

To simplify using services with AWS compatible APIs, or running applications against Localstack, it is possible to configure an endpoint set on all auto-configured AWS clients:

property example description

spring.cloud.aws.endpoint

localhost:4566

endpoint url applied to auto-configured AWS clients

3.4. Customizing AWS Clients

To configure an AWS client with custom HTTP client or ClientOverrideConfiguration, define a bean of type AwsClientConfigurer with a type parameter indicating configured client builder.

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. S3 Integration

S3 allows storing files in a cloud. A Spring Boot starter is provided to auto-configure the various S3 integration related components.

Maven coordinates, using Spring Cloud AWS BOM:

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

4.1. Using S3 client

The starter automatically configures and registers a S3Client bean in the Spring application context. The S3Client bean can be used to perform operations on S3 buckets and objects.

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);
    }
}

4.2. Using S3TransferManager

S3 Transfer Manager provided by AWS is in developer preview phase and should not be used in production.

AWS launched a high level file transfer utility, called Transfer Manager. The starter automatically configures and registers an software.amazon.awssdk.transfer.s3.S3TransferManager bean if it finds the following is added to the project:

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

4.3. Using Cross-Region S3 client

S3Client implementation provided in AWS SDK is region specific - meaning it can be used only to operate on buckets and objects stored in region for which the client has been configured to use.

For example, assuming that DefaultAwsRegionProviderChain resolves a region us-east-1, running any S3 operation that uses a bucket created in another region would result in an exception:

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 provides a CrossRegionS3Client that solves this problem by maintaining an internal dictionary of S3Client objects per region. If you need to customize these clients, you can create a custom S3ClientBuilder bean that acts as a template to create region-specific S3 clients in CrossRegionS3Client. There is no extra work needed to use cross-region S3 client - it is the S3Client auto-configured by Spring Cloud AWS.

To disable CrossRegionS3Client creation and use instead a regular region-specific S3Client, you can either create a custom S3Client bean, or exclude spring-cloud-aws-s3-cross-region-client dependency:

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

4.4. S3 Objects as Spring Resources

Spring Resources are an abstraction for a number of low-level resources, such as file system files, classpath files, servlet context-relative files, etc. Spring Cloud AWS adds a new resource type: a S3Resource object.

The Spring Resource Abstraction for S3 allows S3 objects to be accessed by their S3 URL using the @Value annotation:

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

…​or the Spring application context

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

This creates a Resource object that can be used to read the file, among other possible operations.

It is also possible to write to a Resource, although a WriteableResource is required.

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

To work with the Resource as a S3 resource, cast it to io.awspring.cloud.s3.S3Resource. Using S3Resource directly lets you set the S3 object metadata.

@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));
}

Under the hood by default S3Resource uses a io.awspring.cloud.s3.InMemoryBufferingS3OutputStream. When data is written to the resource, is gets sent to S3 using multipart upload. If a network error occurs during upload, S3Client has a built-in retry mechanism that will retry each failed part. If the upload fails after retries, multipart upload gets aborted and S3Resource throws io.awspring.cloud.s3.S3Exception.

If InMemoryBufferingS3OutputStream behavior does not fit your needs, you can use io.awspring.cloud.s3.DiskBufferingS3OutputStream by defining a bean of type DiskBufferingS3OutputStreamProvider which will override the default output stream provider. With DiskBufferingS3OutputStream when data is written to the resource, first it is stored on the disk in a tmp directory in the OS. Once the stream gets closed, the file gets uploaded with S3Client#putObject method. If a network error occurs during upload, S3Client has a built-in retry mechanism. If the upload fails after retries, S3Resource throws io.awspring.cloud.s3.UploadFailed exception containing a file location in a temporary directory in a file system.

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

If you are using the S3TransferManager, the default implementation will switch to io.awspring.cloud.s3.TransferManagerS3OutputStream. This OutputStream also uses a temporary file to write it on disk before uploading it to S3, but it may be faster as it uses a multi-part upload under the hood.

4.5. Using S3Template

Spring Cloud AWS provides a higher abstraction on the top of S3Client providing methods for the most common use cases when working with S3.

On the top of self-explanatory methods for creating and deleting buckets, S3Template provides a simple methods for uploading and downloading files:

@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 also allows storing & retrieving Java objects.

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

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

By default, if Jackson is on the classpath, S3Template uses ObjectMapper based Jackson2JsonS3ObjectConverter to convert from S3 object to Java object and vice versa. This behavior can be overwritten by providing custom bean of type S3ObjectConverter.

4.6. Determining S3 Objects Content Type

All S3 objects stored in S3 through S3Template, S3Resource or S3OutputStream automatically get set a contentType property on the S3 object metadata, based on the S3 object key (file name).

By default, PropertiesS3ObjectContentTypeResolver - a component supporting over 800 file extensions is responsible for content type resolution. If this content type resolution does not meet your needs, you can provide a custom bean of type S3ObjectContentTypeResolver which will be automatically used in all components responsible for uploading files.

4.7. Configuration

The Spring Boot Starter for S3 provides the following configuration options:

Name

Description

Required

Default value

spring.cloud.aws.s3.enabled

Enables the S3 integration.

No

true

spring.cloud.aws.s3.endpoint

Configures endpoint used by S3Client.

No

localhost:4566

spring.cloud.aws.s3.region

Configures region used by S3Client.

No

eu-west-1

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

Option to enable using the accelerate endpoint when accessing S3. Accelerate endpoints allow faster transfer of objects by using Amazon CloudFront’s globally distributed edge locations.

No

null (falls back to SDK default)

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

Option to disable doing a validation of the checksum of an object stored in S3.

No

null (falls back to SDK default)

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

Option to enable using chunked encoding when signing the request payload for PutObjectRequest and UploadPartRequest.

No

null (falls back to SDK default)

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

Option to enable using path style access for accessing S3 objects instead of DNS style access. DNS style access is preferred as it will result in better load balancing when accessing S3.

No

null (falls back to SDK default)

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

If an S3 resource ARN is passed in as the target of an S3 operation that has a different region to the one the client was configured with, this flag must be set to 'true' to permit the client to make a cross-region call to the region specified in the ARN otherwise an exception will be thrown.

No

null (falls back to SDK default)

4.8. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

Downloading files

s3:GetObject

Searching files

s3:ListObjects

Uploading files

s3:PutObject

Sample IAM policy granting access to spring-cloud-aws-demo bucket:

{
    "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/*"
        }
    ]
}

5. SES Integration

Spring has a built-in support to send e-mails based on the Java Mail API to avoid any static method calls while using the Java Mail API and thus supporting the testability of an application. Spring Cloud AWS supports the Amazon SES as an implementation of the Spring Mail abstraction.

As a result Spring Cloud AWS users can decide to use the Spring Cloud AWS implementation of the Amazon SES service or use the standard Java Mail API based implementation that sends e-mails via SMTP to Amazon SES.

It is preferred to use the Spring Cloud AWS implementation instead of SMTP mainly for performance reasons. Spring Cloud AWS uses one API call to send a mail message, while the SMTP protocol makes multiple requests (EHLO, MAIL FROM, RCPT TO, DATA, QUIT) until it sends an e-mail.

A Spring Boot starter is provided to auto-configure SES integration beans.

Maven coordinates, using Spring Cloud AWS BOM:

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

5.1. Sending simple mails

Application developers can inject the MailSender into their application code and directly send simple text based e-mail messages. The sample below demonstrates the creation of a simple mail message.

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("[email protected]");
        simpleMailMessage.setTo("[email protected]");
        simpleMailMessage.setSubject("test subject");
        simpleMailMessage.setText("test content");
        this.mailSender.send(simpleMailMessage);
    }
}

5.2. Sending attachments

Sending attachments with e-mail requires MIME messages to be created and sent. In order to create MIME messages, the Java Mail dependency is required and has to be included in the classpath. Spring Cloud AWS will detect the dependency and create a org.springframework.mail.javamail.JavaMailSender implementation that allows to create and build MIME messages and send them. A dependency configuration for the Java Mail API is the only change in the configuration which is shown below.

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mailapi</artifactId>
</dependency>

Even though there is a dependency to the Java Mail API there is still the Amazon SES API used underneath to send mail messages. There is no SMTP setup required on the Amazon AWS side.

Sending the mail requires the application developer to use the JavaMailSender to send an e-mail as shown in the example below.

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("[email protected]");
                helper.setFrom("[email protected]");
                helper.addAttachment("test.txt", ...);
                helper.setSubject("test subject with attachment");
                helper.setText("mime body", false);
            }
        });
    }
}

5.3. Authenticating e-mails

To avoid any spam attacks on the Amazon SES mail service, applications without production access must verify each e-mail receiver otherwise the mail sender will throw a software.amazon.awssdk.services.ses.model.MessageRejectedException.

Production access can be requested and will disable the need for mail address verification.

5.4. Configuration

The Spring Boot Starter for SES provides the following configuration options:

Name

Description

Required

Default value

spring.cloud.aws.ses.enabled

Enables the SES integration.

No

true

spring.cloud.aws.ses.endpoint

Configures endpoint used by SesClient.

No

spring.cloud.aws.ses.region

Configures region used by SesClient.

No

Amazon SES is not available in all regions of the Amazon Web Services cloud. Therefore, an application hosted and operated in a region that does not support the mail service will produce an error while using the mail service. Therefore, the region must be overridden for the mail sender configuration. The example below shows a typical combination of a region (EU-CENTRAL-1) that does not provide an SES service where the client is overridden to use a valid region (EU-WEST-1).

spring.cloud.aws.ses.region=eu-west-1

5.5. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

Send e-mail without attachment

ses:SendEmail

Send e-mail with attachment

ses:SendRawEmail

Sample IAM policy granting access to SES:

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

6. SNS Integration

SNS is a pub/sub messaging service that allows clients to publish notifications to a particuluar topic. A Spring Boot starter is provided to auto-configure SNS integration beans.

Maven coordinates, using Spring Cloud AWS BOM:

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

6.1. Sending Notifications

6.1.1. SNS Template

The starter automatically configures and registers a SnsTemplate bean providing higher level abstractions for sending SNS notifications. SnsTemplate implements Spring Messaging abstractions making it easy to combine with other messaging technologies compatible with Spring Messaging.

It supports sending notifications with payload of type:

  • String - using org.springframework.messaging.converter.StringMessageConverter

  • Object - which gets serialized to JSON using org.springframework.messaging.converter.MappingJackson2MessageConverter and Jackson’s com.fasterxml.jackson.databind.ObjectMapper autoconfigured by Spring Boot.

Additionally, it exposes handful of methods supporting 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);
    }
}

If autoconfigured converters do not meet your needs, you can provide a custom SnsTemplate bean with a message converter of your choice.

When sending SNS notification, it is required to provide a topic ARN. Spring Cloud AWS simplifies it and allows providing a topic name instead, under a condition that topic with that name has already been created. Otherwise, Spring Cloud AWS will make an attempt to create topic with this name with a first call.

The behavior of resolving topic ARN by a topic name can be altered by providing a custom bean of type io.awspring.cloud.sns.core.TopicArnResolver.

6.1.2. SNS Operations

Because of Spring Messaging compatibility, SnsTemplate exposes many methods that you may not need if you don’t need Spring Messaging abstractions. In such case, we recommend using SnsOperations - an interface implemented by SnsTemplate, that exposes a convenient method for sending SNS notification, including support for FIFO topics.

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);
    }
}

6.2. Using SNS Client

To have access to all lower level SNS operations, we recommend using SnsClient from AWS SDK. SnsClient bean is autoconfigured by SnsAutoConfiguration.

If autoconfigured SnsClient bean configuration does not meet your needs, it can be replaced by creating a custom bean of type SnsClient.

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"));
    }
}

6.3. Annotation-driven HTTP notification endpoint

SNS supports multiple endpoint types (SQS, Email, HTTP, HTTPS), Spring Cloud AWS provides support for HTTP(S) endpoints. SNS sends three type of requests to an HTTP topic listener endpoint, for each of them annotations are provided:

  • Subscription request → @NotificationSubscriptionMapping

  • Notification request → @NotificationMessageMapping

  • Unsubscription request → @NotificationUnsubscribeMapping

HTTP endpoints are based on Spring MVC controllers. Spring Cloud AWS added some custom argument resolvers to extract the message and subject out of the notification requests.

Example of integration:

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();
    }
}

6.4. Configuration

The Spring Boot Starter for SNS provides the following configuration options:

Name

Description

Required

Default value

spring.cloud.aws.sns.enabled

Enables the SNS integration.

No

true

spring.cloud.aws.sns.endpoint

Configures endpoint used by SnsClient.

No

localhost:4566

spring.cloud.aws.sns.region

Configures region used by SnsClient.

No

eu-west-1

6.5. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

To publish notification to topic

sns:Publish

To publish notification you will also need

sns:ListTopics

To use Annotation-driven HTTP notification endpoint

sns:ConfirmSubscription

For resolving topic name to ARN

sns:CreateTopic

Sample IAM policy granting access to SNS:

{
    "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": "*"
        }
    ]
}

7. Secrets Manager Integration

Secrets Manager helps to protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle.

Spring Cloud AWS adds support for loading configuration properties from Secrets Manager through Spring Boot config import feature.

Maven coordinates, using Spring Cloud AWS BOM:

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

7.1. Loading External Configuration

To fetch secrets from Secrets Manager and add them to Spring’s environment properties, add spring.config.import property to application.properties:

For example, assuming that the secret name in Secrets Manager is /secrets/database-secrets:

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

If a secret with given name does not exist in Secrets Manager, application will fail to start. If secret value is not required for the application, and it should continue to startup even when secret is missing, add optional before prefix:

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

To load multiple secrets, separate their names with ;:

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

If some secrets are required, and other ones are optional, list them as separate entries in spring.config.import property:

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

Fetched secrets can be referenced with @Value, bound to @ConfigurationProperties classes, or referenced in application.properties file.

7.1.1. Using Key-Value (JSON) Secrets

Secrets resolved with spring.config.import can be also referenced in application.properties. When a content of SecretString in a JSON, all top level JSON keys are added as properties to Spring Environment.

For example, with a file mycreds.json containing following JSON structure:

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

Secret is created with a command:

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

spring.config.import entry is added to application.properties:

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

Secret values can be referenced by JSON key names:

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

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

7.1.2. Using plain text secrets

If a SecretString is a plain text, use secret name to retrieve its value. For example, we will JDBC saved as plain text secret type with name /secrets/my-certificate:

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

spring.config.import entry is added to application.properties:

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

Secret value can be retrieved by referencing secret name:

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

7.2. Using SecretsManagerClient

The starter automatically configures and registers a SecretsManagerClient bean in the Spring application context. The SecretsManagerClient bean can be used to create or retrieve secrets imperatively.

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());

7.3. Customizing SecretsManagerClient

To use custom SecretsManagerClient in spring.config.import, provide an implementation of BootstrapRegistryInitializer. For example:

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();
        });
    }
}

Note that this class must be listed under org.springframework.boot.BootstrapRegistryInitializer key in META-INF/spring.factories:

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

If you want to use autoconfigured SecretsManagerClient but change underlying SDKClient or ClientOverrideConfiguration you will need to register bean of type AwsClientConfigurerSecretsManager: Autoconfiguration will configure SecretsManagerClient Bean with provided values after that, for example:

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();
                }
            });
    }
}

7.4. Configuration

The Spring Boot Starter for Secrets Manager provides the following configuration options:

Name

Description

Required

Default value

spring.cloud.aws.secretsmanager.enabled

Enables the Secrets Manager integration.

No

true

spring.cloud.aws.secretsmanager.endpoint

Configures endpoint used by SecretsManagerClient.

No

null

spring.cloud.aws.secretsmanager.region

Configures region used by SecretsManagerClient.

No

null

7.5. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

Get secret value:

secretsmanager:GetSecretValue

Sample IAM policy granting access to Secrets Manager:

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

8. Parameter Store Integration

Spring Cloud AWS adds support for loading configuration properties from Parameter Store through Spring Boot config import feature.

Maven coordinates, using Spring Cloud AWS BOM:

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

8.1. Loading External Configuration

To fetch parameters from Parameter Store and add them to Spring’s environment properties, add spring.config.import property to application.properties:

For example, assuming that the parameters in Parameter Store are stored under path /config/spring:

Parameter Name Parameter Value

/config/spring/message

Welcome

/config/spring/httpUrl

external-service:3030/

Once spring.config.import statement is added:

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

Two parameters are added to environment: message and httpUrl.

If a given path in Parameter Store does not exist, application will fail to start. If parameters retrieved from Parameter Store are not required for the application, and it should continue to startup even when the path is missing, add optional before prefix:

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

To load parameters from multiple paths, separate their names with ;:

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

If some parameters are required, and other ones are optional, list them as separate entries in spring.config.import property:

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

8.2. Using SsmClient

The starter automatically configures and registers a SsmClient bean in the Spring application context. The SsmClient bean can be used to create or retrieve parameters from Parameter Store.

import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.ssm.SsmClient;
...
@Autowired
private SsmClient ssmClient;
...
ssmClient.getParametersByPath(request -> request.path("/config/spring/")).parameters();

8.3. Customizing SsmClient

To use custom SsmClient in spring.config.import, provide an implementation of BootstrapRegistryInitializer. For example:

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();
        });
    }
}

Note that this class must be listed under org.springframework.boot.BootstrapRegistryInitializer key in META-INF/spring.factories:

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

If you want to use autoconfigured SsmClient but change underlying SDKClient or ClientOverrideConfiguration you will need to register bean of type AwsClientConfigurerParameterStore: Autoconfiguration will configure SsmClient Bean with provided values after that, for example:

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();
                }
            });
    }
}

8.4. Configuration

The Spring Boot Starter for Parameter Store provides the following configuration options:

Name Description Required Default value

spring.cloud.aws.parameterstore.enabled

Enables the Parameter Store integration.

No

true

spring.cloud.aws.parameterstore.endpoint

Configures endpoint used by SsmClient.

No

null

spring.cloud.aws.parameterstore.region

Configures region used by SsmClient.

No

null

8.5. IAM Permissions

Following IAM permissions are required by Spring Cloud AWS:

Get parameter from specific path

ssm:GetParametersByPath

Sample IAM policy granting access to Parameter Store:

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

9. Configuration properties

To see the list of all Spring Cloud AWS related configuration properties please check the Appendix page.