DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • CMDB vs. IT Asset Management: Why Confusing Them Can Break Your IT Operations
  • Robust Integration Solutions With Apache Camel and Spring Boot
  • Effective Exception Handling in Microservices Integration
  • Integrate Spring With Open AI

Trending

  • Docker Hardened Images Are Free Now — Here's What You Still Need to Build
  • Why SAP S/4HANA Landscape Design Impacts Cloud TCO More Than Compute Costs
  • Building Production-Grade GenAI on GCP with Vertex AI Agent Builder
  • How to Prevent Data Loss in C#
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Centralized Configuration Management With Consul

Centralized Configuration Management With Consul

In this article, learn how to set up centralized configuration in Spring Boot using HashiCorp Consul for dynamic, environment-specific settings management.

By 
Vishnu Viswambharan user avatar
Vishnu Viswambharan
·
Oct. 15, 25 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
2.8K Views

Join the DZone community and get the full member experience.

Join For Free

What Is Centralized Configuration?

In modern microservice architectures, multiple applications often share common configuration data (e.g., database settings). These might be multiple instances of the same service or entirely different services. Regardless of the service behavior, instead of maintaining configuration at the service level, we can centralize it in one place and distribute it across all services. HashiCorp Consul provides a solution for this.Consul config distribution

Consul config distribution

The beauty of this approach is that configuration changes can be made on the fly and will immediately reflect in the services.

Now, let's check out how this works in Spring Boot applications.

Benefits

  1. Centralized configuration management for all services
  2. Service-specific configurations for multiple instances
  3. Global configurations shared across all applications
  4. Environment-specific configuration support (e.g., dev, qa, prod)
  5. Ability to modify configurations on the fly with immediate effect

 Libraries

  • Consul Server
  • Spring Boot
  • Spring Cloud Gateway
  • Spring Cloud Consul
  • Spring Boot Actuator

Setting Up

The architecture includes two components.

  1. Consul server
  2. User application (a consumer application)

1. Consul

We need to download and configure the Consul service from the official HashiCorp Consul website. For development purposes on Windows, you can start Consul by running below command in PowerShell.

PowerShell
 
consul agent -dev


Once it has successfully started, you can see the dashboard in the browser using the following URL. 8500 is the default port of Consul.

Consul Dashboard

Let's add some configuration to Consul through the dashboard. We can add it through the CLI as well. Here we are adding it as a key value pair, where Key will be the path and Value will have configuration. There is an option to add Key/Value data, located on the left side of the dashboard.

List of added key/values

List of added key/values

Add new key/value

We are adding three sets of Key/Value data to Consul.

1. Key: config/user-app,dev/app.properties 

Value:

Shell
 
server.port=3602
sample.config.1=Test data 111
sample.config.2=Test data 222
sample.config.3=Test data 333
sample.config.4=Test data 444
message=Dev configuration of user-app !!


2. Key: config/user-app/app.properties

Value:

Shell
 
server.port=3601
sample.config.1=Test data 11
sample.config.2=Test data 22
sample.config.3=Test data 33
sample.config.4=Test data 44
message=Default configuration of user-app !!


3. Key: config/application/app.properties

Value:

Shell
 
server.port=3600
sample.config.1=Test data 1
sample.config.2=Test data 2
sample.config.3=Test data 3
sample.config.4=Test data 4
message=Common config for all apps !!


Please note that all of the above data is added only for demonstration purposes.

Working

  • The Logic is very simple, similar to the legacy property (or YAML) configuration of a Spring Boot application.
  • The first one config/user-app,dev/app.properties is specifically created for development env of user-app named services.
  • The second one config/user-app/app.properties is created for saving common configurations for user-app named services.
  • And the last one config/application/app.properties is the kind of common configuration which can be served across all services.

2. User Application (A Consumer Application)

We have to create a simple Spring Boot web service application. Here, it will consume the configuration those are configured in consul.

Maven Configuration

We need to add a dependency below to enable the communication and share the configuration between consul and User application .

