diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 7298f3733ec3..62a7e2d221ee 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -86,7 +86,6 @@ spring-data-cassandra-test spring-data-cosmosdb spring-data-couchbase-2 - spring-data-dynamodb spring-data-eclipselink diff --git a/persistence-modules/spring-data-dynamodb/.gitignore b/persistence-modules/spring-data-dynamodb/.gitignore deleted file mode 100644 index e26d6af43896..000000000000 --- a/persistence-modules/spring-data-dynamodb/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -.settings/ -.classpath -.project diff --git a/persistence-modules/spring-data-dynamodb/README.md b/persistence-modules/spring-data-dynamodb/README.md deleted file mode 100644 index 9f6cdfdb17f0..000000000000 --- a/persistence-modules/spring-data-dynamodb/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Spring Data with DynamoDB - -This module contains articles about Spring Data with DynamoDB. - -### Relevant Articles: -- [DynamoDB in a Spring Boot Application Using Spring Data](http://www.baeldung.com/spring-data-dynamodb) diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml deleted file mode 100644 index d37aeda8e43f..000000000000 --- a/persistence-modules/spring-data-dynamodb/pom.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - 4.0.0 - spring-data-dynamodb - spring-data-dynamodb - jar - This is simple boot application for Spring boot dynamodb test - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.data - spring-data-commons - ${spring.version} - - - io.dropwizard.metrics - metrics-core - - - com.h2database - h2 - - - org.springframework.boot - spring-boot-starter - - - com.jayway.jsonpath - json-path - test - - - org.springframework.boot - spring-boot-starter-mail - - - org.webjars - bootstrap - ${bootstrap.version} - - - com.amazonaws - aws-java-sdk-dynamodb - ${aws-java-sdk-dynamodb.version} - - - commons-logging - commons-logging - - - - - com.github.derjust - spring-data-dynamodb - ${spring-data-dynamodb.version} - - - org.apache.httpcomponents - httpclient - - - - - - com.amazonaws - DynamoDBLocal - ${dynamodblocal.version} - test - - - software.amazon.awssdk - url-connection-client - ${url-connection-client.version} - test - - - - com.almworks.sqlite4java - sqlite4java - ${sqlite4java.version} - test - - - com.almworks.sqlite4java - sqlite4java-win32-x86 - ${sqlite4java.version} - dll - test - - - com.almworks.sqlite4java - sqlite4java-win32-x64 - ${sqlite4java.version} - dll - test - - - com.almworks.sqlite4java - libsqlite4java-osx - ${sqlite4java.version} - dylib - test - - - com.almworks.sqlite4java - libsqlite4java-linux-i386 - ${sqlite4java.version} - so - test - - - com.almworks.sqlite4java - libsqlite4java-linux-amd64 - ${sqlite4java.version} - so - test - - - net.bytebuddy - byte-buddy - 1.14.13 - test - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - copy-dependencies - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.basedir}/native-libs - - - - - - - - - - com.baeldung.Application - 2.7.18 - 5.1.0 - 1.12.714 - 3.3.7-1 - 1.0.392 - 1.25.0 - 3.1.1 - 2.25.45 - - - \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/Application.java deleted file mode 100644 index f5e0e98fd4bd..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/Application.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; - -@SpringBootApplication -@ComponentScan(basePackages = { "com.baeldung" }) -public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/config/DynamoDBConfig.java b/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/config/DynamoDBConfig.java deleted file mode 100644 index 7e97e6b3837c..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/config/DynamoDBConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.spring.data.dynamodb.config; - -import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; - -@Configuration -@EnableDynamoDBRepositories(basePackages = "com.baeldung.spring.data.dynamodb.repositories") -public class DynamoDBConfig { - - @Value("${amazon.dynamodb.endpoint}") - private String amazonDynamoDBEndpoint; - - @Value("${amazon.aws.accesskey}") - private String amazonAWSAccessKey; - - @Value("${amazon.aws.secretkey}") - private String amazonAWSSecretKey; - - @Autowired - private ApplicationContext context; - - @Bean - public AmazonDynamoDB amazonDynamoDB() { - AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials()); - if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) { - amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint); - } - return amazonDynamoDB; - } - - @Bean - public AWSCredentials amazonAWSCredentials() { - return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey); - } - - @Bean(name = "mvcHandlerMappingIntrospectorCustom") - public HandlerMappingIntrospector mvcHandlerMappingIntrospectorCustom() { - return new HandlerMappingIntrospector(context); - } -} diff --git a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/model/ProductInfo.java b/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/model/ProductInfo.java deleted file mode 100644 index 3b9b0628dd93..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/model/ProductInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.spring.data.dynamodb.model; - -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; - -@DynamoDBTable(tableName = "ProductInfo") -public class ProductInfo { - private String id; - private String msrp; - private String cost; - - public ProductInfo() { - } - - public ProductInfo(String cost, String msrp) { - this.msrp = msrp; - this.cost = cost; - } - - @DynamoDBHashKey - @DynamoDBAutoGeneratedKey - public String getId() { - return id; - } - - @DynamoDBAttribute - public String getMsrp() { - return msrp; - } - - @DynamoDBAttribute - public String getCost() { - return cost; - } - - public void setId(String id) { - this.id = id; - } - - public void setMsrp(String msrp) { - this.msrp = msrp; - } - - public void setCost(String cost) { - this.cost = cost; - } -} diff --git a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/repositories/ProductInfoRepository.java b/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/repositories/ProductInfoRepository.java deleted file mode 100644 index 6e8b493c3b66..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/java/com/baeldung/spring/data/dynamodb/repositories/ProductInfoRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.spring.data.dynamodb.repositories; - -import java.util.Optional; - -import org.socialsignin.spring.data.dynamodb.repository.EnableScan; -import org.springframework.data.repository.CrudRepository; - -import com.baeldung.spring.data.dynamodb.model.ProductInfo; - -@EnableScan -public interface ProductInfoRepository extends CrudRepository { - Optional findById(String id); -} diff --git a/persistence-modules/spring-data-dynamodb/src/main/resources/application.properties b/persistence-modules/spring-data-dynamodb/src/main/resources/application.properties deleted file mode 100644 index e6911bc9e7e7..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/resources/application.properties +++ /dev/null @@ -1,32 +0,0 @@ -server.port=8080 -server.contextPath=/springbootapp -management.port=8081 -management.address=127.0.0.1 - -endpoints.shutdown.enabled=true - -endpoints.jmx.domain=Spring Sample Application -endpoints.jmx.uniqueNames=true - -spring.jmx.enabled=true -endpoints.jmx.enabled=true - -## for pretty printing of json when endpoints accessed over HTTP -http.mappers.jsonPrettyPrint=true - -## Configuring info endpoint -info.app.name=Spring Sample Application -info.app.description=This is my first spring boot application G1 -info.app.version=1.0.0 - -## Spring Security Configurations -security.user.name=admin1 -security.user.password=secret1 -management.security.role=SUPERUSER - -logging.level.org.springframework=INFO - -#AWS Keys -amazon.dynamodb.endpoint=http://localhost:8000/ -amazon.aws.accesskey=test1 -amazon.aws.secretkey=test1 \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/main/resources/demo.properties b/persistence-modules/spring-data-dynamodb/src/main/resources/demo.properties deleted file mode 100644 index 649b64f59b3a..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/resources/demo.properties +++ /dev/null @@ -1,6 +0,0 @@ -spring.output.ansi.enabled=never -server.port=7070 - -# Security -security.user.name=admin -security.user.password=password \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/main/resources/logback.xml b/persistence-modules/spring-data-dynamodb/src/main/resources/logback.xml deleted file mode 100644 index ec0dc2469ae0..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/resources/logback.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - - - - \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/main/resources/templates/index.html b/persistence-modules/spring-data-dynamodb/src/main/resources/templates/index.html deleted file mode 100644 index 046d21600a7c..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/main/resources/templates/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - WebJars Demo - - - - - - - × - Success! It is working as we expected. - - - - - - - - \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index 13c1c162f175..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = Application.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java b/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java deleted file mode 100644 index a7269681f966..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.baeldung.spring.data.dynamodb.repository; - -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ResourceInUseException; -import com.baeldung.Application; -import com.baeldung.spring.data.dynamodb.model.ProductInfo; -import com.baeldung.spring.data.dynamodb.repositories.ProductInfoRepository; -import com.baeldung.spring.data.dynamodb.repository.rule.LocalDbCreationRule; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Optional; -import java.util.Properties; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsEqual.equalTo; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = Application.class) -@WebAppConfiguration -@ActiveProfiles("local") -public class ProductInfoRepositoryIntegrationTest { - - @ClassRule - public static LocalDbCreationRule dynamoDB = new LocalDbCreationRule(); - private static DynamoDBMapper dynamoDBMapper; - private static AmazonDynamoDB amazonDynamoDB; - - @Autowired - private ProductInfoRepository repository; - - private static final String DYNAMODB_ENDPOINT = "amazon.dynamodb.endpoint"; - private static final String AWS_ACCESSKEY = "amazon.aws.accesskey"; - private static final String AWS_SECRETKEY = "amazon.aws.secretkey"; - - private static final String EXPECTED_COST = "20"; - private static final String EXPECTED_PRICE = "50"; - - @BeforeClass - public static void setupClass() { - Properties testProperties = loadFromFileInClasspath("application.properties") - .filter(properties -> !isEmpty(properties.getProperty(AWS_ACCESSKEY))) - .filter(properties -> !isEmpty(properties.getProperty(AWS_SECRETKEY))) - .filter(properties -> !isEmpty(properties.getProperty(DYNAMODB_ENDPOINT))) - .orElseThrow(() -> new RuntimeException("Unable to get all of the required test property values")); - - String amazonAWSAccessKey = testProperties.getProperty(AWS_ACCESSKEY); - String amazonAWSSecretKey = testProperties.getProperty(AWS_SECRETKEY); - String amazonDynamoDBEndpoint = testProperties.getProperty(DYNAMODB_ENDPOINT); - - amazonDynamoDB = new AmazonDynamoDBClient(new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey)); - amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint); - dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB); - } - - @Before - public void setup() throws Exception { - - try { - dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB); - - CreateTableRequest tableRequest = dynamoDBMapper.generateCreateTableRequest(ProductInfo.class); - - tableRequest.setProvisionedThroughput(new ProvisionedThroughput(1L, 1L)); - - amazonDynamoDB.createTable(tableRequest); - } catch (ResourceInUseException e) { - // Do nothing, table already created - } - - // TODO How to handle different environments. i.e. AVOID deleting all entries in ProductInfo on table - dynamoDBMapper.batchDelete(repository.findAll()); - } - - @Test - public void givenItemWithExpectedCost_whenRunFindAll_thenItemIsFound() { - - ProductInfo productInfo = new ProductInfo(EXPECTED_COST, EXPECTED_PRICE); - repository.save(productInfo); - - List result = (List) repository.findAll(); - assertThat(result.size(), is(greaterThan(0))); - assertThat(result.get(0).getCost(), is(equalTo(EXPECTED_COST))); - } - - private static boolean isEmpty(String inputString) { - return inputString == null || "".equals(inputString); - } - - private static Optional loadFromFileInClasspath(String fileName) { - InputStream stream = null; - try { - Properties config = new Properties(); - Path configLocation = Paths.get(ClassLoader.getSystemResource(fileName).toURI()); - stream = Files.newInputStream(configLocation); - config.load(stream); - return Optional.of(config); - } catch (Exception e) { - return Optional.empty(); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - } - } - } - } -} diff --git a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/rule/LocalDbCreationRule.java b/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/rule/LocalDbCreationRule.java deleted file mode 100644 index 555d558b0692..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/rule/LocalDbCreationRule.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.spring.data.dynamodb.repository.rule; - -import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; -import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; -import org.junit.rules.ExternalResource; - -import java.util.Optional; - -public class LocalDbCreationRule extends ExternalResource { - - protected DynamoDBProxyServer server; - - public LocalDbCreationRule() { - System.setProperty("sqlite4java.library.path", "native-libs"); - } - - @Override - protected void before() throws Exception { - String port = "8000"; - this.server = ServerRunner.createServerFromCommandLineArgs(new String[]{"-inMemory", "-port", port}); - server.start(); - } - - @Override - protected void after() { - this.stopUnchecked(server); - } - - protected void stopUnchecked(DynamoDBProxyServer dynamoDbServer) { - try { - dynamoDbServer.stop(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/persistence-modules/spring-data-dynamodb/src/test/resources/application.properties b/persistence-modules/spring-data-dynamodb/src/test/resources/application.properties deleted file mode 100644 index 01e8a2e52ece..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/resources/application.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.mail.host=localhost -spring.mail.port=8025 -spring.mail.properties.mail.smtp.auth=false - -amazon.dynamodb.endpoint=http://localhost:8000/ -amazon.aws.accesskey=key -amazon.aws.secretkey=key2 \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/src/test/resources/exception-hibernate.properties b/persistence-modules/spring-data-dynamodb/src/test/resources/exception-hibernate.properties deleted file mode 100644 index cde746acb931..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/resources/exception-hibernate.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.profiles.active=exception -spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext diff --git a/persistence-modules/spring-data-dynamodb/src/test/resources/exception.properties b/persistence-modules/spring-data-dynamodb/src/test/resources/exception.properties deleted file mode 100644 index c55e415a3ae8..000000000000 --- a/persistence-modules/spring-data-dynamodb/src/test/resources/exception.properties +++ /dev/null @@ -1,6 +0,0 @@ -# Security -security.user.name=admin -security.user.password=password - -spring.dao.exceptiontranslation.enabled=false -spring.profiles.active=exception \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/pom.xml b/spring-cloud-modules/spring-cloud-aws-v3/pom.xml index 0d6cb0f1a1f0..5a723de6250e 100644 --- a/spring-cloud-modules/spring-cloud-aws-v3/pom.xml +++ b/spring-cloud-modules/spring-cloud-aws-v3/pom.xml @@ -39,6 +39,10 @@ io.awspring.cloud spring-cloud-aws-starter-sqs + + io.awspring.cloud + spring-cloud-aws-starter-dynamodb + org.springframework.boot spring-boot-starter-test @@ -48,6 +52,11 @@ org.springframework.boot spring-boot-testcontainers + + io.awspring.cloud + spring-cloud-aws-testcontainers + test + org.testcontainers localstack @@ -68,6 +77,12 @@ assertj-core test + + org.instancio + instancio-junit + ${instancio.version} + test + @@ -82,6 +97,7 @@ com.baeldung.spring.cloud.aws.sqs.SpringCloudAwsApplication 3.2.0 + 5.3.0 3.1.0 17 17 diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/Application.java b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/Application.java new file mode 100644 index 000000000000..b1e6d3a744ae --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/Application.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +class Application { + + public static void main(String[] args) { + SpringApplication springApplication = new SpringApplication(Application.class); + springApplication.setAdditionalProfiles("dynamodb"); + springApplication.run(args); + } + +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/CustomTableNameResolver.java b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/CustomTableNameResolver.java new file mode 100644 index 000000000000..997be8ae8fc2 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/CustomTableNameResolver.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import io.awspring.cloud.dynamodb.DynamoDbTableNameResolver; +import org.springframework.stereotype.Component; + +@Component +class CustomTableNameResolver implements DynamoDbTableNameResolver { + + @Override + public String resolve(Class clazz) { + return clazz.getAnnotation(TableName.class).name(); + } + +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/TableName.java b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/TableName.java new file mode 100644 index 000000000000..975fc8f7d997 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/TableName.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target(TYPE) +@Retention(RUNTIME) +@interface TableName { + String name(); +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/User.java b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/User.java new file mode 100644 index 000000000000..9c575572e57d --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/main/java/com/baeldung/spring/cloud/aws/dynamodb/User.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; + +import java.util.UUID; + +@DynamoDbBean +@TableName(name = "users") +public class User { + + private UUID id; + private String name; + private String email; + + @DynamoDbPartitionKey + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/main/resources/application-dynamodb.yaml b/spring-cloud-modules/spring-cloud-aws-v3/src/main/resources/application-dynamodb.yaml new file mode 100644 index 000000000000..41b0530da011 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/main/resources/application-dynamodb.yaml @@ -0,0 +1,8 @@ +spring: + cloud: + aws: + dynamodb: + region: ${AWS_REGION} + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/TestcontainersConfiguration.java b/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/TestcontainersConfiguration.java new file mode 100644 index 000000000000..3b4466327183 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/TestcontainersConfiguration.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.containers.localstack.LocalStackContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; + +@TestConfiguration(proxyBeanMethods = false) +class TestcontainersConfiguration { + + @Bean + @ServiceConnection + LocalStackContainer localStackContainer() { + return new LocalStackContainer(DockerImageName.parse("localstack/localstack:4.3.0")) + .withCopyFileToContainer( + MountableFile.forClasspathResource("init-dynamodb-table.sh", 0744), + "/etc/localstack/init/ready.d/init-dynamodb-table.sh" + ) + .withServices(LocalStackContainer.Service.DYNAMODB) + .waitingFor(Wait.forLogMessage(".*Executed init-dynamodb-table.sh.*", 1)); + } + +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/UserCRUDLiveTest.java b/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/UserCRUDLiveTest.java new file mode 100644 index 000000000000..a439e15883e3 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/test/java/com/baeldung/spring/cloud/aws/dynamodb/UserCRUDLiveTest.java @@ -0,0 +1,120 @@ +package com.baeldung.spring.cloud.aws.dynamodb; + +import io.awspring.cloud.dynamodb.DynamoDbTemplate; +import net.bytebuddy.utility.RandomString; +import org.instancio.Instancio; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@Import(TestcontainersConfiguration.class) +class UserCRUDLiveTest { + + @Autowired + private DynamoDbTemplate dynamoDbTemplate; + + @Test + void whenUserSaved_thenItemCreatedInDynamoDB() { + User user = Instancio.create(User.class); + + dynamoDbTemplate.save(user); + + Key partitionKey = Key.builder().partitionValue(user.getId().toString()).build(); + User retrievedUser = dynamoDbTemplate.load(partitionKey, User.class); + assertThat(retrievedUser) + .isNotNull() + .usingRecursiveComparison() + .isEqualTo(user); + } + + @Test + void whenUserUpdated_thenItemUpdatedInDynamoDB() { + User user = Instancio.create(User.class); + dynamoDbTemplate.save(user); + + String updatedName = RandomString.make(); + String updatedEmail = RandomString.make(); + user.setName(updatedName); + user.setEmail(updatedEmail); + dynamoDbTemplate.update(user); + + Key partitionKey = Key.builder().partitionValue(user.getId().toString()).build(); + User updatedUser = dynamoDbTemplate.load(partitionKey, User.class); + assertThat(updatedUser) + .isNotNull(); + assertThat(updatedUser.getName()) + .isEqualTo(updatedName); + assertThat(updatedUser.getEmail()) + .isEqualTo(updatedEmail); + } + + @Test + void whenUserDeleted_thenItemRemovedFromDynamoDB() { + User user = Instancio.create(User.class); + dynamoDbTemplate.save(user); + + dynamoDbTemplate.delete(user); + + Key partitionKey = Key.builder().partitionValue(user.getId().toString()).build(); + User deletedUser = dynamoDbTemplate.load(partitionKey, User.class); + assertThat(deletedUser) + .isNull(); + } + + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) + void whenUserEntityScanned_thenAllSavedItemsReturned() { + int numberOfUsers = 10; + for (int i = 0; i < numberOfUsers; i++) { + User user = Instancio.create(User.class); + dynamoDbTemplate.save(user); + } + + List retrievedUsers = dynamoDbTemplate + .scanAll(User.class) + .items() + .stream() + .toList(); + + assertThat(retrievedUsers.size()) + .isEqualTo(numberOfUsers); + } + + @Test + void whenUserQueriedByEmail_thenCorrectItemReturned() { + User user = Instancio.create(User.class); + dynamoDbTemplate.save(user); + + Expression expression = Expression.builder() + .expression("#email = :email") + .putExpressionName("#email", "email") + .putExpressionValue(":email", AttributeValue.builder().s(user.getEmail()).build()) + .build(); + ScanEnhancedRequest scanRequest = ScanEnhancedRequest + .builder() + .filterExpression(expression) + .build(); + User retrievedUser = dynamoDbTemplate.scan(scanRequest, User.class) + .items() + .stream() + .findFirst() + .get(); + + assertThat(retrievedUser) + .isNotNull() + .usingRecursiveComparison() + .isEqualTo(user); + } + +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-aws-v3/src/test/resources/init-dynamodb-table.sh b/spring-cloud-modules/spring-cloud-aws-v3/src/test/resources/init-dynamodb-table.sh new file mode 100644 index 000000000000..efc5b8449c93 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-aws-v3/src/test/resources/init-dynamodb-table.sh @@ -0,0 +1,12 @@ +#!/bin/bash +table_name="users" +partition_key="id" + +awslocal dynamodb create-table \ + --table-name "$table_name" \ + --key-schema AttributeName="$partition_key",KeyType=HASH \ + --attribute-definitions AttributeName="$partition_key",AttributeType=S \ + --billing-mode PAY_PER_REQUEST + +echo "DynamoDB table '$table_name' created successfully with partition key '$partition_key'" +echo "Executed init-dynamodb-table.sh" \ No newline at end of file