Skip to content

Commit 2e49e0b

Browse files
committed
Make DynamoDb Clients Standalone
1 parent a45e735 commit 2e49e0b

File tree

2 files changed

+98
-31
lines changed

2 files changed

+98
-31
lines changed

spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java

Lines changed: 91 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,19 @@
1515
*/
1616
package io.awspring.cloud.autoconfigure.dynamodb;
1717

18+
import java.io.IOException;
19+
import java.util.Optional;
20+
1821
import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer;
1922
import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer;
2023
import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration;
2124
import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration;
22-
import io.awspring.cloud.dynamodb.*;
23-
import java.io.IOException;
24-
import java.util.Optional;
25+
import io.awspring.cloud.dynamodb.DefaultDynamoDbTableNameResolver;
26+
import io.awspring.cloud.dynamodb.DefaultDynamoDbTableSchemaResolver;
27+
import io.awspring.cloud.dynamodb.DynamoDbOperations;
28+
import io.awspring.cloud.dynamodb.DynamoDbTableNameResolver;
29+
import io.awspring.cloud.dynamodb.DynamoDbTableSchemaResolver;
30+
import io.awspring.cloud.dynamodb.DynamoDbTemplate;
2531
import org.springframework.beans.factory.ObjectProvider;
2632
import org.springframework.boot.autoconfigure.AutoConfiguration;
2733
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -36,10 +42,14 @@
3642
import org.springframework.context.annotation.Conditional;
3743
import org.springframework.context.annotation.Configuration;
3844
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
45+
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient;
3946
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
4047
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
48+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
49+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClientBuilder;
4150
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
4251
import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
52+
import software.amazon.dax.ClusterDaxAsyncClient;
4353
import software.amazon.dax.ClusterDaxClient;
4454

