Skip to content

Commit 69ad838

Browse files
DynamoDb integration (#339)
Co-authored-by: Maciej Walkowiak <[email protected]>
1 parent 08209f5 commit 69ad838

File tree

34 files changed

+1637
-2
lines changed

34 files changed

+1637
-2
lines changed

docs/src/main/asciidoc/_configprops.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
|spring.cloud.aws.credentials.secret-key | | The secret key to be used with a static provider.
88
|spring.cloud.aws.defaults-mode | | Sets the {@link DefaultsMode} that will be used to determine how certain default configuration options are resolved in the SDK.
99
|spring.cloud.aws.dualstack-enabled | | Configure whether the SDK should use the AWS dualstack endpoint.
10+
|spring.cloud.aws.dynamodb.enabled | `true` | Enables DynamoDb integration.
11+
|spring.cloud.aws.dynamodb.endpoint | | Overrides the default endpoint.
12+
|spring.cloud.aws.dynamodb.region | | Overrides the default region.
1013
|spring.cloud.aws.endpoint | | Overrides the default endpoint for all auto-configured AWS clients.
1114
|spring.cloud.aws.fips-enabled | | Configure whether the SDK should use the AWS fips endpoints.
1215
|spring.cloud.aws.parameterstore.endpoint | | Overrides the default endpoint.

docs/src/main/asciidoc/dynamodb.adoc

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
[#spring-cloud-aws-dynamoDb]
2+
== DynamoDb Integration
3+
4+
https://aws.amazon.com/dynamodb/[DynamoDb] is a fully managed serverless key/value Nosql database designed for high performance.
5+
A Spring Boot starter is provided to auto-configure DynamoDb integration beans.
6+
7+
Maven coordinates, using <<index.adoc#bill-of-materials, Spring Cloud AWS BOM>>:
8+
9+
[source,xml]
10+
----
11+
<dependency>
12+
<groupId>io.awspring.cloud</groupId>
13+
<artifactId>spring-cloud-aws-starter-dynamodb</artifactId>
14+
</dependency>
15+
----
16+
17+
DynamoDb integration will only provide autoconfiguration and simple `DynamoDbOperations` which can be used to communicate with DynamoDb, build repositories and so on...
18+
19+
=== DynamoDbOperations
20+
21+
The starter automatically configures and registers a `DynamoDbOperations` bean providing higher level abstractions for working with DynamoDb.
22+
`DynamoDbTemplate` - a default `DynamoDbOperations` implementation - being built on top of `DynamoDbEnhancedClient` uses annotations provided by AWS.
23+
The list of supported annotations can be found https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html[here].
24+
25+
`DynamoDbEnchancedClient` supports a programming model similar to JPA - where a class is turned into an entity through applying certain annotations:
26+
27+
[source,java]
28+
----
29+
import java.util.UUID;
30+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
31+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
32+
33+
@DynamoDbBean
34+
public class Person {
35+
private UUID id;
36+
private String name;
37+
private String lastName;
38+
39+
@DynamoDbPartitionKey
40+
public UUID getId() {
41+
return id;
42+
}
43+
44+
...
45+
}
46+
----
47+
48+
`DynamoDbTemplate` provides methods to perform typical CRUD operations on such entities, plus it adds convenience methods for querying DynamoDb:
49+
50+
[source,java]
51+
----
52+
53+
import io.awspring.cloud.dynamodb.DynamoDbTemplate;
54+
55+
...
56+
@Autowired
57+
DynamoDbTemplate dynamoDbTemplate;
58+
...
59+
Person person = new Person(...)
60+
dynamoDbTemplate.save(person);
61+
----
62+
63+
==== Resolving Table Name
64+
65+
To resolve a table name for an entity, `DynamoDbTemplate` uses a bean of type `DynamoDbTableNameResolver`. The default implementation turns an entity class name into its snake case representation.
66+
To use custom implementation, declare a bean of type `DynamoDbTableNameResolver` and it will get injected into `DynamoDbTemplate` automatically during auto-configuration.
67+
68+
==== Resolving Table Schema
69+
70+
To resolve a table schema for an entity, `DynamoDbTemplate` uses a bean of type `DynamoDbTableSchemaResolver`. The default implementation caches `TableSchema` objects in internal map.
71+
To use custom implementation, declare a bean of type `DynamoDbTableSchemaResolver` and it will get injected into `DynamoDbTemplate` automatically during auto-configuration.
72+
73+
=== Using DynamoDb Client
74+
75+
Autoconfiguration automatically configures `DynamoDbClient` which can be used for low level api calls and `DynamoDbEnhancedClient` if `DynamoDbOperations` are not enough.
76+
77+
If autoconfigured `DynamoDbClient` or `DynamoDbEnhancedClient` bean configuration does not meet your needs, it can be replaced by creating your custom bean.
78+
79+
[source,java]
80+
----
81+
import java.util.Collections;
82+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
83+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
84+
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
85+
86+
public class DynamoDbService {
87+
private final DynamoDbClient dynamoDbClient;
88+
89+
public DynamoDbService(DynamoDbClient dynamoDbClient) {
90+
this.dynamoDbClient = dynamoDbClient;
91+
}
92+
93+
void deletePerson(String uuid) {
94+
dynamoDbClient.deleteItem(DeleteItemRequest.builder().key(Collections.singletonMap("uuid", AttributeValue.builder().s(uuid).build())).build());
95+
}
96+
}
97+
----
98+
99+
=== Configuration
100+
101+
The Spring Boot Starter for DynamoDb provides the following configuration options:
102+
103+
[cols="3,3,1,1"]
104+
|===
105+
| Name | Description | Required | Default value
106+
| `spring.cloud.aws.dynamodb.enabled` | Enables the DynamoDb integration. | No | `true`
107+
| `spring.cloud.aws.dynamodb.endpoint` | Configures endpoint used by `DynamoDbClient`. | No |
108+
| `spring.cloud.aws.dynamodb.region` | Configures region used by `DynamoDbClient`. | No |
109+
|===
110+
111+
=== IAM Permissions
112+
113+
Since it depends on how you will use DynamoDb integration providing a list of IAM policies would be pointless since least privilege model should be used.
114+
To check what IAM policies DynamoDb uses and see which ones you should use please check https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/using-identity-based-policies.html[IAM policies]

docs/src/main/asciidoc/index.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ before any other BOM dependency that configures AWS SDK dependencies.
127127

128128
include::core.adoc[]
129129

130+
include::dynamodb.adoc[]
131+
130132
include::s3.adoc[]
131133

132134
include::ses.adoc[]

docs/src/main/asciidoc/spring-cloud-aws.adoc

Whitespace-only changes.

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<module>spring-cloud-aws-secrets-manager</module>
4646
<module>spring-cloud-aws-ses</module>
4747
<module>spring-cloud-aws-sns</module>
48+
<module>spring-cloud-aws-dynamodb</module>
4849
<module>spring-cloud-aws-s3-parent</module>
4950
<module>spring-cloud-aws-starters</module>
5051
<module>spring-cloud-aws-samples</module>

spring-cloud-aws-autoconfigure/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
<artifactId>spring-cloud-aws-sns</artifactId>
5555
<optional>true</optional>
5656
</dependency>
57+
<dependency>
58+
<groupId>io.awspring.cloud</groupId>
59+
<artifactId>spring-cloud-aws-dynamodb</artifactId>
60+
<optional>true</optional>
61+
</dependency>
5762
<dependency>
5863
<groupId>io.awspring.cloud</groupId>
5964
<artifactId>spring-cloud-aws-s3</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2013-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.awspring.cloud.autoconfigure.dynamodb;
17+
18+
import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer;
19+
import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer;
20+
import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration;
21+
import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration;
22+
import io.awspring.cloud.dynamodb.*;
23+
import java.util.Optional;
24+
import org.springframework.beans.factory.ObjectProvider;
25+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
26+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
27+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
29+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
30+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.context.annotation.Configuration;
33+
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
34+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
35+
import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
36+
37+
/**
38+
* {@link EnableAutoConfiguration Auto-configuration} for DynamoDB integration.
39+
*
40+
* @author Matej Nedic
41+
* @since 3.0.0
42+
*/
43+
@Configuration(proxyBeanMethods = false)
44+
@EnableConfigurationProperties(DynamoDbProperties.class)
45+
@ConditionalOnClass({ DynamoDbClient.class, DynamoDbEnhancedClient.class, DynamoDbTemplate.class })
46+
@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class })
47+
@ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.enabled", havingValue = "true", matchIfMissing = true)
48+
public class DynamoDbAutoConfiguration {
49+
50+
private final DynamoDbProperties properties;
51+
52+
public DynamoDbAutoConfiguration(DynamoDbProperties properties) {
53+
this.properties = properties;
54+
}
55+
56+
@ConditionalOnMissingBean
57+
@Bean
58+
public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
59+
ObjectProvider<AwsClientCustomizer<DynamoDbClientBuilder>> configurer) {
60+
return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable())
61+
.build();
62+
}
63+
64+
@ConditionalOnMissingBean
65+
@Bean
66+
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
67+
return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
68+
}
69+
70+
@ConditionalOnMissingBean(DynamoDbOperations.class)
71+
@Bean
72+
public DynamoDbTemplate dynamoDBTemplate(DynamoDbEnhancedClient dynamoDbEnhancedClient,
73+
Optional<DynamoDbTableSchemaResolver> tableSchemaResolver,
74+
Optional<DynamoDbTableNameResolver> tableNameResolver) {
75+
DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver
76+
.orElseGet(DefaultDynamoDbTableSchemaResolver::new);
77+
DynamoDbTableNameResolver tableNameRes = tableNameResolver.orElseGet(DefaultDynamoDbTableNameResolver::new);
78+
return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes);
79+
}
80+
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2013-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.awspring.cloud.autoconfigure.dynamodb;
17+
18+
import io.awspring.cloud.autoconfigure.AwsClientProperties;
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
21+
/**
22+
* Properties related to AWS DynamoDB.
23+
* @author Matej Nedic
24+
* @since 3.0.0
25+
*/
26+
@ConfigurationProperties(prefix = DynamoDbProperties.PREFIX)
27+
public class DynamoDbProperties extends AwsClientProperties {
28+
29+
/**
30+
* The prefix used for AWS credentials related properties.
31+
*/
32+
public static final String PREFIX = "spring.cloud.aws.dynamodb";
33+
}

spring-cloud-aws-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
"name": "spring.cloud.aws.s3.enabled",
1818
"description": "Enables S3 integration.",
1919
"type": "java.lang.Boolean"
20+
},
21+
{
22+
"defaultValue": true,
23+
"name": "spring.cloud.aws.dynamodb.enabled",
24+
"description": "Enables DynamoDb integration.",
25+
"type": "java.lang.Boolean"
2026
}
2127
]
2228
}

spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration,\
55
io.awspring.cloud.autoconfigure.ses.SesAutoConfiguration,\
66
io.awspring.cloud.autoconfigure.s3.S3TransferManagerAutoConfiguration,\
77
io.awspring.cloud.autoconfigure.s3.S3AutoConfiguration,\
8-
io.awspring.cloud.autoconfigure.sns.SnsAutoConfiguration
8+
io.awspring.cloud.autoconfigure.sns.SnsAutoConfiguration,\
9+
io.awspring.cloud.autoconfigure.dynamodb.DynamoDbAutoConfiguration
910

1011
# ConfigData Location Resolvers
1112
org.springframework.boot.context.config.ConfigDataLocationResolver=\

0 commit comments

Comments
 (0)