Search code examples
javaspring-bootamazon-dynamodbaws-java-sdk-2.xaws-java-sdk-dynamodb

How to pass aws dynamodb table name dynamically using @DynamoDbTable annotation


I have created a java service to get the details from dynamodb it is working fine but my challenge is i hardcoded the table name to the class file @DynamoDbTable annotation in order to work with different environments i feel it is not the right way. I have given my code below could someone help me to resolve the issue.

Code sample

public class DynamodbService {

    private DynamoDB client;
    private DynamoDBMapper objectMapper;

    /**
     * 
     * @param client
     * @param objectMapper
     */
    @Autowired
    public DynamodbService(DynamoDB client, DynamoDBMapper objectMapper) {
        this.client = client;
        this.objectMapper = objectMapper;
    }


    public List<Dynamodb> findAll() throws Exception {
        DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig.Builder()
                .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(""))
                .build();
        DynamoDBMapper mapper = new DynamoDBMapper(client, mapperConfig);

        DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();

        List<Dynamodb> scanResult = objectMapper.scan(Dynamodb.class, scanExpression);
        return scanResult;
    }

}

My DynamoDB config

@Configuration
public class DynamoDBconfig {
    /**
     * 
     */
    @Value("${amazon.dynamodb.accesskey}")
    private String awsAccessKey;
    /**
     * 
     */
    @Value("${amazon.dynamodb.secretkey}")
    private String awsSecretKey;

    
    @Bean
    public AWSCredentials amazonAWSCredentials() {
        return new BasicAWSCredentials(aes.getDecryptedvalue(awsAccessKey), aes.getDecryptedvalue(awsSecretKey));
    }

    /**
     * 
     * @return
     */
    @Bean
    public DynamoDBMapperConfig dynamoDBMapperConfig() {
        return DynamoDBMapperConfig.DEFAULT;
    }

    /**
     * 
     * @param amazonDynamoDB
     * @param config
     * @return
     */
    @Bean
    public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig config) {
        return new DynamoDBMapper(amazonDynamoDB, config);
    }

    /**
     * 
     * @return
     */
    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        return AmazonDynamoDBClientBuilder.standard().withCredentials(amazonAWSCredentialsProvider())
                .withRegion(Regions.US_EAST_2).build();
    }

    /**
     * 
     * @return
     */
    @Bean
    public DynamoDB dynamoDB() {
        return new DynamoDB(amazonDynamoDB());
    }

    /**
     * 
     * @return
     */
    public AWSCredentialsProvider amazonAWSCredentialsProvider() {
        return new AWSStaticCredentialsProvider(amazonAWSCredentials());
    }

}

ERROR in my dynamodb service

The constructor DynamoDBMapper(DynamoDB, DynamoDBMapperConfig) is undefined

I am unable find out what is the issue. If i use table name in class file it's working fine if i try to replace the table name using code it ends up with error.


Solution

  • DynamoDBMapper expects any implementation of AmazonDynamoDB but not DynamoDB class.

    public DynamoDBMapper(
                final AmazonDynamoDB dynamoDB,
                final DynamoDBMapperConfig config) {
    
    

    You need to inject only the DynamoDBMapper in your service.

    @Bean
    public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
      DynamoDBMapperConfig config = new DynamoDBMapperConfig.Builder().withTableNameOverride(TableNameOverride.withTableNameReplacement(tableName))
            .build();
       return new DynamoDBMapper(amazonDynamoDB, config);
    }
    

    Other option could be using com.amazonaws.services.dynamodbv2.document.DynamoDB class but there you could not use DynamoDBScanExpression and you need to rewrite your code.

    
    String desiredTabledName = "table-name";
    Table table = dynamoDB.getTable(desiredTabledName);
    
    
    You have multiple options.
    
     - table.scan() and table query.
     - Index index = table.getIndex(indexName);
       index.scan() or index.query()
     - You could pass `QuerySpec` and `ScanSpec` to all above.