4555
/**
@@ -51,7 +61,7 @@
5161
*/
5262
@AutoConfiguration
5363
@EnableConfigurationProperties(DynamoDbProperties.class)
54-
@ConditionalOnClass({ DynamoDbClient.class, DynamoDbEnhancedClient.class, DynamoDbTemplate.class })
64+
@ConditionalOnClass({ DynamoDbClient.class, DynamoDbAsyncClient.class })
5565
@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class })
5666
@ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.enabled", havingValue = "true", matchIfMissing = true)
5767
public class DynamoDbAutoConfiguration {
@@ -60,39 +70,59 @@ public class DynamoDbAutoConfiguration {
6070
@ConditionalOnClass(name = "software.amazon.dax.ClusterDaxClient")
6171
static class DaxDynamoDbClient {
6272

63-
@ConditionalOnMissingBean
64-
@Bean
65-
public DynamoDbClient dynamoDbClient(DynamoDbProperties properties, AwsCredentialsProvider credentialsProvider,
66-
AwsRegionProvider regionProvider) throws IOException {
67-
DaxProperties daxProperties = properties.getDax();
68-
73+
private software.amazon.dax.Configuration.Builder toAwsDaxConfiguration(DaxProperties daxProperties) {
6974
PropertyMapper propertyMapper = PropertyMapper.get();
7075
software.amazon.dax.Configuration.Builder configuration = software.amazon.dax.Configuration.builder();
7176
propertyMapper.from(daxProperties.getIdleTimeoutMillis()).whenNonNull()
72-
.to(configuration::idleTimeoutMillis);
77+
.to(configuration::idleTimeoutMillis);
7378
propertyMapper.from(daxProperties.getConnectionTtlMillis()).whenNonNull()
74-
.to(configuration::connectionTtlMillis);
79+
.to(configuration::connectionTtlMillis);
7580
propertyMapper.from(daxProperties.getConnectTimeoutMillis()).whenNonNull()
76-
.to(configuration::connectTimeoutMillis);
81+
.to(configuration::connectTimeoutMillis);
7782
propertyMapper.from(daxProperties.getRequestTimeoutMillis()).whenNonNull()
78-
.to(configuration::requestTimeoutMillis);
83+
.to(configuration::requestTimeoutMillis);
7984
propertyMapper.from(daxProperties.getWriteRetries()).whenNonNull().to(configuration::writeRetries);
8085
propertyMapper.from(daxProperties.getReadRetries()).whenNonNull().to(configuration::readRetries);
8186
propertyMapper.from(daxProperties.getClusterUpdateIntervalMillis()).whenNonNull()
82-
.to(configuration::clusterUpdateIntervalMillis);
87+
.to(configuration::clusterUpdateIntervalMillis);
8388
propertyMapper.from(daxProperties.getEndpointRefreshTimeoutMillis()).whenNonNull()
84-
.to(configuration::endpointRefreshTimeoutMillis);
89+
.to(configuration::endpointRefreshTimeoutMillis);
8590
propertyMapper.from(daxProperties.getMaxConcurrency()).whenNonNull().to(configuration::maxConcurrency);
8691
propertyMapper.from(daxProperties.getMaxPendingConnectionAcquires()).whenNonNull()
87-
.to(configuration::maxPendingConnectionAcquires);
92+
.to(configuration::maxPendingConnectionAcquires);
8893
propertyMapper.from(daxProperties.getSkipHostNameVerification()).whenNonNull()
89-
.to(configuration::skipHostNameVerification);
94+
.to(configuration::skipHostNameVerification);
95+
96+
return configuration;
97+
}
98+
99+
@ConditionalOnMissingBean
100+
@Bean
101+
public DynamoDbClient daxDynamoDbClient(DynamoDbProperties properties,
102+
AwsCredentialsProvider credentialsProvider,
103+
AwsRegionProvider regionProvider) throws IOException {
104+
DaxProperties daxProperties = properties.getDax();
105+
106+
software.amazon.dax.Configuration.Builder configuration = toAwsDaxConfiguration(daxProperties);
90107

91108
configuration.region(AwsClientBuilderConfigurer.resolveRegion(properties, regionProvider))
92109
.credentialsProvider(credentialsProvider).url(properties.getDax().getUrl());
93110
return ClusterDaxClient.builder().overrideConfiguration(configuration.build()).build();
94111
}
95112

113+
@ConditionalOnMissingBean
114+
@Bean
115+
public DynamoDbAsyncClient daxDynamoDbAsyncClient(DynamoDbProperties properties,
116+
AwsCredentialsProvider credentialsProvider,
117+
AwsRegionProvider regionProvider) throws IOException {
118+
DaxProperties daxProperties = properties.getDax();
119+
120+
software.amazon.dax.Configuration.Builder configuration = toAwsDaxConfiguration(daxProperties);
121+
122+
configuration.region(AwsClientBuilderConfigurer.resolveRegion(properties, regionProvider))
123+
.credentialsProvider(credentialsProvider).url(properties.getDax().getUrl());
124+
return ClusterDaxAsyncClient.builder().overrideConfiguration(configuration.build()).build();
125+
}
96126
}
97127

98128
@Conditional(MissingDaxUrlCondition.class)
@@ -101,31 +131,61 @@ static class StandardDynamoDbClient {
101131

102132
@ConditionalOnMissingBean
103133
@Bean
104-
public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
134+
public DynamoDbClient standardDynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
105135
ObjectProvider<AwsClientCustomizer<DynamoDbClientBuilder>> configurer, DynamoDbProperties properties) {
106136
return awsClientBuilderConfigurer
107137
.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable()).build();
108138
}
139+
}
140+
141+
@Conditional(MissingDaxUrlCondition.class)
142+
@Configuration(proxyBeanMethods = false)
143+
static class StandardDynamoDbAsyncClient {
144+
145+
@ConditionalOnMissingBean
146+
@Bean
147+
public DynamoDbAsyncClient standardDynamoDbAsyncClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
148+
ObjectProvider<AwsClientCustomizer<DynamoDbAsyncClientBuilder>> configurer,
149+
DynamoDbProperties properties) {
150+
return awsClientBuilderConfigurer
151+
.configure(DynamoDbAsyncClient.builder(), properties, configurer.getIfAvailable()).build();
152+
}
109153

110154
}
111155

112-
@ConditionalOnMissingBean
113-
@Bean
114-
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
115-
return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
156+
@ConditionalOnClass(name = "software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient")
157+
@Configuration(proxyBeanMethods = false)
158+
static class DynamoDbEnhancedClientConfiguration {
159+
@ConditionalOnMissingBean
160+
@ConditionalOnClass(DynamoDbEnhancedClient.class)
161+
@Bean
162+
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
163+
return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
164+
}
165+
166+
@ConditionalOnMissingBean
167+
@ConditionalOnClass(DynamoDbEnhancedAsyncClient.class)
168+
@Bean
169+
public DynamoDbEnhancedAsyncClient dynamoDbEnhancedAsyncClient(DynamoDbAsyncClient dynamoDbClient) {
170+
return DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(dynamoDbClient).build();
171+
}
116172
}
117173

