Dynamodb ConditionalCheckFailedException on read / update operation - java sdk

I am new to DynamoDB and have tested a sample script using Transaction support. I use the same object provided in the dynamodb-transaction library. The only difference is that I added a range key with a hash key. Here is the table definition:

  • ItemId hash key, string
  • ItemName range key, string

 @DynamoDBTable(tableName = "Item") public static class ExampleItem { private String itemId; private String value; private String itemName; private Long version; @DynamoDBHashKey(attributeName = "ItemId") public String getItemId() { return itemId; } public void setItemId(String itemId) { this.itemId = itemId; } @DynamoDBRangeKey(attributeName="ItemName") public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @DynamoDBVersionAttribute public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version; } } 

As you can see, I also use the version attribute. Now I am trying to execute a simple create or update script using transaction / dbmapper. Here's a snippet of code.

 Transaction t1 = txManager.newTransaction(); ExampleItem keyItem = new ExampleItem(); keyItem.setItemId("Item1"); keyItem.setItemName("USA"); ExampleItem item = t1.load(keyItem); if (item != null) { item.setValue("Magenta"); item.setItemName("UK"); t1.save(item); } else { item = new ExampleItem(); item.setItemId(keyItem.getItemId()); item.setItemName("USA"); item.setValue("Violet"); t1.save(item); } t1.commit(); t1.delete(); 

I can add the record without any problems, but I had a problem when I try to read the record and update any attribute. I get the following exception:

 Uncaught exception:com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: Item {ItemId={S: Item1,}, ItemName={S: UK,}} had unexpected attributes: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: expected attribute(s) {version={Value: {N: 1,},Exists: true}} but found null com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: Item {ItemId={S: Item1,}, ItemName={S: UK,}} had unexpected attributes: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: expected attribute(s) {version={Value: {N: 1,},Exists: true}} but found null 

It seems like this has something to do with the version, but don't know where I am going wrong. Any pointers would be appreciated.

-Thanks

Shamik

+7
java amazon-web-services amazon-dynamodb aws-sdk
source share
3 answers

It looks like you need to install the version when creating the element class. He expects 1, but found zero. The versionedAttribute version expects a value, and it seems that when an element is first created, it expects 1.

If you update this item in the future, it should take care of increasing the version inside.

+2
source share

Dynamodb has this concept. Optimistic locking is a strategy to ensure that the client-side item that you update (or delete) is the same as the item in DynamoDB.

  • First save:

If this is the first update, you should follow this format

 DynamodbSaveExpression saveExpression = new DynamodbSaveExpression() .withExpectedEntry("ItemId", new ExpectedAttributeValue().withExists(false) .withConditionalOperator(AND) .withExpectedEntry("ItemName", new ExpectedAttributeValue().withExists(false)); // saving the item to dynamodb dynamodbmapper.save(itemToSave, saveExpression); 

Explanation: We are reporting that itemToSave should only be saved when the combination "ItemId", "ItemValue" is not present in dynamodb.

  1. Update existing item:

To update an existing item in dynamodb you need to follow this format

 // Step1: Do a GET ExampleItem itemInDynamo = dynamoDBMapper.load(ExampleItem.class, "item_id_value", "item_name_value"); // Step2: Get the version in Dynamo Long versionInDynamo = itemInDynamo.getVersion(); DynamodbSaveExpression saveExpression = new DynamodbSaveExpression() .withExpectedEntry("version", new ExpectedAttributeValue(new AttributeValue().withN(versionInDynamodb.toString()))); // Step3: Update the item dynamodbmapper.save(itemToSave, saveExpression); 

Save will only succeed, if the version you save with is the same in Dynamodb, if you don’t save the crash with ConditionalCheckFailedException , then try again from step 1. First, Read, then write.

+2
source share

This usually happens when your keys are the same for more than one element in dynamodb. For example, if you have a Folder with id as hashKey and folder_name as rangeKey, you will not save the Folder again, where your hash (hashkey + rangeKey) will be the same.

0
source share

All Articles