Kiran
Kiran

Reputation: 879

DynamoDB Exception element does not match the schema

I want to update existing token item with last_accessed_on column (which is new). I tried below code which is failing.
Please point me what is wrong here.

//dynamoDB is initialized with config and it is good.
Table  table = dynamoDB.getTable("Token");
UpdateItemSpec  updateItemSpec = new UpdateItemSpec()
                .withPrimaryKey("GUID", "guidHashed")
                .withUpdateExpression("set #name = :val1")
                .withNameMap(new NameMap().with("#name", "last_accessed_on"))
                .withValueMap(new ValueMap().withLong(":val1", System.currentTimeMillis()));

Below is the DTO object.

@DynamoDBTable(tableName = "Token")
public class TokenItem {

    @DynamoDBHashKey(attributeName = "GUID")
    private String guid;

    @DynamoDBRangeKey(attributeName = "type")
    private String type;

    @DynamoDBAttribute(attributeName = "last_accessed_on")
    private long lastAccessedOn;

    //getter and setters
}

Error:

com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: FNEPHSAEMVJF66Q9ASUAAJG)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1660)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1324)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1074)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:745)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:669)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:651)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:515)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.doInvoke(AmazonDynamoDBClient.java:3768)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:3737)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.executeUpdateItem(AmazonDynamoDBClient.java:3448)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.java:3416)
    at com.amazonaws.services.dynamodbv2.document.internal.UpdateItemImpl.doUpdateItem(UpdateItemImpl.java:102)
    at com.amazonaws.services.dynamodbv2.document.internal.UpdateItemImpl.updateItem(UpdateItemImpl.java:86)
    at com.amazonaws.services.dynamodbv2.document.Table.updateItem(Table.java:225)

Upvotes: 0

Views: 346

Answers (2)

Matthew Pope
Matthew Pope

Reputation: 7669

You are missing the range key from your UpdateItemSpec. You need to use withPrimaryKey(String hashKeyName, Object hashKeyValue, String rangeKeyName, Object rangeKeyValue) instead of the method that accepts only the hash key. Also, type is a reserved word in DynamoDB, so you will need to add it to the NameMap.

The fixed UpdateItemSpec would be like this.

Table  table = dynamoDB.getTable("Token");
UpdateItemSpec  updateItemSpec = new UpdateItemSpec()
            .withPrimaryKey("GUID", ":guid", "#type", ":type")
            .withUpdateExpression("set #name = :val1")
            .withNameMap(new NameMap()
                    .with("#name", "last_accessed_on")
                    .with("#type", "type"))
            .withValueMap(new ValueMap()
                    .withLong(":val1", System.currentTimeMillis())
                    .withString(":guid", /* put the guid here */)
                    .withString(":type", /* put the type here */));

Upvotes: 1

tsingh
tsingh

Reputation: 421

Did you try DynamoDBMapper dyanmoDbMapper = new DynamoDBMapper(client, yourConfig);

DynamoDBQueryExpression<Token> qExp = new DynamoDBQueryExpression<Timesheet>()
            .withKeyConditionExpression(" GUID =:GUID  and type =:type")
            .withExpressionAttributeValues(mapOfGuiAndTypeValues).withScanIndexForward(false)
            .withConsistentRead(false);


QueryResultPage< Token> queryPage= dyanmoDbMapper.queryPage(Token.class, qExp);

once you have retrieved the object then update with last access value and save

dyanmoDbMapper.save(updatedObject);

Upvotes: 0

Related Questions