Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set tableName dynamically using environment variable in spring boot?

I am using AWS ECS to host my application and using DynamoDB for all database operations. So I'll have same database with different table names for different environments. Such as "dev_users" (for Dev env), "test_users" (for Test env), etc.. (This is how our company uses same Dynamo account for different environments)

So I would like to change the "tableName" of the model class using the environment variable passed through "AWS ECS task definition" environment parameters.

For Example.

My Model Class is:

@DynamoDBTable(tableName = "dev_users")
public class User {

Now I need to replace the "dev" with "test" when I deploy my container in test environment. I know I can use

@Value("${DOCKER_ENV:dev}")

to access environment variables. But I'm not sure how to use variables outside the class. Is there any way that I can use the docker env variable to select my table prefix?

My Intent is to use like this:

enter image description here

I know this not possible like this. But is there any other way or work around for this?

Edit 1:

I am working on the Rahul's answer and facing some issues. Before writing the issues, I'll explain the process I followed.

Process:

  1. I have created the beans in my config class (com.myapp.users.config).
  2. As I don't have repositories, I have given my Model class package name as "basePackage" path. (Please check the image)

enter image description here

  • For 1) I have replaced the "table name over-rider bean injection" to avoid the error.
  • For 2) I printed the name that is passing on to this method. But it is Null. So checking all the possible ways to pass the value here.

Check the image for error:

enter image description here

I haven't changed anything in my user model class as beans will replace the name of the DynamoDBTable when the beans got executed. But the table name over riding is happening. Data is pulling from the table name given at the Model Class level only.

What I am missing here?

like image 255
Kiran Avatar asked Jul 10 '18 10:07

Kiran


2 Answers

I am able to achieve table names prefixed with active profile name.

First added TableNameResolver class as below,

@Component
public class TableNameResolver extends DynamoDBMapperConfig.DefaultTableNameResolver {

private String envProfile;

public TableNameResolver() {}

public TableNameResolver(String envProfile) {
    this.envProfile=envProfile;
}

 @Override
 public String getTableName(Class<?> clazz, DynamoDBMapperConfig config) {
  String stageName = envProfile.concat("_");
  String rawTableName = super.getTableName(clazz, config);
  return stageName.concat(rawTableName);
 }
}

Then i setup DynamoDBMapper bean as below,

@Bean
@Primary
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {

    DynamoDBMapper mapper = new DynamoDBMapper(amazonDynamoDB,new DynamoDBMapperConfig.Builder().withTableNameResolver(new TableNameResolver(envProfile)).build());
     return mapper;
}

Added variable envProfile which is an active profile property value accessed from application.properties file.

@Value("${spring.profiles.active}")
private String envProfile;
like image 104
Nilesh Sangvikar Avatar answered Sep 17 '22 09:09

Nilesh Sangvikar


The table names can be altered via an altered DynamoDBMapperConfig bean.

For your case where you have to Prefix each table with a literal, you can add the bean as such. Here the prefix can be the environment name in your case.

 @Bean
public TableNameOverride tableNameOverrider() {
    String prefix = ... // Use @Value to inject values via Spring or use any logic to define the table prefix
    return TableNameOverride.withTableNamePrefix(prefix);
}

For more details check out the complete details here: https://github.com/derjust/spring-data-dynamodb/wiki/Alter-table-name-during-runtime

like image 43
Rahul Babu Avatar answered Sep 21 '22 09:09

Rahul Babu