Adam Bronfin
Adam Bronfin

Reputation: 1299

Java DynamoDB Validation exception required "key not given" when exists in JSON

Running into exception while running dynamoDB .putItem().

Table definition:

{
  "AttributeDefinitions": [
    {
      "AttributeName": "storage_CACHE_KEY",
      "AttributeType": "S"
    }
  ],
  "TableName": "my-table",
  "KeySchema": [
    {
      "AttributeName": "storage_CACHE_KEY",
      "KeyType": "HASH"
    }
  ],
  "TableStatus": "ACTIVE",
  "CreationDateTime": "2017-11-01T05:01:18.883Z",
  "ProvisionedThroughput": {
    "LastIncreaseDateTime": "1970-01-01T00:00:00.000Z",
    "LastDecreaseDateTime": "1970-01-01T00:00:00.000Z",
    "NumberOfDecreasesToday": 0,
    "ReadCapacityUnits": 3,
    "WriteCapacityUnits": 3
  },
  "TableSizeBytes": 199,
  "ItemCount": 1,
  "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/my-table"
} 

Additionally value I'm attempting to put when serialized into JSON appears like so:

{
  "storage_CACHE_KEY" : "storage_cache_key_value",
  "some_other_fields" : [""]
}

I still can't figure out why the below errors are occurring:

com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: One of the required keys was not given a value (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID:

Update: How .putItem is being used

public <T> PutItemResult put(String key, T value, Optional<Long> expires) throws JsonProcessingException {
    PutItemRequest req = (new PutItemRequest()).withTableName(this.tableName).withItem(this.keyValuePair(key, value, expires));
    return this.db.putItem(req);
}
private Map<String, AttributeValue> buildKey(String value) {
    Map<String, AttributeValue> key = new HashMap();
    key.put("name", new AttributeValue(value));
    return key;
}

private <T> Map<String, AttributeValue> keyValuePair(String key, T value, Optional<Long> expires) throws JsonProcessingException {
    Map<String, AttributeValue> item = this.buildKey(key);
    item.put("json", new AttributeValue(this.mapper.writeValueAsString(value)));
    if (expires.isPresent()) {
        item.put(this.ttlKey, (new AttributeValue()).withN(((Long)expires.get()).toString()));
    }

    return item;
}

I have stepped over this code and have seen that T value is JSON in precisely the format I have posted above.

Update: putItem succeeded when I changed the map entry from name to storage_CACHE_KEY but now read fails to marshal back to my object. The json stored in my local dynamodb for the entry is:

{
  "storage_CACHE_KEY": "4728264794434232301",
  "json": "{\"storage_CACHE_KEY\":\"23232432472826479401\", \"otherFields\": \"example\"}"
}

(0 known properties: ]) Unrecognized field "present" (class java.util.Optional), not marked as ignorable

Upvotes: 0

Views: 2956

Answers (1)

APILoader
APILoader

Reputation: 31

I just spent a whole day resolving an instance of this error. I haven't researched your question to see if it is relevant but offer it for what its worth. My cause was creating the table one way and accessing it another. Specifically I was creating the table with createTable in com.amazonaws.services.dynamodbv2.document (which returns a Table) when I should have been using createTable in com.amazonaws.services.dynamodbv2 (which returns a CreateTableResult). If you create with the former and then try and access the table from the Java mapper with mapper.load() you get the error.

Just to complete the confusion if you describe the table to a TableDescription and then convert that to a String with .toString() you get exactly the same description (net of creation date and such) whichever way you created the table. But for all that they aren't the same to the Java mapper.

Upvotes: 3

Related Questions