Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DynamoDB and TableNameOverride with prefix

I am testing DynamoDB tables and want to set up different table names for prod and dev environment using the prefix "dev_" for development.

I made this test to print the table name:

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride;  

TableNameOverride tbl = new TableNameOverride("test").withTableNamePrefix("dev_");
System.out.println("name=" + tbl.getTableName() + "  prefix=" + tbl.getTableNamePrefix());

This prints: name=null prefix=dev_
How come the name here is null ?

TableNameOverride tbl = new TableNameOverride("test");//.withTableNamePrefix("dev_");
System.out.println("name=" + tbl.getTableName() + "  prefix=" + tbl.getTableNamePrefix());

This prints: name=test prefix=null

*How can I get the table name to be "dev_test" ?*

I want to use this later to get a "dev_" prefix for all tables in development mode like this:

DynamoDBTable annotation = (DynamoDBTable) myclass.getClass().getAnnotation(DynamoDBTable.class);  
TableNameOverride tbl = new TableNameOverride(annotation.tableName()).withTableNamePrefix("dev_");

Or is there another solution to separate between dev and prod tables?
I first thought of putting them in separate regions but not sure about this.

Could also use this:

mapper.save(ck, new DynamoDBMapperConfig(new TableNameOverride((isDev ? "dev_" : "") + annotation.tableName())));
like image 485
August Avatar asked Jan 02 '14 17:01

August


People also ask

What is TableNameOverride for?

TableNameOverride object—Instructs the mapper instance to ignore the table name specified by a class's DynamoDBTable annotation, and instead use a different table name that you supply. This is useful when partitioning your data into multiple tables at runtime.

What is binary type in DynamoDB?

Binary − They store any binary data, e.g., encrypted data, images, and compressed text. DynamoDB views its bytes as unsigned. Boolean − They store true or false. Null − They represent an unknown or undefined state.

What is DynamoDBMapper?

The DynamoDBMapper class is the entry point to Amazon DynamoDB. It provides access to a DynamoDB endpoint and enables you to access your data in various tables. It also enables you to perform various create, read, update, and delete (CRUD) operations on items, and run queries and scans against tables.

What type of data is stored in DynamoDB?

DynamoDB supports the following data types: Scalar – Number, String, Binary, Boolean, and Null. Multi-valued – String Set, Number Set, and Binary Set.


2 Answers

I've faced the same situation and struggled with myself a couple of days to get that working.

Just in case you're using DynamoDB + Spring here is what worked for me:

POJO class:

@DynamoDBTable(tableName = "APP-ACCESSKEY")
public class AccessKey {
    @NotBlank
    @Size(min = 1, max = 36)
    private String accessToken;

    @NotNull
    @Size(min = 3, max = 15)
    private String userName;

    private Date dateInsertion;


    public AccessKey() {

    // ... All POJO stuff
}

Spring configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <!-- Amazon Credentials -->
    <bean id="tableNameOverride" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix"/>
        <property name="arguments" value="DES-" />
    </bean>

    <bean id="dynamoDBMapperConfig" class="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig">
        <constructor-arg index="0" ref="tableNameOverride" />
    </bean>

    <bean id="BasicAWSCredentials" class="com.amazonaws.auth.BasicAWSCredentials">
         <constructor-arg index="0" value="${amazon.accessKey}" />
         <constructor-arg index="1" value="${amazon.secretKey}" />
    </bean>

    <bean id="amazonDynamoDBClient" class="com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient">
        <constructor-arg index="0" ref="BasicAWSCredentials" />
        <property name="endpoint" value="http://dynamodb.us-west-2.amazonaws.com" />
    </bean>

    <bean id="dynamoDBMapper" class="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper">
        <constructor-arg index="0" ref="amazonDynamoDBClient" />
        <constructor-arg index="1" ref="dynamoDBMapperConfig" />
    </bean>

</beans>

Explanation:

Taking into account that my AccessKey object point to APP-ACCESSKEY table on AWS DynamodDB then it turns out that after running this, your application will start to point to DES-APP-ACCESSKEY.

Hope it helps someone who's facing a situation akin to it

Cheers

like image 115
Paulo Miguel Almeida Avatar answered Oct 23 '22 11:10

Paulo Miguel Almeida


Same as Paolo Almeidas solution, but with Spring-Boot annotations. Just wanted to share it and maybe save someone time:

I have dynamodb tables for each namespace, e.g. myApp-dev-UserTable, myApp-prod-UserTable and I am using the EKS_NAMESPACE env variable, which in my case gets injected into the pods by kubernetes.

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;

@Configuration
@EnableDynamoDBRepositories(basePackages = "de.dynamodb")
public class DynamoDBConfig {

    @Value("${EKS_NAMESPACE}")
    String eksNamespace;

    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        return AmazonDynamoDBClientBuilder.standard()
            .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(
                    "dynamodb.eu-central-1.amazonaws.com", "eu-central-1"))
            .withCredentials(awsCredentials())
            .build();
    }

    @Bean
    public AWSCredentialsProvider awsCredentials() {
        return WebIdentityTokenCredentialsProvider.builder().build();
    }

    // Table Name override:

    @Bean
    public DynamoDBMapperConfig.TableNameOverride tableNameOverride() {
        return DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix("myApp-" + eksNamespace + "-");
    }

    @Bean
    public DynamoDBMapperConfig dynamoDBMapperConfig() {
        return DynamoDBMapperConfig.builder().withTableNameOverride(tableNameOverride()).build();
    }

    @Bean
    // Marked as primary bean to override default bean.
    @Primary
    public DynamoDBMapper dynamoDBMapper() {
        return new DynamoDBMapper(amazonDynamoDB(), dynamoDBMapperConfig());
    }
}

With a table like this:

@Data
@DynamoDBTable(tableName = "UserTable")
public class User {

        @DynamoDBHashKey
        private String userId;

        @DynamoDBAttribute
        private String foo;

        @DynamoDBAttribute
        private String bar;
}
like image 34
Jonas Eicher Avatar answered Oct 23 '22 11:10

Jonas Eicher