Jules
HomeArticlesServicesContactEbookCapability Statement
Schedule a Call
Tutorial

Spring cloud config

Posted on 

Spring Cloud Config: Centralized Configuration Management

Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With Spring Cloud Config, you can manage your application configurations centrally, eliminating the need to hardcode properties or rely on local configuration files. This article will explore the features of Spring Cloud Config, provide step-by-step examples of setting up a config server and client, and demonstrate how to manage configurations effectively.

Features of Spring Cloud Config

  1. Centralized Configuration Management: Centralize your application configuration in one place, which simplifies management and ensures consistency across different environments.
  2. Version Control Integration: Integrate with version control systems (e.g., Git, SVN) to version and track configuration changes.
  3. JDBC, Vault: Other backends like JDBC databases, or HashiCorp Vault can be used.
  4. Environment-Specific Configurations: Manage different configurations for different environments (development, testing, production).
  5. Dynamic Configuration Updates: Automatically update configurations in running applications without restarting them.
  6. Secure Configuration Management: Secure sensitive information using encryption and decryption mechanisms.

Setting Up Spring Cloud Config Server

Step 1: Create a Spring Boot Application

First create a new Spring Boot project using Spring Initializr (https://start.spring.io/) to act as the Config Server. Add the necessary dependencies in your pom.xml file:

##language-xml

<dependencies>
   <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-config-server</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>

Step 2: Enable Config Server

Enable the Config Server by adding the @EnableConfigServer annotation to your main application class:

##language-java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class DemoApplication {

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

Step 3: Configure the Config Server

Configure the server to load config files from the local filesystem for this demo. Add the following properties to your application.properties or application.yml file. There are many backends available including git, jdbc

##language-ini

server.port=8888
# Enable spring cloud config native profile
spring.profiles.active=native
# Configure cloud config to lookup properties from a local folder
spring.cloud.config.server.native.searchLocations=file:./config
spring.security.user.name=root
spring.security.user.password=changeit

Step 2: Configure the Config Client

Configure the client to connect to the Config Server. Add the following properties to your application.properties or application.yml file:

##language-ini

# The application name is used in the cloud config server to allow
# the server to provide configs for multiple applications
spring.application.name=my-client-app
# Load the dev profile (config/my-client-app-dev.properties)
spring.profiles.active=dev
# Be sure to include http auth here if configured
# prefix with `optional:` if the app should be able
# to come up when the server is unavailable.
spring.config.import=configserver:http://root:changeit@localhost:8888

Step 3: Create Configuration Files

Create configuration files in the folder specified in the Config Server. For example, create a file named config/my-client-app.properties:

##language-ini

message=Hello from Spring Cloud Config

Multiple property files are merged in a similar way that spring already loads property files, there is a specific ordering where each subsequent property file overwrites any existing keys.

  • application.properties
  • application-{profile}.properties
  • {application-name}.properties
  • {application-name}-{profile}.properties

Properties can also be stored inside folders representing the application name, eg:

/{application}/application-{profile}.yml
/{application}/application.yml

Step 4: Access Configuration Properties

Access the configuration properties in your client application using the @Value annotation or @ConfigurationProperties:

##language-java

package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class MessageController {

   @Value("${message}")
   private String message;

   @GetMapping("/message")
   public String getMessage() {
       return this.message;
   }

/** Run code when the context is refreshed */
@EventListener({ ContextRefreshedEvent.class })  
public void onContextRefreshed() {  
/** code to execute when context is refreshed */
System.out.println("Context refreshed, new message value: " + message);
}
}

Managing Environment-Specific Configurations

Spring Cloud Config supports environment-specific configurations. You can create different configuration files for different environments (e.g., application-dev.properties, application-prod.properties).

Example

In the config folder, create three files.

config/my-client-app.properties:

##language-ini

message=Hello from Default Environment

config/my-client-app-dev.properties:

##language-ini

message=Hello from Development Environment

config/my-client-app-prod.properties:

##language-ini

message=Hello from Production Environment

Spring cloud config works by serving properties via get requests, the endpoint format is simple, {spring.application.name}/{spring.profile} with default being the default profile. Spring cloud client's simply make the get request and reload any components that have the @RefreshScope annotation with the new properties, optionally you can be notified when this happens via annotating a handler in the component with @EventListener({ ContextRefreshedEvent.class })

##language-shell

> curl http://root:changeit@localhost:8888/my-client-app/dev | json_pp
{
  "label" : null,
  "name" : "my-client-app",
  "profiles" : [
     "default"
  ],
  "propertySources" : [
     {
        "name" : "file:config/my-client-app.properties",
        "source" : {
           "message" : "Hello from Default environment"
        }
     }
  ],
  "state" : null,
  "version" : null
}

> curl http://root:changeit@localhost:8888/my-client-app/dev | json_pp
{
  "label" : null,
  "name" : "my-client-app",
  "profiles" : [
     "dev"
  ],
  "propertySources" : [
     {
        "name" : "file:config/my-client-app-dev.properties",
        "source" : {
           "message" : "Hello from Development Environment"
        }
     }
  ],
  "state" : null,
  "version" : null
}

Switching Profiles

Switch profiles by setting the spring.profiles.active property in your application.properties file:

spring.profiles.active=dev

Or use the command-line argument:

##language-shell

java -jar my-client-app.jar --spring.profiles.active=prod

Dynamic Configuration Updates

Spring Cloud Config supports dynamic configuration updates using Spring Cloud Bus. The way this works is all clients and servers connect to a message bus (eg, RabbitMQ) and subscribe to some topics. The server can be configured to be triggered by an external source such as a git hook (or manually triggered) to publish property update messages over the message broker. When a client receives a message to update their properties the client performs the same update behavior as above (performing a get request to the server).

To enable this we need a message broker, spinning one up in docker is easy.

Create a docker-compose.yml file to spin up a rabbitmq service

##language-yaml

services:
 rabbitmq:
   image: rabbitmq:management
   container_name: rabbitmq
   environment:
     RABBITMQ_DEFAULT_USER: user
     RABBITMQ_DEFAULT_PASS: changeit
   ports:
     - "5672:5672"
     - "15672:15672"

Just start it up with docker-compose up
Then be sure to add dependencies to the Config server and Client applications:

##language-xml

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

Configure the message broker (e.g., RabbitMQ) in both applications:

##language-ini

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=user
spring.rabbitmq.password=changeit
# Only do this for local development
management.security.enabled=false
# This enables actuator endpoints
# and needs to be done in both server/client
# you should not expose these endpoints publically
management.endpoints.web.exposure.include=*

Disable CSRF security validation so we can test the refresh endpoint via curl

##language-java

 @Bean
 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
   http.csrf(csrf -> csrf.ignoringRequestMatchers(
           "/**"
   ));
   return http.build();
 }

