Skip to content

Commit

Permalink
Refactoring from async CRT client to the sync one.
Browse files Browse the repository at this point in the history
  • Loading branch information
msailes committed Dec 17, 2023
1 parent 7e12dce commit dde1682
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 82 deletions.
2 changes: 1 addition & 1 deletion apigw-lambda-snapstart/UnicornFunction/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<powertools.version>1.16.0</powertools.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<aws.sdk.version>2.20.99</aws.sdk.version>
<aws.sdk.version>2.22.0</aws.sdk.version>
</properties>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Unicorn> unicornDynamoDbAsyncTable(DynamoDbEnhancedAsyncClient dynamoDbEnhancedClient) {
public DynamoDbTable<Unicorn> unicornDynamoDbTable(DynamoDbEnhancedClient dynamoDbEnhancedClient) {
return dynamoDbEnhancedClient.table(System.getenv("UNICORN_TABLE_NAME"), TableSchema.fromClass(Unicorn.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Unicorn> unicornDynamoDbAsyncTable;
private final DynamoDbTable<Unicorn> unicornDynamoDbTable;

public DynamoDBUnicornRepository(DynamoDbAsyncTable<Unicorn> unicornDynamoDbAsyncTable) {
this.unicornDynamoDbAsyncTable = unicornDynamoDbAsyncTable;
public DynamoDBUnicornRepository(DynamoDbTable<Unicorn> 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());
}
Expand All @@ -52,18 +48,14 @@ public Unicorn save(Unicorn unicorn) {
@Override
public Optional<Unicorn> 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());
}
Expand All @@ -72,13 +64,9 @@ public Optional<Unicorn> 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());
}
Expand All @@ -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());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -55,7 +55,7 @@ class StoreApplicationTest {
private final HttpClient httpClient = HttpClient.newHttpClient();

@Autowired
private DynamoDbAsyncTable<Unicorn> dynamoDbAsyncTable;
private DynamoDbTable<Unicorn> dynamoDbTable;

@LocalServerPort
private Integer serverPort;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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());
Expand All @@ -200,7 +200,7 @@ void testPutUnicornNotFound() throws IOException, InterruptedException {
.build();
HttpResponse<String> 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());
Expand All @@ -211,33 +211,33 @@ 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<String> 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
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<Unicorn> unicornDynamoDbAsyncTable(DynamoDbEnhancedAsyncClient dynamoDbEnhancedClient) {
public DynamoDbTable<Unicorn> unicornDynamoDbTable(DynamoDbEnhancedClient dynamoDbEnhancedClient) {
return dynamoDbEnhancedClient.table("Unicorn-Local", TableSchema.fromClass(Unicorn.class));
}
}
Expand Down
Loading

0 comments on commit dde1682

Please sign in to comment.