Amazon provides a Java SDK to issue requests for the all services provided by the Amazon Web Service platform. Using the SDK, application developers still have to integrate the SDK into their application with a considerable amount of infrastructure related code. Spring Cloud AWS provides application developers already integrated Spring-based modules to consume services and avoid infrastructure related code as much as possible. The Spring Cloud AWS module provides a module set so that application developers can arrange the dependencies based on their needs for the particular services. The graphic below provides a general overview of all Spring Cloud AWS modules along with the service support for the respective Spring Cloud AWS services.
-
Spring Cloud AWS Core is the core module of Spring Cloud AWS providing basic services for security and configuration setup. Developers will not use this module directly but rather through other modules. The core module provides support for cloud based environment configurations providing direct access to the instance based EC2 metadata and the overall application stack specific CloudFormation metadata.
-
Spring Cloud AWS Context delivers access to the Simple Storage Service via the Spring resource loader abstraction. Moreover developers can send e-mails using the Simple E-Mail Service and the Spring mail abstraction. Further the developers can introduce declarative caching using the Spring caching support and the ElastiCache caching service.
-
Spring Cloud AWS JDBC provides automatic datasource lookup and configuration for the Relational Database Service which can be used with JDBC or any other support data access technology by Spring.
-
Spring Cloud AWS Messaging enables developers to receive and send messages with the Simple Queueing Service for point-to-point communication. Publish-subscribe messaging is supported with the integration of the Simple Notification Service.
-
Spring Cloud AWS Parameter Store Configuration enables Spring Cloud applications to use the AWS Parameter Store as a Bootstrap Property Source, comparable to the support provided for the Spring Cloud Config Server or Consul’s key-value store.
-
Spring Cloud AWS Secrets Manager Configuration enables Spring Cloud applications to use the AWS Secrets Manager as a Bootstrap Property Source, comparable to the support provided for the Spring Cloud Config Server or Consul’s key-value store.
Before using the Spring Cloud AWS module developers have to pick the dependencies and configure the Spring Cloud AWS module. The next chapters describe the dependency management and also the basic configuration for the Spring AWS Cloud project.
Spring Cloud AWS module dependencies can be used directly in Maven with a direct configuration of the particular module. The Spring Cloud AWS module includes all transitive dependencies for the Spring modules and also the Amazon SDK that are needed to operate the modules. The general dependency configuration will look like this:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-context</artifactId>
<version>{spring-cloud-version}</version>
</dependency>
</dependencies>
Different modules can be included by replacing the module name with the respective one (e.g. spring-cloud-aws-messaging
instead of spring-cloud-aws-context
)
The example above works with the Maven Central repository. To use the Spring Maven repository (e.g. for milestones or developer snapshots), you need to specify the repository location in your Maven configuration. For full releases:
<repositories>
<repository>
<id>io.spring.repo.maven.release</id>
<url>https://repo.spring.io/release/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
For milestones:
<repositories>
<repository>
<id>io.spring.repo.maven.milestone</id>
<url>https://repo.spring.io/milestone/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
Amazon SDK is released more frequently than Spring Cloud AWS. If you need to use newer version of AWS SDK than one configured by Spring Cloud AWS add AWS SDK BOM to dependency management section making sure it is declared before any other BOM dependency that configures AWS SDK dependencies.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>${aws-java-sdk.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
The Spring Cloud AWS configuration is currently done using custom elements provided by Spring Cloud AWS namespaces. JavaConfig will be supported soon. The configuration setup is done directly in Spring XML configuration files so that the elements can be directly used. Each module of Spring Cloud AWS provides custom namespaces to allow the modular use of the modules. A typical XML configuration to use Spring Cloud AWS is outlined below:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aws-context="http://www.springframework.org/schema/cloud/aws/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cloud/aws/context
http://www.springframework.org/schema/cloud/aws/context/spring-cloud-aws-context.xsd">
<aws-context:context-region region="..."/>
</beans>
Tip
|
On application startup, for its internal purposes Spring Cloud AWS performs a check if application runs in AWS cloud environment
by using
If
|
In order to make calls to the Amazon Web Service the credentials must be configured for the the Amazon SDK. Spring Cloud AWS provides support to configure an application context specific credentials that are used for each service call for requests done by Spring Cloud AWS components, with the exception of the Parameter Store and Secrets Manager Configuration. Therefore there must be exactly one configuration of the credentials for an entire application context.
Tip
|
The
|
Based on the overall credentials policy there are different options to configure the credentials. The possible ones are described in the following sub-chapters.
Credentials for the Amazon SDK consist of an access key (which might be shared) and a secret key (which must not be shared). Both security attributes can be configured using the XML namespaces for each Amazon SDK service created by the Spring Cloud AWS module. The overall configuration looks like this
<beans ...>
<aws-context:context-credentials>
<aws-context:simple-credentials access-key="AKIAIO" secret-key="wJalrXUtnFEMI/K7M" />
</aws-context:context-credentials>
</beans>
Caution
|
The access-key and secret-key should be externalized into property files (e.g. Spring Boot application configuration) and not be checked in into the source management system. |
An instance profile configuration allows to assign a profile that is authorized by a role while starting an EC2 instance. All calls made from the EC2 instance are then authenticated with the instance profile specific user role. Therefore there is no dedicated access-key and secret-key needed in the configuration. The configuration for the instance profile in Spring Cloud AWS looks like this:
<beans ...>
<aws-context:context-credentials>
<aws-context:instance-profile-credentials/>
</aws-context:context-credentials>
</beans>
In some cases it is useful to combine both authentication strategies to allow the application to use the instance profile with a fallback for an explicit access-key and secret-key configuration. This is useful if the application is tested inside EC2 (e.g. on a test server) and locally for testing. The next snippet shows a combination of both security configurations.
<beans ...>
<aws-context:context-credentials>
<aws-context:instance-profile-credentials/>
<aws-context:simple-credentials access-key="${accessKey:}" secret-key="${secretKey:}"/>
</aws-context:context-credentials>
</beans>
Tip
|
The access-key and secret-key are defined using a placeholder expressions along with a default value to avoid bootstrap errors if the properties are not configured at all. |
The Parameter Store and Secrets Manager Configuration support uses a bootstrap context to configure a default AWSSimpleSystemsManagement
client, which uses a com.amazonaws.auth.DefaultAWSCredentialsProviderChain
and com.amazonaws.regions.DefaultAwsRegionProviderChain
.
If you want to override this, then you need to
define your own Spring Cloud bootstrap configuration class
with a bean of type AWSSimpleSystemsManagement
that’s configured to use your chosen credentials and/or region provider.
Because this context is created when your Spring Cloud Bootstrap context is created, you can’t simply override the bean
in a regular @Configuration
class.
Amazon Web services are available in different regions. Based
on the custom requirements, the user can host the application on different Amazon regions. The spring-cloud-aws-context
module provides a way to define the region for the entire application context.
The region can be explicitly configured using an XML element. This is particularly useful if the region can not be automatically derived because the application is not hosted on a EC2 instance (e.g. local testing) or the region must be manually overridden.
<beans ...>
<aws-context:context-region region="eu-west-1"/>
</beans>
Tip
|
It is also allowed to use expressions or placeholders to externalize the configuration and ensure that the region can be reconfigured with property files or system properties. |
If the application context is started inside an EC2 instance, then the region can automatically be fetched from the instance metadata and therefore must not be configured statically. The configuration will look like this:
<beans ...>
<aws-context:context-region auto-detect="true" />
</beans>
A region can also be overridden for particular services if one application context consumes services from different regions. The configuration can be done globally like described above and configured for each service with a region attribute. The configuration might look like this for a database service (described later)
<beans ...>
<aws-context:context-region region="eu-central-1" />
<jdbc:data-source ... region="eu-west-1" />
</beans>
Note
|
While it is theoretically possible to use multiple regions per application, we strongly recommend to write applications that are hosted only inside one region and split the application if it is hosted in different regions at the same time. |
Following the Spring Cloud umbrella project, Spring Cloud AWS also provides dedicated Spring Boot support. Spring Cloud AWS can be configured using Spring Boot properties and will also automatically guess any sensible configuration based on the general setup.
Spring Cloud AWS provides a dedicated module to enable the Spring Boot support. That module must be added to the general maven dependency inside the application. The typical configuration will look like this
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-autoconfigure</artifactId>
<version>{spring-cloud-version}</version>
</dependency>
</dependencies>
Additional dependencies to enable particular features like messaging and JDBC have to be added. Spring Cloud AWS will only configure classes that are available in the Spring Boot application’s classpath.
Spring Boot provides a standard way to define properties with property file or YAML configuration files. Spring Cloud AWS provides support to configure the credential information with the Spring Boot application configuration files.
By default Spring Cloud AWS configures DefaultAWSCredentialsProviderChain to resolve AWS credentials.
If other credentials providers are configured, DefaultAWSCredentialsProviderChain is not used and Spring Cloud AWS configures following credentials chain:
-
AWSStaticCredentialsProvider
ifcloud.aws.credentials.access-key
is provided -
EC2ContainerCredentialsProviderWrapper
ifcloud.aws.credentials.instance-profile
is set totrue
-
ProfileCredentialsProvider
ifcloud.aws.credentials.profile-name
is provided
Spring Cloud AWS provides the following properties to configure the credentials setup for the whole application.
property | example | description |
---|---|---|
cloud.aws.credentials.access-key |
AKIAIOSFODNN7EXAMPLE |
The access key to be used with a static provider |
cloud.aws.credentials.secret-key |
wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |
The secret key to be used with a static provider |
cloud.aws.credentials.instance-profile |
true |
Configures an instance profile credentials provider with no further configuration |
cloud.aws.credentials.profile-name |
default |
The name of a configuration profile in the specified configuration file |
cloud.aws.credentials.profile-path |
|
The file path where the profile configuration file is located. Defaults to |
Like for the credentials, the Spring Cloud AWS module also supports the configuration of the region inside the Spring Boot configuration files. The region can be automatically detected using DefaultAwsRegionProviderChain or explicitly configured (e.g. in case of local tests against the AWS cloud).
The properties to configure the region are shown below
property | example | description |
---|---|---|
cloud.aws.region.static |
eu-west-1 |
Configures a static region for the application. Possible regions are (currently) us-east-1, us-west-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-southeast-1, ap-northeast-1, sa-east-1, cn-north-1 and any custom region configured with own region meta data |
For each integrated AWS service you can configure Spring Cloud AWS to use a custom endpoint using configuration properties. For example:
cloud.aws.s3.endpoint=http://localhost:4566
cloud.aws.sqs.endpoint=http://localhost:4566
cloud.aws.rds.endpoint=http://localhost:4566
Using custom endpoint can be especially useful when using Localstack in integration tests or integrating with AWS compatible 3rd party services like MinIO.
For some AWS service integrations you can configure Spring Cloud AWS to use custom ClientConfiguration
.
To override the default ClientConfiguration
used by all integrations, create a bean of type ClientConfiguration
with a name com.amazonaws.ClientConfiguration.BEAN_NAME
.
@Configuration
class CustomAwsConfiguration {
@Bean(name = "com.amazonaws.ClientConfiguration.BEAN_NAME")
ClientConfiguration clientConfiguration() {
ClientConfiguration clientConfiguration= new ClientConfiguration();
clientConfiguration.setProxyHost(proxyHost);
clientConfiguration.setProxyPort(proxyPort);
clientConfiguration.setProxyUsername(proxyUserName);
clientConfiguration.setProxyPassword(proxyPassword);
return clientConfiguration;
}
}
It’s also possible to provide ClientConfiguration
for particular integration by defining a bean of type ClientConfiguration
and a name specific to the integration:
SQS |
|
SNS |
|
SES |
|
RDS |
|
ElastiCache |
|
CloudWatch |
|
For example:
@Configuration
class CustomSqsConfiguration {
@Bean
ClientConfiguration sqsClientConfiguration() {
ClientConfiguration clientConfiguration= new ClientConfiguration();
clientConfiguration.setProxyHost(proxyHost);
clientConfiguration.setProxyPort(proxyPort);
clientConfiguration.setProxyUsername(proxyUserName);
clientConfiguration.setProxyPassword(proxyPassword);
return clientConfiguration;
}
}
Applications often need environment specific configuration information, especially in changing environments like in the Amazon cloud environment. Spring Cloud AWS provides a support to retrieve and use environment specific data inside the application context using common Spring mechanisms like property placeholder or the Spring expression language.
Instance metadata are available inside an EC2 environment. The metadata can be queried using a special HTTP address that provides the instance metadata. Spring Cloud AWS enables application to access this metadata directly in expression or property placeholder without the need to call an external HTTP service.
The instance metadata retrieval support is enabled through an XML element like the standard property placeholder in Spring. The following code sample demonstrates the activation of the instance metadata support inside an application context.
<beans ...>
<aws-context:context-instance-data />
</beans>
Tip
|
Instance metadata can be retrieved without an authorized service call, therefore the configuration above does not require any region or security specific configuration. |
The instance metadata can also be configured within a Java configuration class without the need for an XML configuration.
The next example shows a typical Spring @Configuration
class that enables the instance metadata with the
org.springframework.cloud.aws.context.config.annotation.EnableInstanceData
@Configuration
@EnableContextInstanceData
public static class ApplicationConfiguration {
}
The instance metadata is available in a Spring Boot application as a property source if the application
is running on an EC2 instance and cloud.aws.instance.data.enabled
property is set to true
.
Instance metadata can be used in XML, Java placeholders and expressions. The example below demonstrates the usage of
instance metadata inside an XML file using placeholders and also the expression referring to the special variable environment
<beans ...>
<bean class="org.springframework.cloud.aws....SimpleConfigurationBean">
<property name="value1" value="#{environment.ami-id}" />
<property name="value2" value="#{environment.hostname}" />
<property name="value3" value="${instance-type}" />
<property name="value4" value="${instance-id}" />
</bean>
</beans>
Instance metadata can also be injected with the Spring org.springframework.beans.factory.annotation.Value
annotation
directly into Java fields. The next example demonstrates the use of instance metadata inside a Spring bean.
@Component
public class ApplicationInfoBean {
@Value("${ami-id:N/A}")
private String amiId;
@Value("${hostname:N/A}")
private String hostname;
@Value("${instance-type:N/A}")
private String instanceType;
@Value("${services/domain:N/A}")
private String serviceDomain;
}
Note
|
Every instance metadata can be accessed by the key available in the instance metadata service Nested properties can be accessed by separating the properties with a slash ('/'). |
Besides the default instance metadata it is also possible to configure user data on each instance. This user data is retrieved and
parsed by Spring Cloud AWS. The user data can be defined while starting an EC2 instance with the application. Spring Cloud AWS
expects the format <key>:<value>;<key>:<value>
inside the user data so that it can parse the string and extract the key value pairs.
The user data can be configured using either the management console shown below or a CloudFormation template.
A CloudFormation template snippet for the configuration of the user data is outlined below:
...
"Resources": {
"ApplicationServerInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-6a56b81d",
"UserData": {
"Fn::Base64": "data1:value1;data2:value2"
},
"InstanceType": "t1.micro",
}
}
...
The user data can be accessed directly in the application context like the instance metadata through placeholders or expressions.
@Component
public class SecondConfigurationBean {
@Value("${data1}")
private String firstDataOption;
@Value("${data2}")
private String secondDataOption;
}
User configured properties can also be configured with tags instead of user data. Tags are a global concept in the context of Amazon Web services and used in different services. Spring Cloud AWS supports instance tags also across different services. Compared to user data, user tags can be updated during runtime, there is no need to stop and restart the instance.
Tip
|
User data can also be used to execute scripts on instance startup. Therefore it is useful to leverage instance tags for user configuration and user data to execute scripts on instance startup. |
Instance specific tags can be configured on the instance level through the management console outlined below and like user data also with a CloudFormation template shown afterwards.
A CloudFormation template snippet for the configuration of the instance tags is outlined below:
...
"Resources": {
"UserTagAndUserDataInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-6a56b81d",
"InstanceType": "t1.micro",
"Tags": [
{
"Key": "tag1",
"Value": "tagv1"
},
{
"Key": "tag3",
"Value": "tagv3"
},
{
"Key": "tag2",
"Value": "tagv2"
},
{
"Key": "tag4",
"Value": "tagv4"
}
]
}
}
}
...
To retrieve the instance tags, Spring Cloud AWS has to make authenticated requests and therefore it will need the region
and security configuration before actually resolving the placeholders. Also because the instance tags are not available while starting
the application context, they can only be referenced as expressions and not with placeholders. The context-instance-data
element defines an attribute user-tags-map
that will create a map in the application context for the name. This map
can then be queried using expression for other bean definitions.
<beans ...>
<aws-context:context-instance-data user-tags-map="instanceData" />
</beans>
A java bean might resolve expressions with the @Value
annotation.
public class SimpleConfigurationBean {
@Value("#{instanceData.tag1}")
private String value1;
@Value("#{instanceData.tag2}")
private String value2;
@Value("#{instanceData.tag3}")
private String value3;
@Value("#{instanceData.tag4}")
private String value4;
}
In some circumstances it is necessary to have a custom EC2 client to retrieve the instance information. The
context-instance-data
element supports a custom EC2 client with the amazon-ec2
attribute. The next
example shows the use of a custom EC2 client that might have a special configuration in place.
<beans ...>
<aws-context:context-credentials>....</aws-context:context-credentials>
<aws-context:context-region ... />
<aws-context:context-instance-data amazon-ec2="myCustomClient"/>
<bean id="myCustomClient" class="com.amazonaws.services.ec2.AmazonEC2Client">
...
</bean>
</beans>
If there are user tags configured for the instance data (see above) Spring Cloud AWS configures an EC2 client with
the specified region and security credentials. Application developers can inject the EC2 client directly into their code using the @Autowired
annotation.
public class ApplicationService {
private final AmazonEC2 amazonEc2;
@Autowired
public ApplicationService(AmazonEC2 amazonEc2) {
this.amazonEc2 = amazonEc2;
}
}
Spring Cloud AWS provides Amazon SQS and Amazon SNS integration that simplifies the publication and consumption of messages over SQS or SNS. While SQS fully relies on the messaging API introduced with Spring 4.0, SNS only partially implements it as the receiving part must be handled differently for push notifications.
Before using and configuring the messaging support, the application has to include the respective module dependency into the Maven configuration. Spring Cloud AWS Messaging support comes as a separate module to allow the modularized use of the modules.
The Spring Cloud AWS messaging module comes as a standalone module and can be imported with the following dependency declaration:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-messaging</artifactId>
<version>{spring-cloud-version}</version>
</dependency>
To see the list of all Spring Cloud AWS related configuration properties please check the Appendix page.