Configuration Management in Spring Boot Microservices using Spring Cloud Config

Saquib Khan
4 min readMay 19, 2024

In the world of microservices, configuration management is a critical aspect that can make or break your application’s scalability and maintainability. This article delves into the challenges of configuration management in microservices, explores how configurations work in Spring Boot, and demonstrates advanced techniques using Spring Cloud Config.

Introduction to Configuration Management Challenges in Microservices

Microservices architecture introduces several configuration management challenges:

  1. Configuration Injection: Injecting configurations or properties that microservices need during startup.
  2. Configuration Separation: Separating configurations from microservices so the same Docker image can be deployed in multiple environments.
  3. Centralized Configuration Maintenance: Maintaining configurations in a centralized repository with versioning.

Injecting Configurations in Spring Boot

Spring Boot provides multiple ways to manage configurations:

  1. @Value Annotation: Directly inject property values into beans.
  2. Environment Interface: Programmatically access properties.
  3. @ConfigurationProperties: Bind external properties to a POJO.

Using @Value Annotation

The @Value annotation is a straightforward way to inject property values into your Spring Boot application.

@Value("${property.name}")
private String propertyValue;

This approach is suitable for injecting individual properties into specific fields.

Using Environment Interface

The Environment interface provides methods to access properties from the application's environment.

@Autowired
private Environment environment;

public void getProperty() {
String propertyValue = environment.getProperty("property.name");
}

This approach allows accessing properties programmatically, offering more flexibility.

Using @ConfigurationProperties

The @ConfigurationProperties annotation enables binding entire groups of properties to a bean.

@ConfigurationProperties("prefix")
public class MyConfig {
private String property;
// getters and setters
}

This approach is recommended for binding related properties to a single configuration class, avoiding hardcoding property keys.

Spring Boot Profiles

Spring Boot profiles allow you to define different configurations for different environments (e.g., dev, test, prod).

# application-dev.properties
app.name=MyApp (Dev)
# application-prod.properties
app.name=MyApp (Prod)

Activate profiles using command-line arguments, JVM options, or environment variables:

java -jar myapp.jar --spring.profiles.active=dev

Externalizing Configurations

Externalizing configurations is crucial for maintaining a single codebase across different environments. Spring Boot supports several external configuration sources:

  1. Command-Line Arguments
  2. JVM Options
  3. Environment Variables
  4. Property Files

Externalizing Configurations Using Command-Line, JVM & Environment Options

You can pass configurations through command-line arguments:

java -jar myapp.jar --app.name=MyApp

Or through JVM options:

java -Dapp.name=MyApp -jar myapp.jar

Or set environment variables:

export APP_NAME=MyApp
java -jar myapp.jar

Drawbacks of Externalized Configurations Using Spring Boot Alone

While Spring Boot’s native externalized configuration is powerful, it has some limitations:

  1. Lack of Centralized Management: Managing configurations across multiple microservices can become cumbersome.
  2. Versioning: It lacks built-in support for versioning configurations.
  3. Runtime Refresh: Updating configurations at runtime without restarting the application is challenging.

Introduction to Spring Cloud Config

Spring Cloud Config addresses these limitations by providing server and client-side support for externalized configuration in a distributed system.

Building Config Server Using Spring Cloud Config

To set up a Spring Cloud Config server, you need to create a new Spring Boot application and add the necessary dependencies:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>

Enable the Config Server:

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}

Reading Configurations from the Classpath Location of Config Server

The Config Server can read configurations from various sources, including the classpath:

# application.properties
spring.profiles.active=native
spring.cloud.config.server.native.search-locations=classpath:/configs

Updating Microservices to Read Properties from Config Server

Update your microservices to read configurations from the Config Server:

# bootstrap.yml
spring:
application:
name: myapp
cloud:
config:
uri: http://localhost:8888

Reading Configurations from a GitHub Repository

The Config Server can also read configurations from a GitHub repository:

# application.properties
spring.profiles.active=git
spring.cloud.config.server.git.uri=https://github.com/your-repo/config-repo

Encryption & Decryption of Properties Inside Config Server

Spring Cloud Config supports encryption and decryption of sensitive properties:

  1. Add the encryption key to the Config Server:
# application.properties
encrypt.key=my-secret-key
  1. Encrypt properties using the /encrypt endpoint.
  2. Decrypt properties at runtime using the /decrypt endpoint.

Refresh Configurations at Runtime

Spring Cloud provides mechanisms to refresh configurations at runtime without restarting the application.

Using Refresh Actuator Path

Add the spring-boot-starter-actuator dependency and enable the refresh endpoint:

# application.properties
management.endpoints.web.exposure.include=refresh

Trigger a refresh by invoking the /actuator/refresh endpoint.

Using Spring Cloud Bus

Spring Cloud Bus links multiple applications with a message broker, enabling configuration updates across all instances.

Add the necessary dependencies:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

Trigger a refresh using the Spring Cloud Bus.

Docker and Configuration Management

To manage configurations in Dockerized microservices, update the Dockerfile and docker-compose.yml files to include environment-specific configurations.

Updating Docker Compose Files

# docker-compose.yml
version: '3.8'
services:
config-server:
image: config-server
ports:
- "8888:8888"
environment:
- SPRING_PROFILES_ACTIVE=git

Liveness and Readiness Probes

Liveness and readiness probes ensure that your microservices are running correctly and are ready to handle traffic.

# docker-compose.yml
services:
myapp:
image: myapp
ports:
- "8080:8080"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3

End-to-End Testing Using Docker Compose

Prepare Docker Compose files for different environments (e.g., QA, prod) to test your configurations end-to-end.

Conclusion

Effective configuration management is crucial for the success of microservices architecture. Spring Boot provides robust solutions for handling configurations, and Spring Cloud Config enhances these capabilities by enabling centralized, versioned, and dynamically refreshable configurations. By leveraging these tools, you can ensure that your microservices are scalable, maintainable, and adaptable to changing environments.

--

--