diff --git a/apigw-lambda-snapstart/UnicornFunction/pom.xml b/apigw-lambda-snapstart/UnicornFunction/pom.xml index 0c25aa55c..f1f2f2240 100644 --- a/apigw-lambda-snapstart/UnicornFunction/pom.xml +++ b/apigw-lambda-snapstart/UnicornFunction/pom.xml @@ -19,7 +19,7 @@ 1.16.0 UTF-8 UTF-8 - 2.20.99 + 2.22.0 diff --git a/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/config/DynamoDbConfig.java b/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/config/DynamoDbConfig.java index d2bf57542..987d0aae7 100644 --- a/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/config/DynamoDbConfig.java +++ b/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/config/DynamoDbConfig.java @@ -7,33 +7,33 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; -import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; @Configuration public class DynamoDbConfig { @Bean - public DynamoDbAsyncClient dynamoDbAsyncClient() { - return DynamoDbAsyncClient.builder() + public DynamoDbClient dynamoDbClient() { + return DynamoDbClient.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .httpClientBuilder(AwsCrtAsyncHttpClient.builder()) + .httpClientBuilder(AwsCrtHttpClient.builder()) .build(); } @Bean - public DynamoDbEnhancedAsyncClient dynamoDbEnhancedClient(DynamoDbAsyncClient dynamoDbAsyncClient) { - return DynamoDbEnhancedAsyncClient.builder() - .dynamoDbClient(dynamoDbAsyncClient) + public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) { + return DynamoDbEnhancedClient.builder() + .dynamoDbClient(dynamoDbClient) .build(); } @Bean - public DynamoDbAsyncTable unicornDynamoDbAsyncTable(DynamoDbEnhancedAsyncClient dynamoDbEnhancedClient) { + public DynamoDbTable unicornDynamoDbTable(DynamoDbEnhancedClient dynamoDbEnhancedClient) { return dynamoDbEnhancedClient.table(System.getenv("UNICORN_TABLE_NAME"), TableSchema.fromClass(Unicorn.class)); } } diff --git a/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/data/DynamoDBUnicornRepository.java b/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/data/DynamoDBUnicornRepository.java index 81a95a9cf..795fb5a9c 100644 --- a/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/data/DynamoDBUnicornRepository.java +++ b/apigw-lambda-snapstart/UnicornFunction/src/main/java/com/unicorn/store/data/DynamoDBUnicornRepository.java @@ -12,38 +12,34 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Repository; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import java.util.Optional; -import java.util.concurrent.ExecutionException; @Repository public class DynamoDBUnicornRepository implements UnicornRepository { private static final Logger logger = LogManager.getLogger(); - private final DynamoDbAsyncTable unicornDynamoDbAsyncTable; + private final DynamoDbTable unicornDynamoDbTable; - public DynamoDBUnicornRepository(DynamoDbAsyncTable unicornDynamoDbAsyncTable) { - this.unicornDynamoDbAsyncTable = unicornDynamoDbAsyncTable; + public DynamoDBUnicornRepository(DynamoDbTable unicornDynamoDbTable) { + this.unicornDynamoDbTable = unicornDynamoDbTable; } @Override public Unicorn save(Unicorn unicorn) { logger.info("Saving unicorn with id {} to DynamoDB", unicorn.getId()); try { - unicornDynamoDbAsyncTable.putItem(unicorn).get(); + unicornDynamoDbTable.putItem(unicorn); logger.info("Unicorn with id {} saved successfully", unicorn.getId()); return unicorn; - } catch (ExecutionException e) { - logger.error("Unicorn with id {} could not be saved to DynamoDB", unicorn.getId(), e); - throw new ResourceSaveException(e.getMessage()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (DynamoDbException e) { logger.error("Unicorn with id {} could not be saved to DynamoDB", unicorn.getId(), e); throw new ResourceSaveException(e.getMessage()); } @@ -52,18 +48,14 @@ public Unicorn save(Unicorn unicorn) { @Override public Optional findById(String unicornId) { try { - Unicorn unicorn = unicornDynamoDbAsyncTable.getItem(Key.builder().partitionValue(unicornId).build()).get(); + Unicorn unicorn = unicornDynamoDbTable.getItem(Key.builder().partitionValue(unicornId).build()); if (unicorn == null) { logger.info("Unicorn with id {} not found in DynamoDB", unicornId); return Optional.empty(); } logger.info("Unicorn with id {} found in DynamoDB", unicornId); return Optional.of(unicorn); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.error("Unicorn with id {} could not be retrieved from DynamoDB", unicornId, e); - throw new ResourceRetrievalException(e.getMessage()); - } catch (ExecutionException e) { + } catch (DynamoDbException e) { logger.error("Unicorn with id {} could not be retrieved from DynamoDB", unicornId, e); throw new ResourceRetrievalException(e.getMessage()); } @@ -72,13 +64,9 @@ public Optional findById(String unicornId) { @Override public void deleteById(String unicornId) { try { - unicornDynamoDbAsyncTable.deleteItem(Key.builder().partitionValue(unicornId).build()).get(); + unicornDynamoDbTable.deleteItem(Key.builder().partitionValue(unicornId).build()); logger.info("Unicorn with id {} deleted successfully", unicornId); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.error("Unicorn with id {} could not be deleted from DynamoDB", unicornId, e); - throw new ResourceDeletionException(e.getMessage()); - } catch (ExecutionException e) { + } catch (DynamoDbException e) { logger.error("Unicorn with id {} could not be deleted from DynamoDB", unicornId, e); throw new ResourceDeletionException(e.getMessage()); } @@ -91,18 +79,14 @@ public Unicorn update(Unicorn unicorn) { .conditionExpression(Expression.builder().expression("attribute_exists(id)").build()) .build(); try { - unicornDynamoDbAsyncTable.updateItem(updateItemEnhancedRequest).get(); + unicornDynamoDbTable.updateItem(updateItemEnhancedRequest); logger.info("Unicorn with id {} updated successfully", unicorn.getId()); return unicorn; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (ConditionalCheckFailedException e) { logger.error("Unicorn with id {} could not be updated in DynamoDB", unicorn.getId(), e); - throw new ResourceUpdateException(e.getMessage()); - } catch (ExecutionException e) { + throw new ResourceNotFoundException(String.format("Unicorn with id %s not found", unicorn.getId())); + } catch (DynamoDbException e) { logger.error("Unicorn with id {} could not be updated in DynamoDB", unicorn.getId(), e); - if (e.getCause() instanceof ConditionalCheckFailedException) { - throw new ResourceNotFoundException(String.format("Unicorn with id %s not found", unicorn.getId())); - } throw new ResourceUpdateException(e.getMessage()); } } diff --git a/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/StoreApplicationTest.java b/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/StoreApplicationTest.java index 793bee985..777bb7e83 100644 --- a/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/StoreApplicationTest.java +++ b/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/StoreApplicationTest.java @@ -23,13 +23,13 @@ import org.testcontainers.utility.DockerImageName; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; -import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import java.io.IOException; import java.net.URI; @@ -55,7 +55,7 @@ class StoreApplicationTest { private final HttpClient httpClient = HttpClient.newHttpClient(); @Autowired - private DynamoDbAsyncTable dynamoDbAsyncTable; + private DynamoDbTable dynamoDbTable; @LocalServerPort private Integer serverPort; @@ -65,19 +65,19 @@ class StoreApplicationTest { @BeforeEach void setup() { serverUrl = String.format("http://localhost:%d", serverPort); - dynamoDbAsyncTable.createTable().join(); + dynamoDbTable.createTable(); Unicorn unicorn = new Unicorn(); unicorn.setId("123"); unicorn.setName("Something"); unicorn.setAge("Older"); unicorn.setSize("Very big"); unicorn.setType("Animal"); - dynamoDbAsyncTable.putItem(unicorn).join(); + dynamoDbTable.putItem(unicorn); } @AfterEach void teardown() { - dynamoDbAsyncTable.deleteTable().join(); + dynamoDbTable.deleteTable(); } @Test @@ -146,7 +146,7 @@ void testCreateUnicornCreated() throws IOException, InterruptedException, JSONEx "type": "Test Type" } """, savedUnicorn.getId()), response.body(), JSONCompareMode.STRICT); - assertNotNull(dynamoDbAsyncTable.getItem(Key.builder().partitionValue(savedUnicorn.getId()).build())); + assertNotNull(dynamoDbTable.getItem(Key.builder().partitionValue(savedUnicorn.getId()).build())); } @Test @@ -175,7 +175,7 @@ void testPutUnicornSuccess() throws IOException, InterruptedException, JSONExcep "type": "Test Type" } """, response.body(), JSONCompareMode.STRICT); - Unicorn updatedUnicorn = dynamoDbAsyncTable.getItem(Key.builder().partitionValue("123").build()).join(); + Unicorn updatedUnicorn = dynamoDbTable.getItem(Key.builder().partitionValue("123").build()); assertNotNull(updatedUnicorn); assertEquals("Test Name", updatedUnicorn.getName()); assertEquals("Test Age", updatedUnicorn.getAge()); @@ -200,7 +200,7 @@ void testPutUnicornNotFound() throws IOException, InterruptedException { .build(); HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); assertEquals(404, response.statusCode()); - Unicorn updatedUnicorn = dynamoDbAsyncTable.getItem(Key.builder().partitionValue("123").build()).join(); + Unicorn updatedUnicorn = dynamoDbTable.getItem(Key.builder().partitionValue("123").build()); assertNotNull(updatedUnicorn); assertEquals("Something", updatedUnicorn.getName()); assertEquals("Older", updatedUnicorn.getAge()); @@ -211,14 +211,14 @@ void testPutUnicornNotFound() throws IOException, InterruptedException { @Test @DisplayName("DELETE /unicorns/{unicornId} - 200 Success") void testDeleteUnicornSuccess() throws IOException, InterruptedException { - assertNotNull(dynamoDbAsyncTable.getItem(Key.builder().partitionValue("123").build()).join()); + assertNotNull(dynamoDbTable.getItem(Key.builder().partitionValue("123").build())); HttpRequest request = HttpRequest.newBuilder() .DELETE() .uri(URI.create(serverUrl.concat("/unicorns/123"))) .build(); HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); assertEquals(200, response.statusCode()); - assertNull(dynamoDbAsyncTable.getItem(Key.builder().partitionValue("123").build()).join()); + assertNull(dynamoDbTable.getItem(Key.builder().partitionValue("123").build())); } @TestConfiguration @@ -226,18 +226,18 @@ static class StoreApplicationTestConfig { @Bean @Primary - public DynamoDbAsyncClient dynamoDbAsyncClient() { - return DynamoDbAsyncClient.builder() + public DynamoDbClient dynamoDbClient() { + return DynamoDbClient.builder() .region(Region.EU_WEST_1) .endpointOverride(URI.create(String.format("http://%s:%d", DYNAMODB_CONTAINER.getHost(), DYNAMODB_CONTAINER.getFirstMappedPort()))) - .httpClient(AwsCrtAsyncHttpClient.create()) + .httpClient(AwsCrtHttpClient.create()) .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("fakeMyKeyId", "fakeSecretAccessKey"))) .build(); } @Bean @Primary - public DynamoDbAsyncTable unicornDynamoDbAsyncTable(DynamoDbEnhancedAsyncClient dynamoDbEnhancedClient) { + public DynamoDbTable unicornDynamoDbTable(DynamoDbEnhancedClient dynamoDbEnhancedClient) { return dynamoDbEnhancedClient.table("Unicorn-Local", TableSchema.fromClass(Unicorn.class)); } } diff --git a/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/data/DynamoDBUnicornRepositoryTest.java b/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/data/DynamoDBUnicornRepositoryTest.java index 6d40713a5..19f2f5309 100644 --- a/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/data/DynamoDBUnicornRepositoryTest.java +++ b/apigw-lambda-snapstart/UnicornFunction/src/test/java/com/unicorn/store/data/DynamoDBUnicornRepositoryTest.java @@ -12,13 +12,13 @@ import org.testcontainers.utility.DockerImageName; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; -import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import java.net.URI; import java.util.Optional; @@ -42,34 +42,34 @@ class DynamoDBUnicornRepositoryTest { @BeforeAll static void setupAllTests() { - unicornAsyncTable().createTable().join(); + unicornTable().createTable(); } - private static DynamoDbAsyncTable unicornAsyncTable() { - DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient.builder() + private static DynamoDbTable unicornTable() { + DynamoDbClient dynamoDbClient = DynamoDbClient.builder() .region(Region.EU_WEST_1) .endpointOverride(URI.create(String.format("http://%s:%d", DYNAMODB_CONTAINER.getHost(), DYNAMODB_CONTAINER.getFirstMappedPort()))) - .httpClient(AwsCrtAsyncHttpClient.create()) + .httpClient(AwsCrtHttpClient.create()) .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("fakeMyKeyId", "fakeSecretAccessKey"))) .build(); - DynamoDbEnhancedAsyncClient dynamoDbEnhancedAsyncClient = DynamoDbEnhancedAsyncClient.builder() - .dynamoDbClient(dynamoDbAsyncClient) + DynamoDbEnhancedClient dynamoDbEnhancedClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(dynamoDbClient) .build(); - return dynamoDbEnhancedAsyncClient.table("Unicorn-Local", TableSchema.fromClass(Unicorn.class)); + return dynamoDbEnhancedClient.table("Unicorn-Local", TableSchema.fromClass(Unicorn.class)); } @BeforeEach void setup() { - this.dynamoDBUnicornRepository = new DynamoDBUnicornRepository(unicornAsyncTable()); + this.dynamoDBUnicornRepository = new DynamoDBUnicornRepository(unicornTable()); } @Test @DisplayName("Unicorn is saved to DynamoDB") void testSave() { Unicorn unicornToSave = createTestUnicorn(); - assertNull(unicornAsyncTable().getItem(Key.builder().partitionValue(unicornToSave.getId()).build()).join()); + assertNull(unicornTable().getItem(Key.builder().partitionValue(unicornToSave.getId()).build())); Unicorn savedUnicorn = dynamoDBUnicornRepository.save(unicornToSave); - assertNotNull(unicornAsyncTable().getItem(Key.builder().partitionValue(unicornToSave.getId()).build()).join()); + assertNotNull(unicornTable().getItem(Key.builder().partitionValue(unicornToSave.getId()).build())); assertEquals(unicornToSave.getId(), savedUnicorn.getId()); assertEquals(unicornToSave.getName(), savedUnicorn.getName()); assertEquals(unicornToSave.getAge(), savedUnicorn.getAge()); @@ -81,7 +81,7 @@ void testSave() { @DisplayName("Unicorn is found in DynamoDB") void testFindByIdFound() { Unicorn existingUnicorn = createTestUnicorn(); - unicornAsyncTable().putItem(existingUnicorn).join(); + unicornTable().putItem(existingUnicorn); Optional unicornFound = dynamoDBUnicornRepository.findById(existingUnicorn.getId()); assertTrue(unicornFound.isPresent()); @@ -104,26 +104,26 @@ void testFindByIdNotFound() { @DisplayName("Unicorn is not deleted in DynamoDB") void testDelete() { Unicorn existingUnicorn = createTestUnicorn(); - unicornAsyncTable().putItem(existingUnicorn).join(); + unicornTable().putItem(existingUnicorn); - assertNotNull(unicornAsyncTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()).join()); + assertNotNull(unicornTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build())); dynamoDBUnicornRepository.deleteById(existingUnicorn.getId()); - assertNull(unicornAsyncTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()).join()); + assertNull(unicornTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build())); } @Test @DisplayName("Unicorn is updated if found in DynamoDB") void testUpdateFound() { Unicorn existingUnicorn = createTestUnicorn(); - unicornAsyncTable().putItem(existingUnicorn).join(); + unicornTable().putItem(existingUnicorn); - Unicorn fromDynamoBeforeUpdate = unicornAsyncTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()).join(); + Unicorn fromDynamoBeforeUpdate = unicornTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()); assertEquals("Something", fromDynamoBeforeUpdate.getName()); existingUnicorn.setName("Changed Name"); dynamoDBUnicornRepository.update(existingUnicorn); - Unicorn fromDynamoAfterUpdate = unicornAsyncTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()).join(); + Unicorn fromDynamoAfterUpdate = unicornTable().getItem(Key.builder().partitionValue(existingUnicorn.getId()).build()); assertEquals("Changed Name", fromDynamoAfterUpdate.getName()); } @@ -131,7 +131,7 @@ void testUpdateFound() { @DisplayName("ResourceNotFoundException if Unicorn not found in DynamoDB during Update") void testUpdateNotFound() { Unicorn unicorn = createTestUnicorn(); - assertNull(unicornAsyncTable().getItem(Key.builder().partitionValue(unicorn.getId()).build()).join()); + assertNull(unicornTable().getItem(Key.builder().partitionValue(unicorn.getId()).build())); assertThrows(ResourceNotFoundException.class, () -> dynamoDBUnicornRepository.update(unicorn)); }