I have a long running AWS Java SDK DynamoDB application which behaves normally when I start it up. However, after some number of hours (around 12), I start receiving the same Exception
over and over again with ANY call to the DynamoDB API. If I restart the server, the Exception
disappears...only to reappear again later.
The exact ExpiredTokenException
error text is:
The security token included in the request is expired (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ExpiredTokenException; Request ID: DEMTN0Q5BMPH5IQD9TUQMNO5SFVV4KQNSO5AEMVJF66Q9ASUAAJG)
The most likely cause of a failed read or a failed write is throttling. For BatchGetItem , one or more of the tables in the batch request does not have enough provisioned read capacity to support the operation. For BatchWriteItem , one or more of the tables does not have enough provisioned write capacity.
You must refresh the credentials before they expire. Another reason for expiration is using the incorrect time. A consistent and accurate time reference is crucial for many server tasks and processes. If your instance's date and time aren't set correctly, the AWS credentials are rejected.
To retrieve a single item, you can use the getItem method. Follow these steps: Create an instance of the DynamoDB class. Create an instance of the TableKeysAndAttributes class that describes a list of primary key values to retrieve from a table.
Summary:
Pass an instance of AWSCredentialsProvider
(as opposed to AWSCredentials
) to AmazonDynamoDBClient
's constructor as this enables automatic refreshing of expired AWSCredentials
(if the particular AWSCredentialsProvider
has implemented the refresh functionality...which is the case with all the standard AWS provided ones).
Details:
To resolve the AWS Java SDK DynamoDB related ExpiredTokenException which starts with the prefix "The security token included in the request is expired (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ExpiredTokenException; Request ID: ...", you must alter your code to provide an instance of AWSCredentialsProvider
(and stop using an instance of AWSCredentials
- i.e. sans the "Provider" suffix) to the AmazonDynamoDBClient
's constructor. By handing the AmazonDynamoDBClient
's constructor an instance of AWSCredentialsProvider
, you give it the ability to "automatically refresh the credentials" if/when the AWSCredentials
expire (which I found in this AWS forum thread which requires an account to access).
To provide an explicit example in code, here's a generalization of what the code is producing the ExpiredTokenException
:
AWSCredentialsProvider aWSCredentialsProvider =
new SystemPropertiesCredentialsProvider();
//the above line may be substituted for any valid
//*Provider implementation
AWSCredentials aWSCredentials =
aWSCredentialsProvider.getCredentials();
AmazonDynamoDBClient amazonDynamoDBClient =
new AmazonDynamoDBClient(aWSCredentials);
...
amazonDynamoDBClient.listTables();
//the above line is where the ExpiredTokenException is eventually thrown
And here is a generalization of the code eliminating the ExpiredTokenException
:
AWSCredentialsProvider aWSCredentialsProvider =
new SystemPropertiesCredentialsProvider();
//substitute the above line for any valid *Provider implementation
AmazonDynamoDBClient amazonDynamoDBClient =
new AmazonDynamoDBClient(aWSCredentialsProvider);
//the above line is now passing an instance of AWSCredentialsProvider
//as opposed to AWSCredentials
...
amazonDynamoDBClient.listTables();
//the above line is now enabled, via the AWSCredentialsProvider, to
//automatically refresh the AWSCredentials if/when they have expired
Given how much I climbed all over the AWS Java SDK Javadocs and their provided examples (upon which I based most of my own code), I didn't once notice this specific nuance called out. Hence, the very detailed answer I'm providing for those who come after me (which likely will include myself, LOL).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With