Gourab Banerjee
Gourab Banerjee

Reputation: 59

One or more parameter values were invalid dynamoDB + Java

I am trying to create a table in DynamoDB. I could use DynamoDB console but I prefer doing it via Java. But the following code is giving exception and I can't find why..

Please check the following code..

String serviceRef = "ServiceRef";
ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement()
        .withAttributeName("ServiceID")
        .withKeyType(KeyType.HASH));

ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition()
        .withAttributeName("ServiceID")
        .withAttributeType(ScalarAttributeType.N)
        .withAttributeName("ServiceName")
        .withAttributeType(ScalarAttributeType.S)
        .withAttributeName("CreatedDateUTC")
        .withAttributeType(ScalarAttributeType.N)
        .withAttributeName("UpdatedDateUTC")
        .withAttributeType(ScalarAttributeType.N)
        .withAttributeName("IsDeleted")
        .withAttributeType(ScalarAttributeType.B));

CreateTableRequest request = new CreateTableRequest()
        .withTableName(serviceRef)
        .withKeySchema(keySchema)
        .withAttributeDefinitions(attributeDefinitions)
        .withProvisionedThroughput(
                new ProvisionedThroughput().withReadCapacityUnits(5L).withWriteCapacityUnits(1L));

System.out.println("Issuing create table request for: " + serviceRef);
dynamoDBClient.createTable(request);
System.out.println("Waiting for table Name: " + serviceRef + " to be created...");
try {
    Tables.awaitTableToBecomeActive(dynamoDBClient, serviceRef);
} catch (InterruptedException e) {
    e.printStackTrace();
}

What is wrong with this code? The error it is giving is -

Exception in thread "main" com.amazonaws.AmazonServiceException: One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [ServiceID], AttributeDefinitions: [IsDeleted] (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: SA8P5UUVH37T8P1R7F6VVPP357VV4KQNSO5AEMVJF66Q9ASUAAJG)
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1219)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:803)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:505)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:317)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:1803)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.createTable(AmazonDynamoDBClient.java:832)
    at com.rit.randemmiddleware.controller.TestMain.main(TestMain.java:38)

Also what to use in space of

Tables.awaitTableToBecomeActive(dynamoDBClient, serviceRef);

As it is showing deprecated.

Upvotes: 4

Views: 16928

Answers (3)

sergpank
sergpank

Reputation: 988

It is also necessary to mention that AttributeDefinitions should contain only columns that are necessary for table decalration/description (KeySchema and GlobalSecondaryIndexes). Because DynamoDB is schemaless.

If you will try to create a table with more attributes than is necessary for indexes, you will get an error like:Exception in thread "main" com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: One or more parameter values were invalid: Some AttributeDefinitions are not used. AttributeDefinitions: [Precipitation, Temperature, Rank, ID, Date, Location], keys used: [ID, Date, Location]

I came here with the following case:

Attribute Definitions:

attributeDefinitions.add(new AttributeDefinition("ID", "S"));
attributeDefinitions.add(new AttributeDefinition("Location", "S"));
attributeDefinitions.add(new AttributeDefinition("Date", "S"));
attributeDefinitions.add(new AttributeDefinition("Precipitation", "N"));
attributeDefinitions.add(new AttributeDefinition("Temperature", "N"));
attributeDefinitions.add(new AttributeDefinition("Rank", "N"));

Key Schema:

tableKeySchema.add(new KeySchemaElement("ID", KeyType.HASH))

Global Secondary Index:

GlobalSecondaryIndex locationDateIndex = new GlobalSecondaryIndex()
            .withIndexName("Location_Date-Index")
            .withProjection(new 
Projection().withProjectionType(ProjectionType.ALL))
            .withProvisionedThroughput(new ProvisionedThroughput(10l, 1l))
            .withKeySchema(new KeySchemaElement("Location", KeyType.HASH))
            .withKeySchema(new KeySchemaElement("Date", KeyType.RANGE));

Create Table Request:

CreateTableRequest createTableRequest = new CreateTableRequest()
    .withTableName(tableName)
    .withProvisionedThroughput(new ProvisionedThroughput(5L, 1L))
    .withAttributeDefinitions(attributeDefinitions)
    .withKeySchema(tableKeySchema)
    .withGlobalSecondaryIndexes(locationDateIndex);

And the error from above:

Exception in thread "main" com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: 
One or more parameter values were invalid: Some AttributeDefinitions are not used. 
AttributeDefinitions: [Precipitation, Temperature, Rank, ID, Date, Location], 
keys used: [ID, Date, Location] (Service: AmazonDynamoDBv2; Status Code: 400; 
Error Code: ValidationException; Request ID: ...)

Reducing Attribute Definition List solved my problem:

attributeDefinitions.add(new AttributeDefinition("ID", "S"));
attributeDefinitions.add(new AttributeDefinition("Location", "S"));
attributeDefinitions.add(new AttributeDefinition("Date", "S"));

PS: I answer here because this page is relevant for my request in Google.

Upvotes: 4

mkobit
mkobit

Reputation: 47239

You have only created a single AttributeDefinition. Your method chaining only produces a single AttributeDefinition, rather than a list of them. You also only need to create an AttributeDefinition for attributes that are for your KeySchema of your table or your GSIs.

attributeDefinitions.add(new AttributeDefinition()
        .withAttributeName("ServiceID")
        .withAttributeType(ScalarAttributeType.N));

For your deprecation question, look at the Javadoc of Tables:

Deprecated.

Use TableUtils.

TablesUtils.waitUntilActive(dynamoDBClient, serviceRef);

Upvotes: 0

jarmod
jarmod

Reputation: 78563

You're misusing AttributeDefinition method chaining. You've mistakenly created one attribute definition whose name you keep changing (from "ServiceID" to "ServiceName" to "CreatedDateUTC" etc., and finally to "IsDeleted").

You need to provide an array or collection of attribute definitions. For example:

attributeDefinitions.add(
    new AttributeDefinition()
        .withAttributeName("ServiceID")
        .withAttributeType(ScalarAttributeType.N),
    new AttributeDefinition()
        .withAttributeName("ServiceName")
        .withAttributeType(ScalarAttributeType.S),
    ...
);

Upvotes: 4

Related Questions