From 4a53de0a48e559218a2ba9703c7181a50ce860a8 Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:14:41 -0700 Subject: [PATCH 1/4] fix: use UUIDs and cleanup in beacon styles example to avoid stale item collisions - Generate unique work_id UUIDs per run instead of hardcoded "1" and "2" - Add temporary work_id IN filter to scans (to be removed after table cleanup) - Delete items in finally/cleanup block after assertions - Dynamic compound beacon value using UUID instead of hardcoded "I-1.T-small" - Applied to both Rust and Java examples --- .../beacon_styles_searchable_encryption.rs | 127 +++++--- ...aconStylesSearchableEncryptionExample.java | 275 ++++++++++-------- 2 files changed, 234 insertions(+), 168 deletions(-) diff --git a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs index a287c9ecbc..e838630aac 100644 --- a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs +++ b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs @@ -201,9 +201,13 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)])) .build()?; + // Generate unique work_id values for this run to avoid collisions with stale items + let work_id1 = uuid::Uuid::new_v4().to_string(); + let work_id2 = uuid::Uuid::new_v4().to_string(); + // 8. Create item one, specifically with "dessert != fruit", and "fruit in basket". let item1 = HashMap::from([ - ("work_id".to_string(), AttributeValue::S("1".to_string())), + ("work_id".to_string(), AttributeValue::S(work_id1.clone())), ( "inspection_date".to_string(), AttributeValue::S("2023-06-13".to_string()), @@ -234,7 +238,7 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: // 9. Create item two, specifically with "dessert == fruit", and "fruit not in basket". let item2 = HashMap::from([ - ("work_id".to_string(), AttributeValue::S("2".to_string())), + ("work_id".to_string(), AttributeValue::S(work_id2.clone())), ( "inspection_date".to_string(), AttributeValue::S("2023-06-13".to_string()), @@ -285,43 +289,79 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: .send() .await?; + // Run all scan tests, then clean up items regardless of success or failure + let result = run_scan_tests(&ddb, ddb_table_name, &item1, &item2, &work_id1, &work_id2).await; + + // Clean up: delete both items + let plain_ddb = aws_sdk_dynamodb::Client::new(&sdk_config); + let _ = plain_ddb + .delete_item() + .table_name(ddb_table_name) + .key("work_id", AttributeValue::S(work_id1)) + .key("inspection_date", AttributeValue::S("2023-06-13".to_string())) + .send() + .await; + let _ = plain_ddb + .delete_item() + .table_name(ddb_table_name) + .key("work_id", AttributeValue::S(work_id2)) + .key("inspection_date", AttributeValue::S("2023-06-13".to_string())) + .send() + .await; + + result?; + println!("beacon_styles_searchable_encryption successful."); + Ok(()) +} + +async fn run_scan_tests( + ddb: &aws_sdk_dynamodb::Client, + ddb_table_name: &str, + item1: &HashMap, + item2: &HashMap, + work_id1: &str, + work_id2: &str, +) -> Result<(), crate::BoxError> { + // TODO: Remove work_id IN filter once stale items are cleaned from the table. + // These filters ensure scans only match items created by this test run. + let wid_filter = "work_id IN (:wid1, :wid2)"; + let wid_values = HashMap::from([ + (":wid1".to_string(), AttributeValue::S(work_id1.to_string())), + (":wid2".to_string(), AttributeValue::S(work_id2.to_string())), + ]); + // 12. Test the first type of Set operation : // Select records where the basket attribute holds a particular value - let expression_attribute_values = HashMap::from([( - ":value".to_string(), - AttributeValue::S("banana".to_string()), - )]); + let mut expr_vals = wid_values.clone(); + expr_vals.insert(":value".to_string(), AttributeValue::S("banana".to_string())); let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("contains(basket, :value)") - .set_expression_attribute_values(Some(expression_attribute_values.clone())) + .filter_expression(format!("{wid_filter} AND contains(basket, :value)")) + .set_expression_attribute_values(Some(expr_vals)) .send() .await?; let attribute_values = scan_response.items.unwrap(); // Validate only 1 item was returned: item1 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item1["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item1["work_id"]); // 13. Test the second type of Set operation : // Select records where the basket attribute holds the fruit attribute let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("contains(basket, fruit)") + .filter_expression(format!("{wid_filter} AND contains(basket, fruit)")) + .set_expression_attribute_values(Some(wid_values.clone())) .send() .await?; let attribute_values = scan_response.items.unwrap(); // Validate only 1 item was returned: item1 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item1["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item1["work_id"]); // 14. Test the third type of Set operation : // Select records where the fruit attribute exists in a particular set @@ -330,80 +370,73 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: "orange".to_string(), "grape".to_string(), ]; - let expression_attribute_values = - HashMap::from([(":value".to_string(), AttributeValue::Ss(basket3))]); + let mut expr_vals = wid_values.clone(); + expr_vals.insert(":value".to_string(), AttributeValue::Ss(basket3)); let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("contains(:value, fruit)") - .set_expression_attribute_values(Some(expression_attribute_values.clone())) + .filter_expression(format!("{wid_filter} AND contains(:value, fruit)")) + .set_expression_attribute_values(Some(expr_vals)) .send() .await?; let attribute_values = scan_response.items.unwrap(); - // Validate only 1 item was returned: item1 + // Validate only 1 item was returned: item2 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item2["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item2["work_id"]); // 15. Test a Shared search. Select records where the dessert attribute matches the fruit attribute let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("dessert = fruit") + .filter_expression(format!("{wid_filter} AND dessert = fruit")) + .set_expression_attribute_values(Some(wid_values.clone())) .send() .await?; let attribute_values = scan_response.items.unwrap(); - // Validate only 1 item was returned: item1 + // Validate only 1 item was returned: item2 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item2["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item2["work_id"]); - // 15. Test the AsSet attribute 'veggies' : + // 16. Test the AsSet attribute 'veggies' : // Select records where the veggies attribute holds a particular value - let expression_attribute_values = - HashMap::from([(":value".to_string(), AttributeValue::S("peas".to_string()))]); + let mut expr_vals = wid_values.clone(); + expr_vals.insert(":value".to_string(), AttributeValue::S("peas".to_string())); let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("contains(veggies, :value)") - .set_expression_attribute_values(Some(expression_attribute_values.clone())) + .filter_expression(format!("{wid_filter} AND contains(veggies, :value)")) + .set_expression_attribute_values(Some(expr_vals)) .send() .await?; let attribute_values = scan_response.items.unwrap(); - // Validate only 1 item was returned: item1 + // Validate only 1 item was returned: item2 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item2["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item2["work_id"]); - // 16. Test the compound beacon 'work_unit' : - let expression_attribute_values = HashMap::from([( + // 17. Test the compound beacon 'work_unit' : + let mut expr_vals = wid_values.clone(); + expr_vals.insert( ":value".to_string(), - AttributeValue::S("I-1.T-small".to_string()), - )]); + AttributeValue::S(format!("I-{}.T-small", item1["work_id"].as_s().unwrap())), + ); let scan_response = ddb .scan() .table_name(ddb_table_name) - .filter_expression("work_unit = :value") - .set_expression_attribute_values(Some(expression_attribute_values.clone())) + .filter_expression(format!("{wid_filter} AND work_unit = :value")) + .set_expression_attribute_values(Some(expr_vals)) .send() .await?; let attribute_values = scan_response.items.unwrap(); // Validate only 1 item was returned: item1 assert_eq!(attribute_values.len(), 1); - let returned_item = &attribute_values[0]; - // Validate the item has the expected attributes - assert_eq!(returned_item["work_id"], item1["work_id"]); + assert_eq!(attribute_values[0]["work_id"], item1["work_id"]); - println!("beacon_styles_searchable_encryption successful."); Ok(()) } diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java index 65714e0eba..e65ae4d9a4 100644 --- a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java +++ b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java @@ -4,10 +4,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.swing.text.html.Option; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; import software.amazon.awssdk.services.dynamodb.model.ScanRequest; @@ -274,9 +276,13 @@ public static void PutItemQueryItemWithBeaconStyles( .tableEncryptionConfigs(tableConfigs) .build(); + // Generate unique work_id values for this run to avoid collisions with stale items + final String workId1 = UUID.randomUUID().toString(); + final String workId2 = UUID.randomUUID().toString(); + // 8. Create item one, specifically with "dessert != fruit", and "fruit in basket". final HashMap item1 = new HashMap<>(); - item1.put("work_id", AttributeValue.builder().s("1").build()); + item1.put("work_id", AttributeValue.builder().s(workId1).build()); item1.put( "inspection_date", AttributeValue.builder().s("2023-06-13").build() @@ -297,7 +303,7 @@ public static void PutItemQueryItemWithBeaconStyles( // 9. Create item two, specifically with "dessert == fruit", and "fruit not in basket". final HashMap item2 = new HashMap<>(); - item2.put("work_id", AttributeValue.builder().s("2").build()); + item2.put("work_id", AttributeValue.builder().s(workId2).build()); item2.put( "inspection_date", AttributeValue.builder().s("2023-06-13").build() @@ -349,135 +355,162 @@ public static void PutItemQueryItemWithBeaconStyles( // Validate object put successfully assert 200 == putResponse.sdkHttpResponse().statusCode(); - // 13. Test the first type of Set operation : - // Select records where the basket attribute holds a particular value - Map expressionAttributeValues = new HashMap<>(); - expressionAttributeValues.put( - ":value", - AttributeValue.builder().s("banana").build() - ); - - ScanRequest scanRequest = ScanRequest - .builder() - .tableName(ddbTableName) - .filterExpression("contains(basket, :value)") - .expressionAttributeValues(expressionAttributeValues) - .build(); - - ScanResponse scanResponse = ddb.scan(scanRequest); - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); - - // Validate only 1 item was returned: item1 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item1); - - // 14. Test the second type of Set operation : - // Select records where the basket attribute holds the fruit attribute - scanRequest = - ScanRequest - .builder() - .tableName(ddbTableName) - .filterExpression("contains(basket, fruit)") - .build(); - - scanResponse = ddb.scan(scanRequest); - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); - - // Validate only 1 item was returned: item1 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item1); - - // 15. Test the third type of Set operation : - // Select records where the fruit attribute exists in a particular set - ArrayList basket3 = new ArrayList(); - basket3.add("boysenberry"); - basket3.add("grape"); - basket3.add("orange"); - expressionAttributeValues.put( - ":value", - AttributeValue.builder().ss(basket3).build() - ); - - scanRequest = - ScanRequest - .builder() - .tableName(ddbTableName) - .filterExpression("contains(:value, fruit)") - .expressionAttributeValues(expressionAttributeValues) - .build(); - - scanResponse = ddb.scan(scanRequest); - - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); - - // Validate only 1 item was returned: item2 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item2); - - // Test a Shared search. Select records where the dessert attribute matches the fruit attribute - scanRequest = - ScanRequest - .builder() - .tableName(ddbTableName) - .filterExpression("dessert = fruit") - .build(); - - scanResponse = ddb.scan(scanRequest); - - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); - - // Validate only 1 item was returned: item2 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item2); - - // 16. Test the AsSet attribute 'veggies' : - // Select records where the veggies attribute holds a particular value - expressionAttributeValues.put( - ":value", - AttributeValue.builder().s("peas").build() - ); + // TODO: Remove work_id IN filter once stale items are cleaned from the table. + // These filters ensure scans only match items created by this test run. + final String widFilter = "work_id IN (:wid1, :wid2)"; + final Map widValues = new HashMap<>(); + widValues.put(":wid1", AttributeValue.builder().s(workId1).build()); + widValues.put(":wid2", AttributeValue.builder().s(workId2).build()); + + try { + // 13. Test the first type of Set operation : + // Select records where the basket attribute holds a particular value + Map expressionAttributeValues = new HashMap<>( + widValues + ); + expressionAttributeValues.put( + ":value", + AttributeValue.builder().s("banana").build() + ); - scanRequest = - ScanRequest + ScanRequest scanRequest = ScanRequest .builder() .tableName(ddbTableName) - .filterExpression("contains(veggies, :value)") + .filterExpression(widFilter + " AND contains(basket, :value)") .expressionAttributeValues(expressionAttributeValues) .build(); - scanResponse = ddb.scan(scanRequest); - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); + ScanResponse scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item1); - // Validate only 1 item was returned: item1 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item2); - - // 17. Test the compound beacon 'work_unit' : - expressionAttributeValues.put( - ":value", - AttributeValue.builder().s("I-1.T-small").build() - ); + // 14. Test the second type of Set operation : + // Select records where the basket attribute holds the fruit attribute + scanRequest = + ScanRequest + .builder() + .tableName(ddbTableName) + .filterExpression(widFilter + " AND contains(basket, fruit)") + .expressionAttributeValues(widValues) + .build(); + + scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item1); + + // 15. Test the third type of Set operation : + // Select records where the fruit attribute exists in a particular set + ArrayList basket3 = new ArrayList(); + basket3.add("boysenberry"); + basket3.add("grape"); + basket3.add("orange"); + expressionAttributeValues = new HashMap<>(widValues); + expressionAttributeValues.put( + ":value", + AttributeValue.builder().ss(basket3).build() + ); - scanRequest = - ScanRequest - .builder() - .tableName(ddbTableName) - .filterExpression("work_unit = :value") - .expressionAttributeValues(expressionAttributeValues) - .build(); + scanRequest = + ScanRequest + .builder() + .tableName(ddbTableName) + .filterExpression(widFilter + " AND contains(:value, fruit)") + .expressionAttributeValues(expressionAttributeValues) + .build(); + + scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item2); + + // Test a Shared search. Select records where the dessert attribute matches the fruit attribute + scanRequest = + ScanRequest + .builder() + .tableName(ddbTableName) + .filterExpression(widFilter + " AND dessert = fruit") + .expressionAttributeValues(widValues) + .build(); + + scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item2); + + // 16. Test the AsSet attribute 'veggies' : + // Select records where the veggies attribute holds a particular value + expressionAttributeValues = new HashMap<>(widValues); + expressionAttributeValues.put( + ":value", + AttributeValue.builder().s("peas").build() + ); - scanResponse = ddb.scan(scanRequest); - // Validate query was returned successfully - assert 200 == scanResponse.sdkHttpResponse().statusCode(); + scanRequest = + ScanRequest + .builder() + .tableName(ddbTableName) + .filterExpression(widFilter + " AND contains(veggies, :value)") + .expressionAttributeValues(expressionAttributeValues) + .build(); + + scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item2); + + // 17. Test the compound beacon 'work_unit' : + expressionAttributeValues = new HashMap<>(widValues); + expressionAttributeValues.put( + ":value", + AttributeValue.builder().s("I-" + workId1 + ".T-small").build() + ); - // Validate only 1 item was returned: item1 - assert scanResponse.items().size() == 1; - assert scanResponse.items().get(0).equals(item1); + scanRequest = + ScanRequest + .builder() + .tableName(ddbTableName) + .filterExpression(widFilter + " AND work_unit = :value") + .expressionAttributeValues(expressionAttributeValues) + .build(); + + scanResponse = ddb.scan(scanRequest); + assert 200 == scanResponse.sdkHttpResponse().statusCode(); + assert scanResponse.items().size() == 1; + assert scanResponse.items().get(0).equals(item1); + } finally { + // Clean up: delete both items using a plain DDB client + final DynamoDbClient plainDdb = DynamoDbClient.create(); + plainDdb.deleteItem( + DeleteItemRequest + .builder() + .tableName(ddbTableName) + .key( + Map.of( + "work_id", + AttributeValue.builder().s(workId1).build(), + "inspection_date", + AttributeValue.builder().s("2023-06-13").build() + ) + ) + .build() + ); + plainDdb.deleteItem( + DeleteItemRequest + .builder() + .tableName(ddbTableName) + .key( + Map.of( + "work_id", + AttributeValue.builder().s(workId2).build(), + "inspection_date", + AttributeValue.builder().s("2023-06-13").build() + ) + ) + .build() + ); + } } public static void main(final String[] args) { From 98d7d9e9138bdd2a4ada5b2bb7f580374e3c2d87 Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:45:32 -0700 Subject: [PATCH 2/4] fix: use HashMap instead of Map.of for Java 8 compatibility --- ...aconStylesSearchableEncryptionExample.java | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java index e65ae4d9a4..91c4a13c92 100644 --- a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java +++ b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java @@ -482,33 +482,23 @@ public static void PutItemQueryItemWithBeaconStyles( } finally { // Clean up: delete both items using a plain DDB client final DynamoDbClient plainDdb = DynamoDbClient.create(); + HashMap key1 = new HashMap<>(); + key1.put("work_id", AttributeValue.builder().s(workId1).build()); + key1.put( + "inspection_date", + AttributeValue.builder().s("2023-06-13").build() + ); plainDdb.deleteItem( - DeleteItemRequest - .builder() - .tableName(ddbTableName) - .key( - Map.of( - "work_id", - AttributeValue.builder().s(workId1).build(), - "inspection_date", - AttributeValue.builder().s("2023-06-13").build() - ) - ) - .build() + DeleteItemRequest.builder().tableName(ddbTableName).key(key1).build() + ); + HashMap key2 = new HashMap<>(); + key2.put("work_id", AttributeValue.builder().s(workId2).build()); + key2.put( + "inspection_date", + AttributeValue.builder().s("2023-06-13").build() ); plainDdb.deleteItem( - DeleteItemRequest - .builder() - .tableName(ddbTableName) - .key( - Map.of( - "work_id", - AttributeValue.builder().s(workId2).build(), - "inspection_date", - AttributeValue.builder().s("2023-06-13").build() - ) - ) - .build() + DeleteItemRequest.builder().tableName(ddbTableName).key(key2).build() ); } } From 6b1751127db1e178d1aa4d5182bb0b04ec477b9d Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:15:32 -0700 Subject: [PATCH 3/4] chore: remove TODO comments from filter expressions --- .../searchableencryption/beacon_styles_searchable_encryption.rs | 1 - .../BeaconStylesSearchableEncryptionExample.java | 1 - 2 files changed, 2 deletions(-) diff --git a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs index e838630aac..247f7309d9 100644 --- a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs +++ b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs @@ -322,7 +322,6 @@ async fn run_scan_tests( work_id1: &str, work_id2: &str, ) -> Result<(), crate::BoxError> { - // TODO: Remove work_id IN filter once stale items are cleaned from the table. // These filters ensure scans only match items created by this test run. let wid_filter = "work_id IN (:wid1, :wid2)"; let wid_values = HashMap::from([ diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java index 91c4a13c92..c6a39493e2 100644 --- a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java +++ b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java @@ -355,7 +355,6 @@ public static void PutItemQueryItemWithBeaconStyles( // Validate object put successfully assert 200 == putResponse.sdkHttpResponse().statusCode(); - // TODO: Remove work_id IN filter once stale items are cleaned from the table. // These filters ensure scans only match items created by this test run. final String widFilter = "work_id IN (:wid1, :wid2)"; final Map widValues = new HashMap<>(); From 79601537e70407106e277860f0aa74b9c581a39b Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Fri, 13 Mar 2026 09:07:43 -0700 Subject: [PATCH 4/4] fix: remove unused import, extract inspection_date constant, and guard cleanup from masking test failures --- .../beacon_styles_searchable_encryption.rs | 10 ++-- ...aconStylesSearchableEncryptionExample.java | 48 ++++++++++--------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs index 247f7309d9..7400483dbd 100644 --- a/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs +++ b/DynamoDbEncryption/runtimes/rust/examples/searchableencryption/beacon_styles_searchable_encryption.rs @@ -23,6 +23,8 @@ use aws_db_esdk::DynamoDbTablesEncryptionConfig; use aws_sdk_dynamodb::types::AttributeValue; use std::collections::HashMap; +const INSPECTION_DATE: &str = "2023-06-13"; + /* This example demonstrates how to use Beacons Styles on Standard Beacons on encrypted attributes, put an item with the beacon, and query against that beacon. @@ -210,7 +212,7 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: ("work_id".to_string(), AttributeValue::S(work_id1.clone())), ( "inspection_date".to_string(), - AttributeValue::S("2023-06-13".to_string()), + AttributeValue::S(INSPECTION_DATE.to_string()), ), ("dessert".to_string(), AttributeValue::S("cake".to_string())), ("fruit".to_string(), AttributeValue::S("banana".to_string())), @@ -241,7 +243,7 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: ("work_id".to_string(), AttributeValue::S(work_id2.clone())), ( "inspection_date".to_string(), - AttributeValue::S("2023-06-13".to_string()), + AttributeValue::S(INSPECTION_DATE.to_string()), ), ( "dessert".to_string(), @@ -298,14 +300,14 @@ pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate: .delete_item() .table_name(ddb_table_name) .key("work_id", AttributeValue::S(work_id1)) - .key("inspection_date", AttributeValue::S("2023-06-13".to_string())) + .key("inspection_date", AttributeValue::S(INSPECTION_DATE.to_string())) .send() .await; let _ = plain_ddb .delete_item() .table_name(ddb_table_name) .key("work_id", AttributeValue::S(work_id2)) - .key("inspection_date", AttributeValue::S("2023-06-13".to_string())) + .key("inspection_date", AttributeValue::S(INSPECTION_DATE.to_string())) .send() .await; diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java index c6a39493e2..3c5a9e34c2 100644 --- a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java +++ b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/BeaconStylesSearchableEncryptionExample.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.swing.text.html.Option; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -75,6 +74,8 @@ public class BeaconStylesSearchableEncryptionExample { + private static final String INSPECTION_DATE = "2023-06-13"; + public static void PutItemQueryItemWithBeaconStyles( String ddbTableName, String branchKeyId, @@ -285,7 +286,7 @@ public static void PutItemQueryItemWithBeaconStyles( item1.put("work_id", AttributeValue.builder().s(workId1).build()); item1.put( "inspection_date", - AttributeValue.builder().s("2023-06-13").build() + AttributeValue.builder().s(INSPECTION_DATE).build() ); item1.put("dessert", AttributeValue.builder().s("cake").build()); item1.put("fruit", AttributeValue.builder().s("banana").build()); @@ -306,7 +307,7 @@ public static void PutItemQueryItemWithBeaconStyles( item2.put("work_id", AttributeValue.builder().s(workId2).build()); item2.put( "inspection_date", - AttributeValue.builder().s("2023-06-13").build() + AttributeValue.builder().s(INSPECTION_DATE).build() ); item2.put("fruit", AttributeValue.builder().s("orange").build()); item2.put("dessert", AttributeValue.builder().s("orange").build()); @@ -480,25 +481,28 @@ public static void PutItemQueryItemWithBeaconStyles( assert scanResponse.items().get(0).equals(item1); } finally { // Clean up: delete both items using a plain DDB client - final DynamoDbClient plainDdb = DynamoDbClient.create(); - HashMap key1 = new HashMap<>(); - key1.put("work_id", AttributeValue.builder().s(workId1).build()); - key1.put( - "inspection_date", - AttributeValue.builder().s("2023-06-13").build() - ); - plainDdb.deleteItem( - DeleteItemRequest.builder().tableName(ddbTableName).key(key1).build() - ); - HashMap key2 = new HashMap<>(); - key2.put("work_id", AttributeValue.builder().s(workId2).build()); - key2.put( - "inspection_date", - AttributeValue.builder().s("2023-06-13").build() - ); - plainDdb.deleteItem( - DeleteItemRequest.builder().tableName(ddbTableName).key(key2).build() - ); + try (DynamoDbClient plainDdb = DynamoDbClient.create()) { + HashMap key1 = new HashMap<>(); + key1.put("work_id", AttributeValue.builder().s(workId1).build()); + key1.put( + "inspection_date", + AttributeValue.builder().s(INSPECTION_DATE).build() + ); + plainDdb.deleteItem( + DeleteItemRequest.builder().tableName(ddbTableName).key(key1).build() + ); + HashMap key2 = new HashMap<>(); + key2.put("work_id", AttributeValue.builder().s(workId2).build()); + key2.put( + "inspection_date", + AttributeValue.builder().s(INSPECTION_DATE).build() + ); + plainDdb.deleteItem( + DeleteItemRequest.builder().tableName(ddbTableName).key(key2).build() + ); + } catch (Exception e) { + System.err.println("Cleanup failed: " + e.getMessage()); + } } }