Search code examples
javaamazon-web-servicesamazon-dynamodbcruddynamodb-mapper

DynamoDB not fetching all entries in case of two autogenerated attributes


I have a crud application which uses DynamoDb, it has a model class containing two autogenerated attributes, one for primary key and another for timestamp. I am using scan() function of DynamoDbMapper to getAll entries from the db but getting below error.

com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: expected N in value {S: 2022-12-09T09:23:52.737Z,}

Employee

@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamoDBTable(tableName = "employee")
public class Employee {

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String employeeId;

    @DynamoDBAttribute
    private String firstName;

    @DynamoDBAttribute
    private String lastName;

    @DynamoDBAttribute
    private String email;

    @DynamoDBAttribute
    private Department department;

    @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS)
    private Long timestamp;
}

DynamoDbConfiguration

package com.dailycodebuffer.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DynamoDbConfiguration {

    @Bean
    public DynamoDBMapper dynamoDBMapper() {
        return new DynamoDBMapper(buildAmazonDynamoDB());
    }

    private AmazonDynamoDB buildAmazonDynamoDB() {
        return AmazonDynamoDBClientBuilder
                .standard()
                .withEndpointConfiguration(
                        new AwsClientBuilder.EndpointConfiguration(
                                "endpoint",
                                "region"
                        )
                )
                .withCredentials(
                        new AWSStaticCredentialsProvider(
                                new BasicAWSCredentials(
                                        "access_key",
                                        "secret_key"
                                )
                        )
                )
                .build();
    }

}

Method to getAll the entries

public List<Employee> getAllEmployees() {
        return dynamoDBMapper.scan(Employee.class, new DynamoDBScanExpression());
    }

DynamoDb dependency :

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.11.857</version>
        </dependency>

Note: If i remove the timestamp, getAll works perfectly fine.

I am new to DynamoDb, any help would be appreciated.


Solution

  • I am going to take a random guess at this one, but I believe the issue is that you have an item (or several) which have stored a value for timestamp as a String, perhaps you inserted them into the table manually?

    Now when you read back those items in the Scan, DynamoDB Mapper is trying to marshall against your class, which states that timestamp should be a Long, however, the item is showing a String.

    My suggestion is to take a look through your table to see if such an item exists, which is causing your Scan to fail. Another quick way to check is my setting Limit on the Scan to 1, and see if there are no exceptions (hopefully the first item isn't the broken one :-/ )