XML
 
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>


Application Property File

Properties files
 
#Application name
spring.application.name=user-app

# Informing the spring boot application to import the configurations from consul
spring.config.import=consul:
logback.log.file.path=./logs/service

# To enable extra logs
logging.level.org.springframework.cloud.consul.config=DEBUG

# Consul Configuration
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

# Enabling Consul configuration management
spring.cloud.consul.config.enabled=true

# Declaring the config data format (propreties or yaml)
spring.cloud.consul.config.format=properties

# Declaring the prefix of all config key
spring.cloud.consul.config.prefix=config

# Declaring the data file name which contains configuration
spring.cloud.consul.config.data-key=app.properties

# Declaring the default config path
spring.cloud.consul.config.default-context=application

# It will be used for separating the keyword of profile in consul (Eg :config/user-app,dev/app.properties )
spring.cloud.consul.config.profile-separator=,
    
# Informing spring boot to load config from dev env
spring.profiles.active=dev


  • Here in the above configuration, The consul will look for the key config/user-app,dev/app.properties and return it's Value to spring boot application. Why because,
  • The prefix of Key mentioned as spring.cloud.consul.config.prefix=config
  • The application name is configured as spring.application.name=user-app
  • The profile separator mentioned as spring.cloud.consul.config.profile-separator=,
  • The active profile configured as spring.profiles.active=dev
  • And finally, the data file name mentioned as spring.cloud.consul.config.data-key=app.properties
  • If any of the expected properties are not found in config/user-app,dev/app.properties, the system will then check config/user-app/app.properties. If the property is still not found, it will fall back to the common configuration at config/application/app.properties.

Auto Refresh of Configuration

This is enabled by adding an annotation called @RefreshScope in class level, wherever we are using the data from the property file.

Java
 
@RestController
@RefreshScope
public class Controller {

    private static final Logger logger = LoggerFactory.getLogger(Controller.class);
    private final PortListener portListener;

    public Controller(PortListener portListener) {
        this.portListener = portListener;
    }

    @Value("${message:Default}")
    String testMessage;
    @Value("${sample.config.1:Default}")
    String sampleConfig1;
    @Value("${sample.config.2:Default}")
    String sampleConfig2;
    @Value("${sample.config.3:Default}")
    String sampleConfig3;
    @Value("${sample.config.4:Default}")
    String sampleConfig4;

    // config from the common config of all apps
    @Value("${global.config:Default}")
    String globalConfig;

    @GetMapping(value = "getStatus", produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<ResponseEntity<Object>> healthCheck() {
        logger.info("<--- Service to get status request : received --->");

        List<String> stringList = new ArrayList<>();
        stringList.add("Message: "+testMessage);
        stringList.add("Application is running under port: "+portListener.getPort());
        stringList.add("Global :"+globalConfig);
        stringList.add(sampleConfig1);
        stringList.add(sampleConfig2);
        stringList.add(sampleConfig3);
        stringList.add(sampleConfig4);
        logger.info("<--- Service to get status response : given --->");

        return Mono.just(ResponseEntity.ok(stringList));
    }
}


Testing

Right now, if we call the getStatus API, we will receive the following data, which is loaded from Consul.

JSON
 
[
  “Message: Dev configuration of user-app !!”,
  “Application is running under port: 3602”,
  “Global :Default”,
  “Test data 111”,
  “Test data 222”,
  “Test data 333”,
  “Test data 444”
]


After that, if we update the value in the Consul dashboard, then the next time this same api will return newly updated data from Consul.

GitHub

The sample project is available in the repository.

That is all... thanks for reading!

Configuration management Test data Spring Boot Integration

Opinions expressed by DZone contributors are their own.

Related

  • CMDB vs. IT Asset Management: Why Confusing Them Can Break Your IT Operations
  • Robust Integration Solutions With Apache Camel and Spring Boot
  • Effective Exception Handling in Microservices Integration
  • Integrate Spring With Open AI

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook