0
votes

I am getting conditionalcheckfailed exception when trying to save/update items using dynamodb mapper.

Can anyone please share snippet of code using java that can demonstrate how versioning and optimistic locking can be implemented successfully?

Tried not setting version at all!! Tried adding a record to table, and then doing read before save.

Nothing woked!! I continue to get ConditionalCheckFailed Exception. Only thing works is if I set the config to COBBLER!! but that's not what I want as I need optimistic locking for my data.

DB item class---

@DynamoDBTable(tableName="Funds")
public class FundsItem {
    private String id;
    private String auditId;
    private Long version;
    private String shopId;
    private String terminalId;
    private String txId;

    @DynamoDBHashKey(attributeName = "Id")
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    @DynamoDBRangeKey(attributeName = "AuditId")
    public String getAuditId() {
        return auditId;
    }
    public void setAuditId(String auditId) {
        this.auditId = auditId;
    }

    @DynamoDBVersionAttribute(attributeName = "Version")
    public Long getVersion() { return version; }
    public void setVersion(Long version) { this.version = version; }


    @DynamoDBAttribute(attributeName = "ShopId")
    public String getShopId() {
        return shopId;
    }
    public void setShopId(String shopId) {
        this.shopId = shopId;
    }

    @DynamoDBAttribute(attributeName = "TerminalId")
    public String getTerminalId() { return terminalId; }
    public void setTerminalId(String terminalId) {
        this.terminalId = terminalId;
    }

    @DynamoDBAttribute(attributeName = "TxId")
    public String getTxId() {
        return txId;
    }
    public void setTxId(String txId) {
        this.txId = txId;
    }

   }

Code to save new item -----

public long addFunds(FundsRequest request){

  FundsItem dbItem = new FundsItem();

  String Id = request.getShopId().trim() + request.getTerminalId().trim();
  String V0_Audit_Rec = "V0_Audit_" + Id;


        //save V0 item.
        dbItem.setVersion((long) 1);
        dbItem.setId(Id);
        dbItem.setAuditId(V0_Audit_Rec);
        dbItem.setShopId(request.getShopId().trim());
        dbItem.setTerminalId(request.getTerminalId().trim());
        dbItem.setTxId(request.getTxId().trim());

        mapper.save(dbItem);
}

Pls check the snippet above - This is a new empty table. hashkey - id, rangekey - auditId, VersionField - version.

I just want to be able to add a new record that's why not doing any read before saving a new item. If I can get this simple case i.e. adding a new /first record to the dynamodb table work, I can implement rest of the use cases too.

1

1 Answers

1
votes

In general:

  1. Never set your version, the SDK will initialise this if required.
  2. Always try and load an item with your key first. If null is returned, create the item and save it. Else update the returned item and save it.

I know you mentioned you've tried the above. If its truely an empty table your code should work OK (minus the setting of the version).

A couple of things I would also do:

  • Don't set your version field with a custom attribute name. In theory this should be fine, but for the sake of making your code the same as the AWS examples, I would remove this, at least until you have it working.
  • Although I think you need to remove the setting of the version, I note you are casting to a long, not a Long. Again, unlikely to be an issue but just something to eliminate at least. i.e. if you insist of setting version use new Long(l).