Start up both the server and client via mvn spring-boot:run
Then update one of the property files then send a POST request to the Config Server to refresh the configurations.
This is a different endpoint from /refresh above in the client and tells the server to notify clients over the message broker to do remote refreshes.

##language-shell

curl -X POST http://localhost:8888/actuator/busrefresh

It is possible for spring cloud config server to use encrypted property values, that is outside the scope of this document but there are endpoints /encrypt and /decrypt you can use to look up how to do this.

Code available here

Conclusion

Spring Cloud Config is a powerful tool for managing application configurations centrally. It provides features like environment-specific configurations, dynamic updates, and secure configuration management. By following the steps outlined in this article, you can set up a Spring Cloud Config Server and Client, manage configurations effectively, and ensure that your applications are always running with the correct configurations.

‍

Tagged:
Spring Cloud
Chase Ripplinger
view All Posts

Featured Posts

Spring
Simplify Spring Boot Version Migration with OpenRewrite
Spring
@SecondaryTable
Staff Augmentation: A Catalyst for Mission-Driven Companies

Tags

Advertising
App
Development
Gagets
Inspiration
Mac OS
Mobile
Motivation
Photography
Social
Spring Cloud
Tech
Travel
Web Design
iPhone
More Posts

You Might Also Like

Sep 12, 2024
 in 
Tutorial

Spring cloud overview

Chase Ripplinger
May 12, 2023
 in 
Spring

Simplify Spring Boot Version Migration with OpenRewrite

Matthew Wojtowicz
May 11, 2023
 in 

Three Tools to Keep Your Dependencies Up to Date in a Spring Boot Project

Modern Java
for Your Business

Navigation

HomeServicesBlogContactPrivacy

Contact Info

contact@katyella.com
5290 Shawnee Rd,
Alexandria, VA 22312

SAM.gov Info

CAGE : 07X06
UEI: Y71RFT26SSP7