I'm trying to create a DynamoDB table programmatically in Kotlin using a CreateTableRequest
:
val createTableRequest: CreateTableRequest = CreateTableRequest.builder()
.tableName(tableName)
.billingMode("PAY_PER_REQUEST")
.attributeDefinitions(attributeDefinitions)
.keySchema(keySchema)
.streamSpecification(streamSpecification)
.globalSecondaryIndexes(globalSecondaryIndexes)
.tags(tags)
.build()
dynamoDbClient.createTable(createTableRequest)
I want to set the TTL and Point-in-time recovery (PITR) settings to true, however it doesn't seem like CreateTableRequest
has an option for enabling the TTL and Point-in-time recovery.
I know there is an UpdateTimeToLiveRequest
and an UpdateContinuousBackupsRequest
, however when I try to run those right after creating the table, it throws an error since the table is still being created.
// Enable TTL
val updateTimeToLiveRequest = UpdateTimeToLiveRequest.builder()
.tableName(tableName)
.timeToLiveSpecification(TimeToLiveSpecification.builder().enabled(true).attributeName("ttl").build())
.build()
dynamoDbClient.updateTimeToLive(updateTimeToLiveRequest)
software.amazon.awssdk.services.dynamodb.model.ResourceInUseException: Attempt to change a resource which is still in use: Table table-test is being created (Service: DynamoDb, Status Code: 400, Request ID: H3RKQE7OKQHGE1Q3E2J8SFKRCVVV4KQNSO5AEMVJF66Q9ASUAAJG)
Is there a way to create a DynamoDB table with the TTL and PITR settings already enabled?
To build an Amazon DynamoDB table in Kotlin, use the AWS SDK for Kotlin as opposed to the AWS SDK for Java. When you use the AWS SDK for Kotlin, you get benefits like Kotlin Coroutines functionality. For more information about Coroutines in the SDK for Kotlin, see this topic in the AWS SDK for Kotlin DEV Guide:
Now when you create a table using the Kotlin SDK, you can use Waiters. WHen you use Waiters, the code does not proceed until the table is created. To create a table using the Kotlin SDK, use this Kotlin code:
// snippet-sourcedescription:[CreateTable.kt demonstrates how to create an Amazon DynamoDB table using a waiter.]
// snippet-keyword:[AWS SDK for Kotlin]
// snippet-service:[Amazon DynamoDB]
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package com.kotlin.dynamodb
// snippet-start:[dynamodb.kotlin.create_table.import]
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
import aws.sdk.kotlin.services.dynamodb.model.AttributeDefinition
import aws.sdk.kotlin.services.dynamodb.model.CreateTableRequest
import aws.sdk.kotlin.services.dynamodb.model.KeySchemaElement
import aws.sdk.kotlin.services.dynamodb.model.KeyType
import aws.sdk.kotlin.services.dynamodb.model.ProvisionedThroughput
import aws.sdk.kotlin.services.dynamodb.model.ScalarAttributeType
import aws.sdk.kotlin.services.dynamodb.waiters.waitUntilTableExists
import kotlin.system.exitProcess
// snippet-end:[dynamodb.kotlin.create_table.import]
/**
Before running this Kotlin code example, set up your development environment,
including your credentials.
For more information, see the following documentation topic:
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html
*/
suspend fun main(args: Array<String>) {
val usage = """
Usage:
<tableName> <key>
Where:
tableName - The Amazon DynamoDB table to create (for example, Music3).
key - The key for the Amazon DynamoDB table (for example, Artist).
"""
if (args.size != 2) {
println(usage)
exitProcess(0)
}
val tableName = args[0]
val key = args[1]
println("Creating an Amazon DynamoDB table named $tableName with a key named $key")
val tableArn = createNewTable(tableName, key)
println("The new table ARN is $tableArn")
}
// snippet-start:[dynamodb.kotlin.create_table.main]
suspend fun createNewTable(tableNameVal: String, key: String): String? {
val attDef = AttributeDefinition {
attributeName = key
attributeType = ScalarAttributeType.S
}
val keySchemaVal = KeySchemaElement {
attributeName = key
keyType = KeyType.Hash
}
val provisionedVal = ProvisionedThroughput {
readCapacityUnits = 10
writeCapacityUnits = 10
}
val request = CreateTableRequest {
attributeDefinitions = listOf(attDef)
keySchema = listOf(keySchemaVal)
provisionedThroughput = provisionedVal
tableName = tableNameVal
}
DynamoDbClient { region = "us-east-1" }.use { ddb ->
var tableArn: String
val response = ddb.createTable(request)
ddb.waitUntilTableExists { // suspend call
tableName = tableNameVal
}
tableArn = response.tableDescription!!.tableArn.toString()
println("Table $tableArn is ready")
return tableArn
}
}
// snippet-end:[dynamodb.kotlin.create_table.main]'
The Kotlin SDK supports updateTimeToLive.
To learn how to use the AWS SDK for Kotlin, refer to the DEV Guide.
Using Waiter with AWS SDK for Java v2
If for some reason, you need to continue to use Java SDK, then your issue is you are not using Waiters. The solution is to use Waiters before trying to modify the table with other methods, as shown in this Java example.
//snippet-sourcedescription:[CreateTable.java demonstrates how to create an Amazon DynamoDB table by using a waiter.]
//snippet-keyword:[SDK for Java v2]
//snippet-service:[Amazon DynamoDB]
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package com.example.dynamodb;
// snippet-start:[dynamodb.java2.create_table.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
// snippet-end:[dynamodb.java2.create_table.import]
/**
* Before running this Java V2 code example, set up your development environment, including your credentials.
*
* For more information, see the following documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class CreateTable {
public static void main(String[] args) {
final String usage = "\n" +
"Usage:\n" +
" <tableName> <key>\n\n" +
"Where:\n" +
" tableName - The Amazon DynamoDB table to create (for example, Music3).\n\n" +
" key - The key for the Amazon DynamoDB table (for example, Artist).\n" ;
if (args.length != 2) {
System.out.println(usage);
System.exit(1);
}
String tableName = args[0];
String key = args[1];
System.out.println("Creating an Amazon DynamoDB table "+tableName +" with a simple primary key: " +key );
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
Region region = Region.US_EAST_1;
DynamoDbClient ddb = DynamoDbClient.builder()
.credentialsProvider(credentialsProvider)
.region(region)
.build();
String result = createTable(ddb, tableName, key);
System.out.println("New table is "+result);
ddb.close();
}
// snippet-start:[dynamodb.java2.create_table.main]
public static String createTable(DynamoDbClient ddb, String tableName, String key) {
DynamoDbWaiter dbWaiter = ddb.waiter();
CreateTableRequest request = CreateTableRequest.builder()
.attributeDefinitions(AttributeDefinition.builder()
.attributeName(key)
.attributeType(ScalarAttributeType.S)
.build())
.keySchema(KeySchemaElement.builder()
.attributeName(key)
.keyType(KeyType.HASH)
.build())
.provisionedThroughput(ProvisionedThroughput.builder()
.readCapacityUnits(new Long(10))
.writeCapacityUnits(new Long(10))
.build())
.tableName(tableName)
.build();
String newTable ="";
try {
CreateTableResponse response = ddb.createTable(request);
DescribeTableRequest tableRequest = DescribeTableRequest.builder()
.tableName(tableName)
.build();
// Wait until the Amazon DynamoDB table is created.
WaiterResponse<DescribeTableResponse> waiterResponse = dbWaiter.waitUntilTableExists(tableRequest);
waiterResponse.matched().response().ifPresent(System.out::println);
newTable = response.tableDescription().tableName();
return newTable;
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
System.exit(1);
}
return "";
}
// snippet-end:[dynamodb.java2.create_table.main]
}
Both of these AWS code examples to create an Amazon DynamoDB table can be found here in the AWS Code Library.