AWS code-library documentation change
Summary
Added comprehensive code examples and documentation for DynamoDB Multi-Region Strong Consistency (MRSC) implementation including table creation, configuration verification, consistency testing, and cleanup
Security assessment
The changes document Multi-Region Strong Consistency features which improve data integrity across regions but do not address a specific security vulnerability. While MRSC enhances consistency guarantees (important for data accuracy), this is a feature documentation update rather than a security fix. The changes demonstrate proper implementation of strong consistency controls which could help prevent stale data issues.
Diff
diff --git a/code-library/latest/ug/java_2_dynamodb_code_examples.md b/code-library/latest/ug/java_2_dynamodb_code_examples.md index 31e32f583..591c7aab0 100644 --- a//code-library/latest/ug/java_2_dynamodb_code_examples.md +++ b//code-library/latest/ug/java_2_dynamodb_code_examples.md @@ -3818,0 +3819,687 @@ The following code example shows how to create an item with TTL. +The following code example shows how to create and manage DynamoDB global tables with Multi-Region Strong Consistency (MRSC). + + * Create a table with Multi-Region Strong Consistency. + + * Verify MRSC configuration and replica status. + + * Test strong consistency across Regions with immediate reads. + + * Perform conditional writes with MRSC guarantees. + + * Clean up MRSC global table resources. + + + + +**SDK for Java 2.x** + + +Create a regional table ready for MRSC conversion using AWS SDK for Java 2.x. + + + public static CreateTableResponse createRegionalTable(final DynamoDbClient dynamoDbClient, final String tableName) { + + if (dynamoDbClient == null) { + throw new IllegalArgumentException("DynamoDB client cannot be null"); + } + if (tableName == null || tableName.trim().isEmpty()) { + throw new IllegalArgumentException("Table name cannot be null or empty"); + } + + try { + LOGGER.info("Creating regional table: " + tableName + " (must be empty for MRSC)"); + + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(tableName) + .attributeDefinitions( + AttributeDefinition.builder() + .attributeName("Artist") + .attributeType(ScalarAttributeType.S) + .build(), + AttributeDefinition.builder() + .attributeName("SongTitle") + .attributeType(ScalarAttributeType.S) + .build()) + .keySchema( + KeySchemaElement.builder() + .attributeName("Artist") + .keyType(KeyType.HASH) + .build(), + KeySchemaElement.builder() + .attributeName("SongTitle") + .keyType(KeyType.RANGE) + .build()) + .billingMode(BillingMode.PAY_PER_REQUEST) + .build(); + + CreateTableResponse response = dynamoDbClient.createTable(createTableRequest); + LOGGER.info("Regional table creation initiated. Status: " + + response.tableDescription().tableStatus()); + + return response; + + } catch (DynamoDbException e) { + LOGGER.severe("Failed to create regional table: " + tableName + " - " + e.getMessage()); + throw DynamoDbException.builder() + .message("Failed to create regional table: " + tableName) + .cause(e) + .build(); + } + } + + + +Convert a regional table to MRSC with replicas and witness using AWS SDK for Java 2.x. + + + public static UpdateTableResponse convertToMRSCWithWitness( + final DynamoDbClient dynamoDbClient, + final String tableName, + final Region replicaRegion, + final Region witnessRegion) { + + if (dynamoDbClient == null) { + throw new IllegalArgumentException("DynamoDB client cannot be null"); + } + if (tableName == null || tableName.trim().isEmpty()) { + throw new IllegalArgumentException("Table name cannot be null or empty"); + } + if (replicaRegion == null) { + throw new IllegalArgumentException("Replica region cannot be null"); + } + if (witnessRegion == null) { + throw new IllegalArgumentException("Witness region cannot be null"); + } + + try { + LOGGER.info("Converting table to MRSC with replica in " + replicaRegion.id() + " and witness in " + + witnessRegion.id()); + + // Create replica update using ReplicationGroupUpdate + ReplicationGroupUpdate replicaUpdate = ReplicationGroupUpdate.builder() + .create(CreateReplicationGroupMemberAction.builder() + .regionName(replicaRegion.id()) + .build()) + .build(); + + // Create witness update + GlobalTableWitnessGroupUpdate witnessUpdate = GlobalTableWitnessGroupUpdate.builder() + .create(CreateGlobalTableWitnessGroupMemberAction.builder() + .regionName(witnessRegion.id()) + .build()) + .build(); + + UpdateTableRequest updateTableRequest = UpdateTableRequest.builder() + .tableName(tableName) + .replicaUpdates(List.of(replicaUpdate)) + .globalTableWitnessUpdates(List.of(witnessUpdate)) + .multiRegionConsistency(MultiRegionConsistency.STRONG) + .build(); + + UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest); + LOGGER.info("MRSC conversion initiated. Status: " + + response.tableDescription().tableStatus()); + LOGGER.info("UpdateTableResponse full object: " + response); + return response; + + } catch (DynamoDbException e) { + LOGGER.severe("Failed to convert table to MRSC: " + tableName + " - " + e.getMessage()); + throw DynamoDbException.builder() + .message("Failed to convert table to MRSC: " + tableName) + .cause(e) + .build(); + } + } + + + +Describe an MRSC global table configuration using AWS SDK for Java 2.x. + + + public static DescribeTableResponse describeMRSCTable(final DynamoDbClient dynamoDbClient, final String tableName) { + + if (dynamoDbClient == null) { + throw new IllegalArgumentException("DynamoDB client cannot be null"); + } + if (tableName == null || tableName.trim().isEmpty()) { + throw new IllegalArgumentException("Table name cannot be null or empty"); + } + + try { + LOGGER.info("Describing MRSC global table: " + tableName); + + DescribeTableRequest request = + DescribeTableRequest.builder().tableName(tableName).build(); + + DescribeTableResponse response = dynamoDbClient.describeTable(request); + + LOGGER.info("Table status: " + response.table().tableStatus()); + LOGGER.info("Multi-region consistency: " + response.table().multiRegionConsistency()); + + if (response.table().replicas() != null + && !response.table().replicas().isEmpty()) { + LOGGER.info("Number of replicas: " + response.table().replicas().size()); + response.table() + .replicas() + .forEach(replica -> LOGGER.info( + "Replica region: " + replica.regionName() + ", Status: " + replica.replicaStatus())); + } + + if (response.table().globalTableWitnesses() != null + && !response.table().globalTableWitnesses().isEmpty()) { + LOGGER.info("Number of witnesses: " + + response.table().globalTableWitnesses().size()); + response.table() + .globalTableWitnesses() + .forEach(witness -> LOGGER.info( + "Witness region: " + witness.regionName() + ", Status: " + witness.witnessStatus())); + } + + return response; + + } catch (ResourceNotFoundException e) { + LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage()); + throw DynamoDbException.builder() + .message("Table not found: " + tableName) + .cause(e) + .build(); + } catch (DynamoDbException e) { + LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage()); + throw DynamoDbException.builder() + .message("Failed to describe table: " + tableName) + .cause(e) + .build(); + } + }