118-
@ConditionalOnMissingBean(DynamoDbOperations.class)
119-
@Bean
120-
public DynamoDbTemplate dynamoDBTemplate(DynamoDbProperties properties,
121-
DynamoDbEnhancedClient dynamoDbEnhancedClient, Optional<DynamoDbTableSchemaResolver> tableSchemaResolver,
122-
Optional<DynamoDbTableNameResolver> tableNameResolver) {
123-
DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver
174+
@ConditionalOnClass(name = "io.awspring.cloud.dynamodb.DynamoDbOperations")
175+
@Configuration(proxyBeanMethods = false)
176+
static class DynamoDbTemplateConfiguration {
177+
@ConditionalOnMissingBean(DynamoDbOperations.class)
178+
@Bean
179+
public DynamoDbTemplate dynamoDBTemplate(DynamoDbProperties properties,
180+
DynamoDbEnhancedClient dynamoDbEnhancedClient, Optional<DynamoDbTableSchemaResolver> tableSchemaResolver,
181+
Optional<DynamoDbTableNameResolver> tableNameResolver) {
182+
DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver
124183
.orElseGet(DefaultDynamoDbTableSchemaResolver::new);
125184

126-
DynamoDbTableNameResolver tableNameRes = tableNameResolver
185+
DynamoDbTableNameResolver tableNameRes = tableNameResolver
127186
.orElseGet(() -> new DefaultDynamoDbTableNameResolver(properties.getTablePrefix()));
128-
return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes);
187+
return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes);
188+
}
129189
}
130190

131191
static class MissingDaxUrlCondition extends NoneNestedConditions {

spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@
4040
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
4141
import software.amazon.awssdk.http.SdkHttpClient;
4242
import software.amazon.awssdk.http.apache.ApacheHttpClient;
43+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
4344
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
4445
import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
46+
import software.amazon.dax.ClusterDaxAsyncClient;
4547
import software.amazon.dax.ClusterDaxClient;
4648

4749
/**
@@ -96,6 +98,7 @@ void withDynamoDbClientCustomEndpoint() {
9698
contextRunner.withPropertyValues("spring.cloud.aws.dynamodb.endpoint:http://localhost:8090")
9799
.run(context -> {
98100
assertThat(context).hasSingleBean(DynamoDbClient.class);
101+
assertThat(context).hasSingleBean(DynamoDbAsyncClient.class);
99102
assertThat(context).hasSingleBean(DynamoDbTemplate.class);
100103
assertThat(context).hasSingleBean(DynamoDbEnhancedClient.class);
101104

@@ -109,6 +112,7 @@ void withDynamoDbClientCustomEndpoint() {
109112
void dynamoDbClientConfiguredSinceNoUrl() {
110113
contextRunner.run(context -> {
111114
assertThat(context).hasSingleBean(DynamoDbClient.class);
115+
assertThat(context).hasSingleBean(DynamoDbAsyncClient.class);
112116
assertThat(context).hasSingleBean(DynamoDbTemplate.class);
113117
assertThat(context).hasSingleBean(DynamoDbEnhancedClient.class);
114118
assertThat(context).doesNotHaveBean(ClusterDaxClient.class);
@@ -170,6 +174,7 @@ void defaultsAreUsedWhenPropertiesAreNotSet() {
170174
.run(context -> {
171175
ConfiguredDaxClient daxClient = new ConfiguredDaxClient(
172176
context.getBean(ClusterDaxClient.class));
177+
assertThat(context).hasSingleBean(ClusterDaxAsyncClient.class);
173178
assertThat(daxClient.getUrl())
174179
.isEqualTo("dax://something.dax-clusters.us-east-1.amazonaws.com");
175180
assertThat(daxClient.getWriteRetries()).isEqualTo(2);
@@ -211,6 +216,7 @@ void clusterDaxClient_CustomUrl_DefaultValues() {
211216
.run(context -> {
212217
ConfiguredDaxClient daxClient = new ConfiguredDaxClient(
213218
context.getBean(ClusterDaxClient.class));
219+
assertThat(context).hasSingleBean(ClusterDaxAsyncClient.class);
214220
assertThat(daxClient.getUrl())
215221
.isEqualTo("dax://something.dax-clusters.us-east-1.amazonaws.com");
216222
assertThat(daxClient.getWriteRetries()).isEqualTo(2);
@@ -237,6 +243,7 @@ void customTableResolverResolverCanBeConfigured() {
237243
assertThat(dynamoDBDynamoDbTableNameResolver)
238244
.isInstanceOf(CustomDynamoDBDynamoDbTableNameResolver.class);
239245

246+
assertThat(context).hasSingleBean(ClusterDaxAsyncClient.class);
240247
});
241248
}
242249

0 commit comments

Comments
 (0)