Get Your Copy of The CXO's Playbook for Gen AI: Practical Insights From Industry Leaders.  Download Now >
Back to Blogs

Spring Cloud Config to Centralize Spring Applications

Introduction

In modern software development, managing configurations across multiple applications and environments is crucial for reliability and scalability. Spring Cloud Config, a feature of the Spring framework, offers a centralized solution for handling configurations in Spring applications. By centralizing configurations and providing a server-client architecture, Spring Cloud Config simplifies configuration management and ensures applications operate with up-to-date settings. 

We can store the configuration in Git version control or in the file system as well. Here we are going to see two spring boot applications: one will act as a spring cloud config server and the other will be the client application.

This guide explores the architecture, functionalities, and benefits of Spring Cloud Config, empowering developers to streamline configuration workflows and enhance application reliability.

Spring Cloud Config Server Architecture

Spring cloud config Architecture

Once done with adding the properties to application.yml file, create the configuration file in the path mentioned for "search-locations".

Spring Cloud Starter Config: Required Dependencies

The server project is relying on “spring-cloud-config-server” dependency,

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

The client application is relying on “spring-cloud-config-client” dependency,

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>2.2.1.RELEASE</version>
<scope>runtime</scope>
</dependency>

Note: You can also use spring-cloud-starter-config dependency instead of spring-cloud-config-client.

Spring Cloud Config Server Implementation

To make the spring application into Cloud Config Server first we need to mention the @EnableConfigServer annotation.

@EnableConfigServer
@SpringBootApplication
public class SpringConfigServerApplication {

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

Next, we need to add the below properties in the application.yml file

Storing Configuration in the Local File System

spring:
 application:
                 name: config-server
           profiles:
             active: native
cloud:
    config:
       server:
native:
                          search-locations: file:///C:/Documents/config

The native property tells the server to search for the configuration in the local file system instead of Git. And search-locations is the path of the local file system where you are storing the configuration file.

Storing Configuration in Git

spring:
 application:
             name: config-server
 cloud:
   config:
     server:
         git:
           uri: <git url>

Storing configuration in Multiple Locations

spring:
 application:
             name: config-server
             profiles:
                active: native, git
 cloud:
    config:
        server:
native:
                search-locations: file:///C:/Documents/config,  file:///C:/Documents/config
git:
    uri: <git url>
   repos:
      testapp:
         pattern: test-app
uri: <git url>

You can mention multiple search locations for the file system separated by a comma and for multiple Git locations use repos and pattern tags to differentiate the URL so in the above example if the URL has a pattern “test-app” like “localhost:8080/test-app/development”  the config server fetch the value from the URI mentioned for test-app else by default it will fetch from “git.uri” location.

In this demo, I will go with storing the configuration in the local file system. Once done with adding the properties to application.yml file, create the configuration file in the path mentioned for "search-locations".

Starting Config Server

Step 1 : I have created a file named “redis-client-development.yml”  in C:Documentsconfig. The naming convention of the file name should be that the first part that is "redis-client" should match the client application name, and the last part that is "development" shows the profiling for the client application. You can have different files with different profiling like production, and QA.

Example file names for different profiles - redis-client-production.yml,redis-client-qa.yml

The file contains the configuration below, which I want to externalize.

spring:
 datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: test
    password: test

Step 2: Start the application

Once you start the application successfully, you hit the endpoint

"http://localhost:9898/redis-client/development" then the response will be:

{
  "name":"redis-client",
  "profiles":[
 "development"
  ],
  "label":null,
  "version":null,
  "state":null,
  "propertySources":[
 {
"name":"file:///C:/Documents/config/redis-client-development.yml",
"source":{
"spring.datasource.driver-class-name":"com.mysql.jdbc.Driver",
"spring.datasource.url":"jdbc:mysql://localhost:3306/test",
"spring.datasource.username":"test",
"spring.datasource.password":"test"
}
 }
  ]
}

The development in the URL will be considered as profiling so we have to mention it after "/".

Spring Cloud Config Client Implementation

The client application is going to be a simple one. We need to add the required dependency for the config client.

Then we have to add the below properties to our bootstrap.yml file.

spring:
 application:
   name: redis-client
 profiles:
   active: development
 cloud:
   config:
     uri: http://localhost:9898

Here cloud.config.uri is the URL of the config server. So the Spring boot will understand that it has to fetch configurations from that URL.

To show that the client application fetches the values from the config server I have created a java file in the client application that populates all its required configurations from the config server.

package com.project.redisdemo.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

   @Value("${spring.datasource.driver-class-name}")
   private String driverClassName;
   @Value("${spring.datasource.url}")
   private String url;
   @Value("${spring.datasource.username}")
   private String username;
   @Value("${spring.datasource.password}")
   private String password;


   @Bean
   public DataSource getDataSource() {
       DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
       System.out.println("********************************driverClassName - "+driverClassName);
       dataSourceBuilder.driverClassName(driverClassName);
       dataSourceBuilder.url(url);
       dataSourceBuilder.username(username);
       dataSourceBuilder.password(password);
       return dataSourceBuilder.build();
   }
}

This class has @configuration annotation so that the file will get loaded at server startup and also I have added a print statement to show that the values have been fetched from the config server. Now we can start the client application.

Client Application Logs

2021-08-29 20:16:57.850  INFO 10268 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-08-29 20:16:57.850  INFO 10268 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2789 ms
********************************driverClassName - com.mysql.jdbc.Driver
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
2021-08-29 20:16:58.112  INFO 10268 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-08-29 20:16:58.119  WARN 10268 --- [           main] com.zaxxer.hikari.util.DriverDataSource  : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2021-08-29 20:16:58.634  INFO 10268 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.

In the above logs, you can see the MySQL driver class name has been fetched from the config server.

Conclusion

Now, we are able to create a config server that fetches the config properties from our local file system. And now we can also build the centralized configuration for microservices.

- - - - - -

Ideas2IT Team

Connect with Us

We'd love to brainstorm your priority tech initiatives and contribute to the best outcomes.