DynamoDB and TableNameOverride with prefix
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
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;
}
withTableNamePrefix
is a static method. So this line is creating a new instance of TableNameOverride
with the String "test", and then throwing that instance away by using it to call the static withTableNamePrefix
method:
TableNameOverride tbl = new TableNameOverride("test").withTableNamePrefix("dev_");
To answer the deeper question of separating test from prod, I would recommend having 2 separate AWS Accounts entirely, one for dev and one for prod. This is the only way you can:
- See billing separately
- Ensure you never leak data between prod and test systems
- Have high scaling on a dev table prevent you from scaling a prod table higher