Managing Configuration effectively in Spring Boot

Kasun Sameera
FAUN — Developer Community 🐾
6 min readAug 31, 2020

--

Bugatti Chiron Engine and Gearbox

I started to write this story almost a year ago, but I never got a chance or interest to complete it. But recently, I was assigned to create a simple framework for our system; there, I had to use the AWS parameter store to manage configuration, which made this more interesting.

I’m assuming that you guys have some knowledge in Spring boot, and I’m not going to talk about all the small details. I’m going to focus on how configurations can be managed effectively in spring boot applications.

Spring gives a few ways to manage configurations.

  • YAML or properties file
  • Command-line arguments.
  • Environment variables

YAML or Properties file

This is the most common way most of us manage configurations. Each application has application.yml or application.properties file in the resource folder. I always prefer YAML files over the properties file because it is more structured and readable. Below is a typical application.yml configuration file.

A application.yml file

As a best practice put all the common configurations in the application.yml file like “application name, queue name, topic name, port, context path, Jackson date-format”. Basically whatever the configurations that are not going to change on the environment that the application is running on can put into application.yml file.

Command-line arguments

Command-line arguments are the best way to pass a small number of configurations at runtime. A command-line argument is an ideal way to activate profiles (will talk about later). Below is how you use command-line arguments,

java -jar spring-boot-demo.jar --some.config.variable=some_value

some.config.variable” is the configuration variable and “some_value” is the value we passed to it. Command-line arguments take precedence over what defined in the config files. You can override values defined in the config files using command-line arguments. But I use this only to activate profiles because it is challenging to read the start command of the application when we have a massive number of command-line arguments.

Environment variables

The environment variable is the most preferred way to pass configuration values.

When it comes to microservices, we say that the environment should configure the application. That means the environment should have all the necessary configurations values needed for the applications to run.

Spring boot has a built-in mechanism to read the environment variable. For example, if we have a variable called “demo.application.variable” then spring will search for an environment variable called “DEMO_APPLICATION_VARIABLE”.

Don’t create unnecessary configurations.

Create configurations if it is necessary. Unnecessary configurations make it difficult to manage the application. For example, you can define the JDBC connection URL using multiple variables like below,

Example for unnecessary configurations

DB host is different from one environment to another, port and schema may change. Here you can pass values to these variables using environment variables, command-line argument, or you can define variables and assign values in the config repo(using config server). But one thing to understand is that the complete URL is different from one environment to another. So there is no point of creating these variables instead of this we can create one variable for JDBC URL or else you directly pass the JDBC URL as an environment variable like below,

export SPRING_DATASOURCE_URL=”jdbc:postgresql://hostname:6606/demo”

Another important thing is to maintain consistency between environments, and this helps to reduce configurations. For example, if our application uses RabbitMQ, then we can keep the same queue name in all the environments. Still, we can define the queue name in the application.yml configuration file, but you don’t have to change it for each environment. The only thing we are going to change is the RabbitMQ connection URL and credentials. The same thing applies for Kafka topics.

Try to reduce the differences between each environment, and this will reduce the number of configuration variables that we are going to use in our applications.

Environment Specific configurations

The main advantage of the configuration variable is we can run the same build in different environments just by changing the value that we pass to the variable; this gives us the option to do the build promotion. Spring provides a few ways to manage environment-specific configurations. Let’s look at these.

Profiles

Spring provides the concept of profiles. For each profile, we can create a configuration file and define profile-specific values for each configuration variable. There is a convention to create these configuration files, which is application-profile_name.yml. If you are going to create a profile called dev, then you have to create a file called application-dev.yml in the resource folder. There is a configuration to activate these profiles, which is “spring.profiles.active”. We can use a command-line argument to activate the profile. Never put common configurations like “spring.application.name”, RabbitMQ queue name, Kafka topic name into profiles. The disadvantage of putting profiles in the resource folder is that everyone can see configurations for all the environments, including prod and if we change one value in the profile then we will have to rebuild our application.

Config Server

Config server is an excellent way to externalize configurations. We can put our profiles outside of the application code base and ask our application to get configurations related to the active profile from the config server. Most of the time, we use the git repository to host our profiles. Important of this is we have to make sure that the Config server is up and running all the time because if the Config server is not responsive when we are deploying our application, then our application will not start correctly.

AWS Parameter store

AWS Parameter Store is the best way to externalize configurations if we are running our application in AWS. Using “spring-cloud-starter-aws-parameter-store-config” starter, we can connect with the AWS parameter store.

K8S Config Maps

Config Map is the preferred way to manage configuration when running application in K8S. If we established configurations correctly, then we can re-use the same Deployment for all the environments just changing the namespace because the config map is the one that is going to change from one namespace to another. Below is a sample config maps defined for two different namespaces.

K8S ConfigMap

And this the corresponding deployment YAML.

Deployment YAML

As you can see we can use the same deployment YAML just changing the namespace. With this, we can run our application without activating a specific profile. We are just letting the environment to configure the application.

Conclusion

With configurations, we can develop applications that can run on different environments without changing the code. Spring Boot has out of the box support for this. But we have to use configurations more effectively. Adding unnecessary configuration makes it hard to maintain the application. Sometimes I use the same hostname for DB or Kafka by adding host entry to the hosts file just to reduce configurations and give it to the environment to manage it.

Join FAUN!

Subscribe to FAUN topics and get your weekly dose of the must-read tech stories, news, and tutorials 🗞️

Follow us on Twitter 🐦 and Facebook 👥 and Instagram 📷 and join our Facebook and Linkedin Groups 💬

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇

--

--