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:
-
Java System Properties -
aws.accessKeyId
andaws.secretAccessKey
-
Environment Variables -
AWS_ACCESS_KEY_ID
andAWS_SECRET_ACCESS_KEY
-
Web Identity Token credentials from system properties or environment variables
-
Credential profiles file at the default location (
~/.aws/credentials
) shared by all AWS SDKs and the AWS CLI -
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,
-
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 |
|
The file path where the profile configuration file is located. Defaults to |
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:
-
Check the
aws.region
system property for the region. -
Check the
AWS_REGION
environment variable for the region. -
Check the
{user.home}/.aws/credentials
and{user.home}/.aws/config
files for the region. -
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 |
|
The file path where the profile configuration file is located. Defaults to |
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 |
---|---|---|
|
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 |
|
Enables the S3 integration. |
No |
|
|
Configures endpoint used by |
No |
|
|
Configures region used by |
No |
|
|
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 |
|
|
Option to disable doing a validation of the checksum of an object stored in S3. |
No |
|
|
Option to enable using chunked encoding when signing the request payload for |
No |
|
|
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 |
|
|
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 |
|
4.8. IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:
Downloading files |
|
Searching files |
|
Uploading files |
|
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 |
|
Enables the SES integration. |
No |
|
|
Configures endpoint used by |
No |
|
|
Configures region used by |
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 |
|
Send e-mail with attachment |
|
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
- usingorg.springframework.messaging.converter.StringMessageConverter
-
Object
- which gets serialized to JSON usingorg.springframework.messaging.converter.MappingJackson2MessageConverter
and Jackson’scom.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 |
|
Enables the SNS integration. |
No |
|
|
Configures endpoint used by |
No |
|
|
Configures region used by |
No |
|
6.5. IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:
To publish notification to topic |
|
To publish notification you will also need |
|
To use Annotation-driven HTTP notification endpoint |
|
For resolving topic name to ARN |
|
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 |
|
Enables the Secrets Manager integration. |
No |
|
|
Configures endpoint used by |
No |
|
|
Configures region used by |
No |
|
7.5. IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:
Get secret value: |
|
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 |
---|---|
|
|
|
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 |
---|---|---|---|
|
Enables the Parameter Store integration. |
No |
|
|
Configures endpoint used by |
No |
|
|
Configures region used by |
No |
|
8.5. IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:
Get parameter from specific path |
|
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.