1313 * permissions and limitations under the License.
1414 */
1515
16+
1617package software .amazon .awssdk .enhanced .dynamodb ;
1718
18- import static org .assertj .core .api .Assertions .as ;
1919import static org .assertj .core .api .Assertions .assertThat ;
2020import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2121
3131import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedRequest ;
3232import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedResponse ;
3333import software .amazon .awssdk .enhanced .dynamodb .model .Record ;
34+ import software .amazon .awssdk .enhanced .dynamodb .model .RecordWithVersion ;
35+ import software .amazon .awssdk .enhanced .dynamodb .model .TransactWriteItemsEnhancedRequest ;
3436import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedRequest ;
3537import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedResponse ;
3638import software .amazon .awssdk .services .dynamodb .DynamoDbAsyncClient ;
4143import software .amazon .awssdk .services .dynamodb .model .ReturnItemCollectionMetrics ;
4244import software .amazon .awssdk .services .dynamodb .model .ReturnValue ;
4345import software .amazon .awssdk .services .dynamodb .model .ReturnValuesOnConditionCheckFailure ;
46+ import software .amazon .awssdk .services .dynamodb .model .TransactionCanceledException ;
4447
4548public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
4649
@@ -56,13 +59,15 @@ public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegr
5659 private static DynamoDbAsyncClient dynamoDbClient ;
5760 private static DynamoDbEnhancedAsyncClient enhancedClient ;
5861 private static DynamoDbAsyncTable <Record > mappedTable ;
62+ private static DynamoDbAsyncTable <RecordWithVersion > recordWithVersionMappedTable ;
5963
6064 @ BeforeClass
6165 public static void beforeClass () {
6266 dynamoDbClient = createAsyncDynamoDbClient ();
6367 enhancedClient = DynamoDbEnhancedAsyncClient .builder ().dynamoDbClient (dynamoDbClient ).build ();
6468 mappedTable = enhancedClient .table (TABLE_NAME , TABLE_SCHEMA );
6569 mappedTable .createTable (r -> r .localSecondaryIndices (LOCAL_SECONDARY_INDEX )).join ();
70+ recordWithVersionMappedTable = enhancedClient .table (TABLE_NAME , RECORD_WITH_VERSION_TABLE_SCHEMA );
6671 dynamoDbClient .waiter ().waitUntilTableExists (r -> r .tableName (TABLE_NAME )).join ();
6772 }
6873
@@ -113,8 +118,8 @@ public void putItem_returnItemCollectionMetrics_set_itemCollectionMetricsNotNull
113118 public void updateItem_returnItemCollectionMetrics_set_itemCollectionMetricsNull () {
114119 Record record = new Record ().setId ("1" ).setSort (10 );
115120 UpdateItemEnhancedRequest <Record > request = UpdateItemEnhancedRequest .builder (Record .class )
116- .item (record )
117- .build ();
121+ .item (record )
122+ .build ();
118123
119124 UpdateItemEnhancedResponse <Record > response = mappedTable .updateItemWithResponse (request ).join ();
120125
@@ -196,8 +201,8 @@ public void updateItem_returnValues_all_old() {
196201
197202
198203 UpdateItemEnhancedResponse <Record > response = mappedTable .updateItemWithResponse (r -> r .item (updatedRecord )
199- .returnValues (ReturnValue .ALL_OLD ))
200- .join ();
204+ .returnValues (ReturnValue .ALL_OLD ))
205+ .join ();
201206
202207 assertThat (response .attributes ().getId ()).isEqualTo (record .getId ());
203208 assertThat (response .attributes ().getSort ()).isEqualTo (record .getSort ());
@@ -341,4 +346,167 @@ public void getItem_withoutReturnConsumedCapacity() {
341346 GetItemEnhancedResponse <Record > response = mappedTable .getItemWithResponse (req -> req .key (key )).join ();
342347 assertThat (response .consumedCapacity ()).isNull ();
343348 }
349+
350+ @ Test
351+ public void deleteItemWithoutVersion_andOptimisticLockingEnabled_shouldSucceed () {
352+ Record originalItem = new Record ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
353+ Key recordKey = Key .builder ()
354+ .partitionValue (originalItem .getId ())
355+ .sortValue (originalItem .getSort ())
356+ .build ();
357+ mappedTable .putItem (originalItem ).join ();
358+
359+ // Retrieve the item
360+ Record retrievedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
361+
362+ // Delete the item using a transaction
363+ TransactWriteItemsEnhancedRequest request =
364+ TransactWriteItemsEnhancedRequest .builder ()
365+ .addDeleteItem (mappedTable , retrievedItem )
366+ .build ();
367+
368+ enhancedClient .transactWriteItems (request ).join ();
369+
370+ Record deletedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
371+ assertThat (deletedItem ).isNull ();
372+ }
373+
374+ @ Test
375+ public void deleteItemWithoutVersion_andOptimisticLockingDisabled_shouldSucceed () {
376+ Record originalItem = new Record ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
377+ Key recordKey = Key .builder ()
378+ .partitionValue (originalItem .getId ())
379+ .sortValue (originalItem .getSort ())
380+ .build ();
381+ mappedTable .putItem (originalItem ).join ();
382+
383+ // Retrieve the item
384+ Record retrievedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
385+
386+ // Delete the item using a transaction
387+ TransactWriteItemsEnhancedRequest request =
388+ TransactWriteItemsEnhancedRequest .builder ()
389+ .addDeleteItem (mappedTable , retrievedItem )
390+ .build ();
391+
392+ enhancedClient .transactWriteItems (request ).join ();
393+
394+ Record deletedItem = mappedTable .getItem (r -> r .key (recordKey )).join ();
395+ assertThat (deletedItem ).isNull ();
396+ }
397+
398+ @ Test
399+ public void deleteItemWithVersion_andOptimisticLockingEnabled_ifVersionMatch_shouldSucceed () {
400+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
401+ Key recordKey = Key .builder ()
402+ .partitionValue (originalItem .getId ())
403+ .sortValue (originalItem .getSort ())
404+ .build ();
405+ recordWithVersionMappedTable .putItem (originalItem ).join ();
406+
407+ // Retrieve the item
408+ RecordWithVersion retrievedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
409+
410+ // Delete the item using a transaction
411+ TransactWriteItemsEnhancedRequest request =
412+ TransactWriteItemsEnhancedRequest .builder ()
413+ .addDeleteItem (recordWithVersionMappedTable , retrievedItem )
414+ .build ();
415+
416+ enhancedClient .transactWriteItems (request ).join ();
417+
418+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
419+ assertThat (deletedItem ).isNull ();
420+ }
421+
422+ @ Test
423+ public void deleteItemWithVersion_andOptimisticLockingEnabled_ifVersionMismatch_shouldFail () {
424+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
425+ Key recordKey = Key .builder ()
426+ .partitionValue (originalItem .getId ())
427+ .sortValue (originalItem .getSort ())
428+ .build ();
429+
430+ recordWithVersionMappedTable .putItem (originalItem ).join ();
431+
432+ // Retrieve the item and modify it separately
433+ RecordWithVersion modifiedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
434+ modifiedItem .setStringAttribute ("Updated Item" );
435+
436+ // Update the item, which will increment the version
437+ recordWithVersionMappedTable .updateItem (modifiedItem );
438+
439+
440+ // Now attempt to delete the original item using a transaction
441+ TransactWriteItemsEnhancedRequest request =
442+ TransactWriteItemsEnhancedRequest .builder ()
443+ .addDeleteItem (recordWithVersionMappedTable , modifiedItem )
444+ .build ();
445+
446+ // enhancedClient.transactWriteItems(request).join();
447+
448+ assertThatThrownBy (() -> enhancedClient .transactWriteItems (request ).join ())
449+ .isInstanceOf (CompletionException .class )
450+ .satisfies (e ->
451+ assertThat (((TransactionCanceledException ) e .getCause ())
452+ .cancellationReasons ()
453+ .stream ()
454+ .anyMatch (reason ->
455+ "ConditionalCheckFailed" .equals (reason .code ())
456+ && "The conditional request failed" .equals (reason .message ())))
457+ .isTrue ());
458+ }
459+
460+ @ Test
461+ public void deleteItemWithVersion_andOptimisticLockingDisabled_ifVersionMatch_shouldSucceed () {
462+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
463+ Key recordKey = Key .builder ()
464+ .partitionValue (originalItem .getId ())
465+ .sortValue (originalItem .getSort ())
466+ .build ();
467+ recordWithVersionMappedTable .putItem (originalItem ).join ();
468+
469+ // Retrieve the item
470+ RecordWithVersion retrievedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
471+
472+ // Delete the item using a transaction
473+ TransactWriteItemsEnhancedRequest request =
474+ TransactWriteItemsEnhancedRequest .builder ()
475+ .addDeleteItem (recordWithVersionMappedTable , retrievedItem )
476+ .build ();
477+
478+ enhancedClient .transactWriteItems (request ).join ();
479+
480+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
481+ assertThat (deletedItem ).isNull ();
482+ }
483+
484+ @ Test
485+ public void deleteItemWithVersion_andOptimisticLockingDisabled_ifVersionMismatch_shouldSucceed () {
486+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
487+ Key recordKey = Key .builder ()
488+ .partitionValue (originalItem .getId ())
489+ .sortValue (originalItem .getSort ())
490+ .build ();
491+
492+ recordWithVersionMappedTable .putItem (originalItem ).join ();
493+
494+ // Retrieve the item and modify it separately
495+ RecordWithVersion modifiedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
496+ modifiedItem .setStringAttribute ("Updated Item" );
497+
498+ // Update the item, which will increment the version
499+ recordWithVersionMappedTable .updateItem (modifiedItem );
500+
501+ // Now attempt to delete the original item using a transaction
502+ TransactWriteItemsEnhancedRequest request =
503+ TransactWriteItemsEnhancedRequest .builder ()
504+ .addDeleteItem (recordWithVersionMappedTable , modifiedItem )
505+ .build ();
506+
507+ enhancedClient .transactWriteItems (request ).join ();
508+
509+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
510+ assertThat (deletedItem ).isNull ();
511+ }
344512}
0 commit comments