From eba98e131e7e61f0d9bf6f12e85aec7253b50e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Thu, 20 Apr 2023 07:55:04 +0000 Subject: [PATCH] Make DynamoDb Clients Standalone --- ...a => DynamoDbClientAutoConfiguration.java} | 92 ++++++++++--------- ...namoDbEnhancedClientAutoConfiguration.java | 57 ++++++++++++ .../DynamoDbTemplateAutoConfiguration.java | 62 +++++++++++++ .../DynamoDbAutoConfigurationTest.java | 4 +- 4 files changed, 169 insertions(+), 46 deletions(-) rename spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/{DynamoDbAutoConfiguration.java => DynamoDbClientAutoConfiguration.java} (65%) create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbEnhancedClientAutoConfiguration.java create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbTemplateAutoConfiguration.java diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbClientAutoConfiguration.java similarity index 65% rename from spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java rename to spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbClientAutoConfiguration.java index 6a37d350e..9fade0d7b 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbClientAutoConfiguration.java @@ -15,13 +15,12 @@ */ package io.awspring.cloud.autoconfigure.dynamodb; +import java.io.IOException; + import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; -import io.awspring.cloud.dynamodb.*; -import java.io.IOException; -import java.util.Optional; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -30,102 +29,107 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClientBuilder; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; +import software.amazon.dax.ClusterDaxAsyncClient; import software.amazon.dax.ClusterDaxClient; /** - * {@link EnableAutoConfiguration Auto-configuration} for DynamoDB integration. + * {@link DynamoDbClientAutoConfiguration Auto-configuration} for DynamoDB integration. * * @author Matej Nedic * @author Arun Patra * @since 3.0.0 */ @AutoConfiguration -@EnableConfigurationProperties(DynamoDbProperties.class) -@ConditionalOnClass({ DynamoDbClient.class, DynamoDbEnhancedClient.class, DynamoDbTemplate.class }) -@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class }) +@ConditionalOnClass({DynamoDbClient.class, DynamoDbAsyncClient.class}) +@AutoConfigureAfter({CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class}) @ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.enabled", havingValue = "true", matchIfMissing = true) -public class DynamoDbAutoConfiguration { +public class DynamoDbClientAutoConfiguration { + @ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.dax.url") @Configuration(proxyBeanMethods = false) @ConditionalOnClass(name = "software.amazon.dax.ClusterDaxClient") static class DaxDynamoDbClient { - @ConditionalOnMissingBean @Bean - public DynamoDbClient dynamoDbClient(DynamoDbProperties properties, AwsCredentialsProvider credentialsProvider, - AwsRegionProvider regionProvider) throws IOException { + @ConditionalOnMissingBean + software.amazon.dax.Configuration daxConfiguration(DynamoDbProperties properties, + AwsCredentialsProvider credentialsProvider, + AwsRegionProvider regionProvider) { DaxProperties daxProperties = properties.getDax(); PropertyMapper propertyMapper = PropertyMapper.get(); software.amazon.dax.Configuration.Builder configuration = software.amazon.dax.Configuration.builder(); propertyMapper.from(daxProperties.getIdleTimeoutMillis()).whenNonNull() - .to(configuration::idleTimeoutMillis); + .to(configuration::idleTimeoutMillis); propertyMapper.from(daxProperties.getConnectionTtlMillis()).whenNonNull() - .to(configuration::connectionTtlMillis); + .to(configuration::connectionTtlMillis); propertyMapper.from(daxProperties.getConnectTimeoutMillis()).whenNonNull() - .to(configuration::connectTimeoutMillis); + .to(configuration::connectTimeoutMillis); propertyMapper.from(daxProperties.getRequestTimeoutMillis()).whenNonNull() - .to(configuration::requestTimeoutMillis); + .to(configuration::requestTimeoutMillis); propertyMapper.from(daxProperties.getWriteRetries()).whenNonNull().to(configuration::writeRetries); propertyMapper.from(daxProperties.getReadRetries()).whenNonNull().to(configuration::readRetries); propertyMapper.from(daxProperties.getClusterUpdateIntervalMillis()).whenNonNull() - .to(configuration::clusterUpdateIntervalMillis); + .to(configuration::clusterUpdateIntervalMillis); propertyMapper.from(daxProperties.getEndpointRefreshTimeoutMillis()).whenNonNull() - .to(configuration::endpointRefreshTimeoutMillis); + .to(configuration::endpointRefreshTimeoutMillis); propertyMapper.from(daxProperties.getMaxConcurrency()).whenNonNull().to(configuration::maxConcurrency); propertyMapper.from(daxProperties.getMaxPendingConnectionAcquires()).whenNonNull() - .to(configuration::maxPendingConnectionAcquires); + .to(configuration::maxPendingConnectionAcquires); propertyMapper.from(daxProperties.getSkipHostNameVerification()).whenNonNull() - .to(configuration::skipHostNameVerification); + .to(configuration::skipHostNameVerification); configuration.region(AwsClientBuilderConfigurer.resolveRegion(properties, regionProvider)) - .credentialsProvider(credentialsProvider).url(properties.getDax().getUrl()); - return ClusterDaxClient.builder().overrideConfiguration(configuration.build()).build(); + .credentialsProvider(credentialsProvider).url(properties.getDax().getUrl()); + + return configuration.build(); + } + + @ConditionalOnMissingBean + @Bean + public DynamoDbClient dynamoDbClient(software.amazon.dax.Configuration configuration) throws IOException { + return ClusterDaxClient.builder().overrideConfiguration(configuration).build(); } + @ConditionalOnMissingBean + @Bean + public DynamoDbAsyncClient dynamoDbAsyncClient(software.amazon.dax.Configuration configuration) throws IOException { + return ClusterDaxAsyncClient.builder().overrideConfiguration(configuration).build(); + } } - @Conditional(MissingDaxUrlCondition.class) + @Conditional(DynamoDbClientAutoConfiguration.MissingDaxUrlCondition.class) @Configuration(proxyBeanMethods = false) static class StandardDynamoDbClient { @ConditionalOnMissingBean @Bean public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, DynamoDbProperties properties) { + ObjectProvider> configurer, + DynamoDbProperties properties) { return awsClientBuilderConfigurer - .configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable()).build(); + .configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable()).build(); } - } - - @ConditionalOnMissingBean - @Bean - public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) { - return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build(); - } + @ConditionalOnMissingBean + @Bean + public DynamoDbAsyncClient dynamodbAsyncClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + DynamoDbProperties properties) { + return awsClientBuilderConfigurer + .configure(DynamoDbAsyncClient.builder(), properties, configurer.getIfAvailable()).build(); + } - @ConditionalOnMissingBean(DynamoDbOperations.class) - @Bean - public DynamoDbTemplate dynamoDBTemplate(DynamoDbProperties properties, - DynamoDbEnhancedClient dynamoDbEnhancedClient, Optional tableSchemaResolver, - Optional tableNameResolver) { - DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver - .orElseGet(DefaultDynamoDbTableSchemaResolver::new); - - DynamoDbTableNameResolver tableNameRes = tableNameResolver - .orElseGet(() -> new DefaultDynamoDbTableNameResolver(properties.getTablePrefix())); - return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes); } static class MissingDaxUrlCondition extends NoneNestedConditions { diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbEnhancedClientAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbEnhancedClientAutoConfiguration.java new file mode 100644 index 000000000..61865ded3 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbEnhancedClientAutoConfiguration.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.dynamodb; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * {@link DynamoDbEnhancedClientAutoConfiguration Auto-configuration} for DynamoDB integration. + * + * @author Matej Nedic + * @author Arun Patra + * @since 3.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({DynamoDbEnhancedClient.class, DynamoDbEnhancedAsyncClient.class}) +@AutoConfigureAfter(DynamoDbClientAutoConfiguration.class) +@ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.enabled", havingValue = "true", matchIfMissing = true) +public class DynamoDbEnhancedClientAutoConfiguration { + + @ConditionalOnMissingBean + @Bean + public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) { + return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build(); + } + + + @ConditionalOnMissingBean + @Bean + public DynamoDbEnhancedAsyncClient dynamoDbEnhancedAsyncClient(DynamoDbAsyncClient dynamoDbAsyncClient) { + return DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(dynamoDbAsyncClient) + .build(); + } +} diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbTemplateAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbTemplateAutoConfiguration.java new file mode 100644 index 000000000..309fc5cae --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbTemplateAutoConfiguration.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.dynamodb; + +import java.util.Optional; + +import io.awspring.cloud.dynamodb.DefaultDynamoDbTableNameResolver; +import io.awspring.cloud.dynamodb.DefaultDynamoDbTableSchemaResolver; +import io.awspring.cloud.dynamodb.DynamoDbOperations; +import io.awspring.cloud.dynamodb.DynamoDbTableNameResolver; +import io.awspring.cloud.dynamodb.DynamoDbTableSchemaResolver; +import io.awspring.cloud.dynamodb.DynamoDbTemplate; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for DynamoDB integration. + * + * @author Matej Nedic + * @author Arun Patra + * @since 3.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({DynamoDbClient.class, DynamoDbEnhancedClient.class, DynamoDbTemplate.class}) +@AutoConfigureAfter(DynamoDbEnhancedClientAutoConfiguration.class) +@ConditionalOnProperty(name = "spring.cloud.aws.dynamodb.enabled", havingValue = "true", matchIfMissing = true) +public class DynamoDbTemplateAutoConfiguration { + + @ConditionalOnMissingBean(DynamoDbOperations.class) + @Bean + public DynamoDbTemplate dynamoDBTemplate(DynamoDbProperties properties, + DynamoDbEnhancedClient dynamoDbEnhancedClient, Optional tableSchemaResolver, + Optional tableNameResolver) { + DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver + .orElseGet(DefaultDynamoDbTableSchemaResolver::new); + + DynamoDbTableNameResolver tableNameRes = tableNameResolver + .orElseGet(() -> new DefaultDynamoDbTableNameResolver(properties.getTablePrefix())); + return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes); + } + +} diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java index 178327a74..bc6b81f9f 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java @@ -45,7 +45,7 @@ import software.amazon.dax.ClusterDaxClient; /** - * Tests for {@link DynamoDbAutoConfiguration}. + * Tests for {@link DynamoDbTemplateAutoConfiguration}. * * @author Matej Nedic */ @@ -55,7 +55,7 @@ class DynamoDbAutoConfigurationTest { .withPropertyValues("spring.cloud.aws.region.static:eu-west-1", "spring.cloud.aws.credentials.access-key:noop", "spring.cloud.aws.credentials.secret-key:noop") .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, - CredentialsProviderAutoConfiguration.class, DynamoDbAutoConfiguration.class)); + CredentialsProviderAutoConfiguration.class, DynamoDbTemplateAutoConfiguration.class)); @Nested class DynamoDbTests {