1515
1616package software .amazon .awssdk .enhanced .dynamodb ;
1717
18- import static org .assertj .core .api .Assertions .as ;
1918import static org .assertj .core .api .Assertions .assertThat ;
2019import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2120
3130import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedRequest ;
3231import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedResponse ;
3332import software .amazon .awssdk .enhanced .dynamodb .model .Record ;
33+ import software .amazon .awssdk .enhanced .dynamodb .model .RecordWithVersion ;
34+ import software .amazon .awssdk .enhanced .dynamodb .model .TransactWriteItemsEnhancedRequest ;
3435import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedRequest ;
3536import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedResponse ;
3637import software .amazon .awssdk .services .dynamodb .DynamoDbAsyncClient ;
4142import software .amazon .awssdk .services .dynamodb .model .ReturnItemCollectionMetrics ;
4243import software .amazon .awssdk .services .dynamodb .model .ReturnValue ;
4344import software .amazon .awssdk .services .dynamodb .model .ReturnValuesOnConditionCheckFailure ;
45+ import software .amazon .awssdk .services .dynamodb .model .TransactionCanceledException ;
4446
4547public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
4648
@@ -56,13 +58,15 @@ public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegr
5658 private static DynamoDbAsyncClient dynamoDbClient ;
5759 private static DynamoDbEnhancedAsyncClient enhancedClient ;
5860 private static DynamoDbAsyncTable <Record > mappedTable ;
61+ private static DynamoDbAsyncTable <RecordWithVersion > recordWithVersionMappedTable ;
5962
6063 @ BeforeClass
6164 public static void beforeClass () {
6265 dynamoDbClient = createAsyncDynamoDbClient ();
6366 enhancedClient = DynamoDbEnhancedAsyncClient .builder ().dynamoDbClient (dynamoDbClient ).build ();
6467 mappedTable = enhancedClient .table (TABLE_NAME , TABLE_SCHEMA );
6568 mappedTable .createTable (r -> r .localSecondaryIndices (LOCAL_SECONDARY_INDEX )).join ();
69+ recordWithVersionMappedTable = enhancedClient .table (TABLE_NAME , RECORD_WITH_VERSION_TABLE_SCHEMA );
6670 dynamoDbClient .waiter ().waitUntilTableExists (r -> r .tableName (TABLE_NAME )).join ();
6771 }
6872
@@ -341,4 +345,164 @@ public void getItem_withoutReturnConsumedCapacity() {
341345 GetItemEnhancedResponse <Record > response = mappedTable .getItemWithResponse (req -> req .key (key )).join ();
342346 assertThat (response .consumedCapacity ()).isNull ();
343347 }
348+
349+ @ Test
350+ public void deleteItemWithoutVersion_andOptimisticLockingEnabled_shouldSucceed () {
351+ Record originalItem = new Record ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
352+ Key recordKey = Key .builder ()
353+ .partitionValue (originalItem .getId ())
354+ .sortValue (originalItem .getSort ())
355+ .build ();
356+ mappedTable .putItem (originalItem ).join ();
357+
358+ // Retrieve the item
359+ Record retrievedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
360+
361+ // Delete the item using a transaction
362+ TransactWriteItemsEnhancedRequest request =
363+ TransactWriteItemsEnhancedRequest .builder ()
364+ .addDeleteItem (mappedTable , retrievedItem , true )
365+ .build ();
366+
367+ enhancedClient .transactWriteItems (request ).join ();
368+
369+ Record deletedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
370+ assertThat (deletedItem ).isNull ();
371+ }
372+
373+ @ Test
374+ public void deleteItemWithoutVersion_andOptimisticLockingDisabled_shouldSucceed () {
375+ Record originalItem = new Record ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
376+ Key recordKey = Key .builder ()
377+ .partitionValue (originalItem .getId ())
378+ .sortValue (originalItem .getSort ())
379+ .build ();
380+ mappedTable .putItem (originalItem ).join ();
381+
382+ // Retrieve the item
383+ Record retrievedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
384+
385+ // Delete the item using a transaction
386+ TransactWriteItemsEnhancedRequest request =
387+ TransactWriteItemsEnhancedRequest .builder ()
388+ .addDeleteItem (mappedTable , retrievedItem , false )
389+ .build ();
390+
391+ enhancedClient .transactWriteItems (request ).join ();
392+
393+ Record deletedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
394+ assertThat (deletedItem ).isNull ();
395+ }
396+
397+ @ Test
398+ public void deleteItemWithVersion_andOptimisticLockingEnabled_ifVersionMatch_shouldSucceed () {
399+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
400+ Key recordKey = Key .builder ()
401+ .partitionValue (originalItem .getId ())
402+ .sortValue (originalItem .getSort ())
403+ .build ();
404+ recordWithVersionMappedTable .putItem (originalItem ).join ();
405+
406+ // Retrieve the item
407+ RecordWithVersion retrievedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
408+
409+ // Delete the item using a transaction
410+ TransactWriteItemsEnhancedRequest request =
411+ TransactWriteItemsEnhancedRequest .builder ()
412+ .addDeleteItem (recordWithVersionMappedTable , retrievedItem , true )
413+ .build ();
414+
415+ enhancedClient .transactWriteItems (request ).join ();
416+
417+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
418+ assertThat (deletedItem ).isNull ();
419+ }
420+
421+ @ Test
422+ public void deleteItemWithVersion_andOptimisticLockingEnabled_ifVersionMismatch_shouldFail () {
423+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
424+ Key recordKey = Key .builder ()
425+ .partitionValue (originalItem .getId ())
426+ .sortValue (originalItem .getSort ())
427+ .build ();
428+
429+ recordWithVersionMappedTable .putItem (originalItem ).join ();
430+
431+ // Retrieve the item and modify it separately
432+ RecordWithVersion modifiedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
433+ modifiedItem .setStringAttribute ("Updated Item" );
434+
435+ // Update the item, which will increment the version
436+ recordWithVersionMappedTable .updateItem (modifiedItem );
437+
438+ // Now attempt to delete the original item using a transaction
439+ TransactWriteItemsEnhancedRequest request =
440+ TransactWriteItemsEnhancedRequest .builder ()
441+ .addDeleteItem (recordWithVersionMappedTable , modifiedItem , true )
442+ .build ();
443+
444+ assertThatThrownBy (() -> enhancedClient .transactWriteItems (request ).join ())
445+ .isInstanceOf (CompletionException .class )
446+ .satisfies (e ->
447+ assertThat (((TransactionCanceledException ) e .getCause ())
448+ .cancellationReasons ()
449+ .stream ()
450+ .anyMatch (reason ->
451+ "ConditionalCheckFailed" .equals (reason .code ())
452+ && "The conditional request failed" .equals (reason .message ())))
453+ .isTrue ());
454+ }
455+
456+ @ Test
457+ public void deleteItemWithVersion_andOptimisticLockingDisabled_ifVersionMatch_shouldSucceed () {
458+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
459+ Key recordKey = Key .builder ()
460+ .partitionValue (originalItem .getId ())
461+ .sortValue (originalItem .getSort ())
462+ .build ();
463+ recordWithVersionMappedTable .putItem (originalItem ).join ();
464+
465+ // Retrieve the item
466+ RecordWithVersion retrievedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
467+
468+ // Delete the item using a transaction
469+ TransactWriteItemsEnhancedRequest request =
470+ TransactWriteItemsEnhancedRequest .builder ()
471+ .addDeleteItem (recordWithVersionMappedTable , retrievedItem , false )
472+ .build ();
473+
474+ enhancedClient .transactWriteItems (request ).join ();
475+
476+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
477+ assertThat (deletedItem ).isNull ();
478+ }
479+
480+ @ Test
481+ public void deleteItemWithVersion_andOptimisticLockingDisabled_ifVersionMismatch_shouldSucceed () {
482+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
483+ Key recordKey = Key .builder ()
484+ .partitionValue (originalItem .getId ())
485+ .sortValue (originalItem .getSort ())
486+ .build ();
487+
488+ recordWithVersionMappedTable .putItem (originalItem ).join ();
489+
490+ // Retrieve the item and modify it separately
491+ RecordWithVersion modifiedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
492+ modifiedItem .setStringAttribute ("Updated Item" );
493+
494+ // Update the item, which will increment the version
495+ recordWithVersionMappedTable .updateItem (modifiedItem );
496+
497+ // Now attempt to delete the original item using a transaction
498+ TransactWriteItemsEnhancedRequest request =
499+ TransactWriteItemsEnhancedRequest .builder ()
500+ .addDeleteItem (recordWithVersionMappedTable , modifiedItem , false )
501+ .build ();
502+
503+ enhancedClient .transactWriteItems (request ).join ();
504+
505+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
506+ assertThat (deletedItem ).isNull ();
507+ }
344508}
0 commit comments