30
30
import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedRequest ;
31
31
import software .amazon .awssdk .enhanced .dynamodb .model .PutItemEnhancedResponse ;
32
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 ;
33
35
import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedRequest ;
34
36
import software .amazon .awssdk .enhanced .dynamodb .model .UpdateItemEnhancedResponse ;
35
37
import software .amazon .awssdk .services .dynamodb .DynamoDbAsyncClient ;
40
42
import software .amazon .awssdk .services .dynamodb .model .ReturnItemCollectionMetrics ;
41
43
import software .amazon .awssdk .services .dynamodb .model .ReturnValue ;
42
44
import software .amazon .awssdk .services .dynamodb .model .ReturnValuesOnConditionCheckFailure ;
45
+ import software .amazon .awssdk .services .dynamodb .model .TransactionCanceledException ;
43
46
44
47
public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
45
48
@@ -55,13 +58,15 @@ public class AsyncCrudWithResponseIntegrationTest extends DynamoDbEnhancedIntegr
55
58
private static DynamoDbAsyncClient dynamoDbClient ;
56
59
private static DynamoDbEnhancedAsyncClient enhancedClient ;
57
60
private static DynamoDbAsyncTable <Record > mappedTable ;
61
+ private static DynamoDbAsyncTable <RecordWithVersion > recordWithVersionMappedTable ;
58
62
59
63
@ BeforeClass
60
64
public static void beforeClass () {
61
65
dynamoDbClient = createAsyncDynamoDbClient ();
62
66
enhancedClient = DynamoDbEnhancedAsyncClient .builder ().dynamoDbClient (dynamoDbClient ).build ();
63
67
mappedTable = enhancedClient .table (TABLE_NAME , TABLE_SCHEMA );
64
68
mappedTable .createTable (r -> r .localSecondaryIndices (LOCAL_SECONDARY_INDEX )).join ();
69
+ recordWithVersionMappedTable = enhancedClient .table (TABLE_NAME , RECORD_WITH_VERSION_TABLE_SCHEMA );
65
70
dynamoDbClient .waiter ().waitUntilTableExists (r -> r .tableName (TABLE_NAME )).join ();
66
71
}
67
72
@@ -191,7 +196,7 @@ public void updateItem_returnValues_all_old() {
191
196
Record record = new Record ().setId ("1" ).setSort (10 );
192
197
mappedTable .putItem (record ).join ();
193
198
194
- Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 ). setVersion ( 1 ) ;
199
+ Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 );
195
200
196
201
197
202
UpdateItemEnhancedResponse <Record > response = mappedTable .updateItemWithResponse (r -> r .item (updatedRecord )
@@ -201,15 +206,14 @@ public void updateItem_returnValues_all_old() {
201
206
assertThat (response .attributes ().getId ()).isEqualTo (record .getId ());
202
207
assertThat (response .attributes ().getSort ()).isEqualTo (record .getSort ());
203
208
assertThat (response .attributes ().getValue ()).isEqualTo (null );
204
- assertThat (response .attributes ().getVersion ()).isEqualTo (1 );
205
209
}
206
210
207
211
@ Test
208
212
public void updateItem_returnValues_all_new () {
209
213
Record record = new Record ().setId ("1" ).setSort (10 );
210
214
mappedTable .putItem (record ).join ();
211
215
212
- Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 ). setVersion ( 1 ) ;
216
+ Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 );
213
217
214
218
215
219
UpdateItemEnhancedResponse <Record > response = mappedTable .updateItemWithResponse (r -> r .item (updatedRecord )
@@ -219,15 +223,14 @@ public void updateItem_returnValues_all_new() {
219
223
assertThat (response .attributes ().getId ()).isEqualTo (updatedRecord .getId ());
220
224
assertThat (response .attributes ().getSort ()).isEqualTo (updatedRecord .getSort ());
221
225
assertThat (response .attributes ().getValue ()).isEqualTo (updatedRecord .getValue ());
222
- assertThat (response .attributes ().getVersion ()).isEqualTo (updatedRecord .getVersion () + 1 );
223
226
}
224
227
225
228
@ Test
226
229
public void updateItem_returnValues_not_set () {
227
230
Record record = new Record ().setId ("1" ).setSort (10 );
228
231
mappedTable .putItem (record ).join ();
229
232
230
- Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 ). setVersion ( 1 ) ;
233
+ Record updatedRecord = new Record ().setId ("1" ).setSort (10 ).setValue (11 );
231
234
232
235
233
236
UpdateItemEnhancedResponse <Record > response = mappedTable .updateItemWithResponse (r -> r .item (updatedRecord ))
@@ -236,7 +239,6 @@ public void updateItem_returnValues_not_set() {
236
239
assertThat (response .attributes ().getId ()).isEqualTo (updatedRecord .getId ());
237
240
assertThat (response .attributes ().getSort ()).isEqualTo (updatedRecord .getSort ());
238
241
assertThat (response .attributes ().getValue ()).isEqualTo (updatedRecord .getValue ());
239
- assertThat (response .attributes ().getVersion ()).isEqualTo (updatedRecord .getVersion () + 1 );
240
242
}
241
243
242
244
@ Test
@@ -343,4 +345,61 @@ public void getItem_withoutReturnConsumedCapacity() {
343
345
GetItemEnhancedResponse <Record > response = mappedTable .getItemWithResponse (req -> req .key (key )).join ();
344
346
assertThat (response .consumedCapacity ()).isNull ();
345
347
}
348
+
349
+ @ Test
350
+ public void deleteItemWithOptimisticLockingEnabled_shouldSucceedIfVersionMatch () {
351
+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
352
+ Key recordKey = Key .builder ()
353
+ .partitionValue (originalItem .getId ())
354
+ .sortValue (originalItem .getSort ())
355
+ .build ();
356
+ recordWithVersionMappedTable .putItem (originalItem ).join ();
357
+
358
+ // Retrieve the item
359
+ RecordWithVersion retrievedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
360
+
361
+ // Delete the item using a transaction
362
+ TransactWriteItemsEnhancedRequest request = TransactWriteItemsEnhancedRequest .builder ()
363
+ .addDeleteItem (recordWithVersionMappedTable , retrievedItem )
364
+ .build ();
365
+
366
+ enhancedClient .transactWriteItems (request ).join ();
367
+
368
+ RecordWithVersion deletedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
369
+ assertThat (deletedItem ).isNull ();
370
+ }
371
+
372
+ @ Test
373
+ public void deleteItemWithOptimisticLockingEnabled_shouldFailIfVersionMismatch () {
374
+ RecordWithVersion originalItem = new RecordWithVersion ().setId ("123" ).setSort (10 ).setStringAttribute ("Original Item" );
375
+ Key recordKey = Key .builder ()
376
+ .partitionValue (originalItem .getId ())
377
+ .sortValue (originalItem .getSort ())
378
+ .build ();
379
+
380
+ recordWithVersionMappedTable .putItem (originalItem ).join ();
381
+
382
+ // Retrieve the item and modify it separately
383
+ RecordWithVersion modifiedItem = recordWithVersionMappedTable .getItem (r -> r .key (recordKey )).join ();
384
+ modifiedItem .setStringAttribute ("Updated Item" );
385
+
386
+ // Update the item, which will increment the version
387
+ recordWithVersionMappedTable .updateItem (modifiedItem ).join ();
388
+
389
+ // Now attempt to delete the original item using a transaction
390
+ TransactWriteItemsEnhancedRequest request = TransactWriteItemsEnhancedRequest .builder ()
391
+ .addDeleteItem (recordWithVersionMappedTable , modifiedItem )
392
+ .build ();
393
+
394
+ assertThatThrownBy (() -> enhancedClient .transactWriteItems (request ).join ())
395
+ .isInstanceOf (CompletionException .class )
396
+ .satisfies (e ->
397
+ assertThat (((TransactionCanceledException ) e .getCause ())
398
+ .cancellationReasons ()
399
+ .stream ()
400
+ .anyMatch (reason ->
401
+ "ConditionalCheckFailed" .equals (reason .code ())
402
+ && "The conditional request failed" .equals (reason .message ())))
403
+ .isTrue ());
404
+ }
346
405
}
0 commit comments