15
15
16
16
package software .amazon .awssdk .enhanced .dynamodb ;
17
17
18
- import static org .assertj .core .api .Assertions .as ;
19
18
import static org .assertj .core .api .Assertions .assertThat ;
20
19
import static org .assertj .core .api .Assertions .assertThatThrownBy ;
21
20
31
30
import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedRequest ;
32
31
import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedResponse ;
33
32
import 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 ;
34
35
import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedRequest ;
35
36
import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedResponse ;
36
37
import software .amazon .awssdk .services .dynamodb .DynamoDbAsyncClient ;
41
42
import software .amazon .awssdk .services .dynamodb .model .ReturnItemCollectionMetrics ;
42
43
import software .amazon .awssdk .services .dynamodb .model .ReturnValue ;
43
44
import software .amazon .awssdk .services .dynamodb .model .ReturnValuesOnConditionCheckFailure ;
45
+ import software .amazon .awssdk .services .dynamodb .model .TransactionCanceledException ;
44
46
45
47
public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
46
48
@@ -56,13 +58,15 @@ public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegr
56
58
private static DynamoDbAsyncClient dynamoDbClient ;
57
59
private static DynamoDbEnhancedAsyncClient enhancedClient ;
58
60
private static DynamoDbAsyncTable <Record > mappedTable ;
61
+ private static DynamoDbAsyncTable <RecordWithVersion > recordWithVersionMappedTable ;
59
62
60
63
@ BeforeClass
61
64
public static void beforeClass () {
62
65
dynamoDbClient = createAsyncDynamoDbClient ();
63
66
enhancedClient = DynamoDbEnhancedAsyncClient .builder ().dynamoDbClient (dynamoDbClient ).build ();
64
67
mappedTable = enhancedClient .table (TABLE_NAME , TABLE_SCHEMA );
65
68
mappedTable .createTable (r -> r .localSecondaryIndices (LOCAL_SECONDARY_INDEX )).join ();
69
+ recordWithVersionMappedTable = enhancedClient .table (TABLE_NAME , RECORD_WITH_VERSION_TABLE_SCHEMA );
66
70
dynamoDbClient .waiter ().waitUntilTableExists (r -> r .tableName (TABLE_NAME )).join ();
67
71
}
68
72
@@ -341,4 +345,164 @@ public void getItem_withoutReturnConsumedCapacity() {
341
345
GetItemEnhancedResponse <Record > response = mappedTable .getItemWithResponse (req -> req .key (key )).join ();
342
346
assertThat (response .consumedCapacity ()).isNull ();
343
347
}
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
+ }
344
508
}
0 commit comments