Spring Cloud Config

Dominik Adamek

Spring Cloud Config is a project that offers support for externalized configuration in a distributed system for both client side and server side. At server side, Spring Cloud Config helps you to implement a Config Server, which is a central service that manages configuration for applications across all environments. At client side, you can use Spring Cloud Config to automatically fetch appropriate properties at the application startup. In this article, we’ll show how to use Spring Cloud Config to implement a Config Server and how to use it at a client side.

Config Server

To implement a Config Server, we’ll use:

  • Maven
  • Spring Boot 2.5.5
  • Spring Cloud 2020.0.4

In order to start using Spring Cloud Config you will need following Maven dependencies:

<dependencies>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-config-server</artifactid>
    </dependency>
</dependencies>

Now you can create a Config Server by embedding it into Spring Boot application using @EnableConfigServer annotation:

package org.example;

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

@SpringBootApplication
@EnableConfigServer
public class Application {

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

}

In order to serve configuration data, Spring Cloud Config uses the EnvironmentRepository interface, which returns the Environment object containing propertySourcesEnvironmentRepository serves property sources from /{application}/{profile}/{label}, where each variable has it’s corresponding client side mapping:

  • application is a spring.application.name on the client side
  • profile is a spring.profiles.active on the client side
  • label can be used for versioned configuration files

Spring Cloud Config allows you to choose between different backend options (different EnvironmentRepository implementations) for storing your configuration:

  • Git, which is a default backend
  • SVN
  • File System
  • Vault
  • JDBC (relational database storage)
  • Redis
  • AWS S3
  • CredHub

Additionally, you may want to fetch configuration from multiple sources. In order to do that, you need to set spring.profiles.active=composite in your Config Server’s application.properties (or YAML). Then you can configure different types of configuration backends. For the purpose of this article, we will use a File System Backend as this is a perfect candidate for getting started quickly with Spring Cloud Config. However, you should be careful using this backend on production and consider to use other types.

File System Backend comes along with Config Server’s native profile. Let’s start from activating a native profile in our application.properties:

spring.profiles.active=native

With File System Backend, you can load configuration data from the local classpath or file system. You can use spring.cloud.config.server.native.searchLocations to specify the location of your config files. In our example, we won’t specify this property and expect Config Server to load data from the classpath as this is the default behaviour. Let’s create two configuration files for our Client app with two separate profiles dev and prod under src/main/resources:

  • client-dev.properties:
my.custom.property=dev
  • client-prod.properties:
my.custom.property=prod

Now, let’s run our Config Server and verify it by calling: http://localhost:8080/client/dev. You should expect a following response:

{"name":"client","profiles":["dev"],"label":null,"version":null,"state":null,"propertySources":[{"name":"class path resource [client-dev.properties]","source":{"my.custom.property":"dev"}}]}

Encryption and Decryption

If your configuration files contain secret values like passwords, you can use the encryption and decryption features of Spring Cloud Config. Please note that those features require JCE (Java Cryptography Extension) to be installed in your JVM. Once that is in place, you may use built-in /encrypt and /decrypt endpoints to use Spring Cloud Config security features. Assuming your instance of the Config Server is running on localhost:8080, you can follow this example to encrypt your secret:

$ curl localhost:8888/encrypt -d myPassword

Then you can use the response from /encrypt in the configuration file starting with {cipher}:

my.custom.username=dev-user
my.custom.password='{cipher}<config-server-encrypted-response>'

All encrypted values (starting with {cipher}) are decrypted before sending to clients.

Client Side Setup

For the client side implementation, we’ll use the same base stack as for the Config Server, including Maven, Spring Boot and Spring Cloud. Additionally, we will use spring-boot-starter-actuator to demonstrate the Environment content at the client side. To start using Spring Cloud Config in the client application, you will need following Maven dependencies:

<dependencies>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-config</artifactid>
    </dependency>
</dependencies>

For testing purposes, let’s use a non-standard 8081 port and create application.properties files under /src/main/resources/:

server.port=8081
spring.application.name=client
spring.config.import=optional:configserver:http://localhost:8080
management.endpoints.web.exposure.include=*

Spring Cloud Config requires spring.config.import property to be set, so then it can use it to fetch configuration data from the Config Server at the application startup. We are also setting spring.application.name property, which will be used at the Config Server side, to lookup appropriate properties. The second required property for server-side property lookup is the profile which we will pass along with the run command (or you can specify it in your IDE’s run configuration). Let’s create a very basic main class:

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

}

Now we can start the application in a dev profile (please make sure before that your Config Server is up and running):

mvn spring-boot:run -Dspring-boot.run.profiles=dev

You may notice following lines in the startup log:

Fetching config from server at : http://localhost:8080
Located environment: name=client, profiles=[dev], label=null, version=null, state=null

In order to verify the value of our my.custom.property, let’s use the built-in env endpoint of Spring Actuator:

curl http://localhost:8081/actuator/env/my.custom.property
{"property":{"source":"configserver:class path resource [client-dev.properties]","value":"dev"},"activeProfiles":["dev"],"propertySources":[{"name":"server.ports"},{"name":"commandLineArgs"},{"name":"servletConfigInitParams"},{"name":"servletContextInitParams"},{"name":"systemProperties"},{"name":"systemEnvironment"},{"name":"random"},{"name":"cachedrandom"},{"name":"springCloudClientHostInfo"},{"name":"configserver:class path resource [client-dev.properties]","property":{"value":"dev","origin":"Config Server class path resource [client-dev.properties]:1:20"}},{"name":"configClient"},{"name":"Config resource 'class path resource [application.properties]' via location 'optional:classpath:/'"},{"name":"Management Server"}]}

You can verify the value for the prod profile as well and try to experiment with an additional labels at Config Server side, so you can see how you can version your config data.

Summary

In this article, we explored the basic concepts and features of Spring Cloud Config based on two Spring Boot Microservices working as a client and a server. To demonstrate how it works, we created a Config Server with a File System backend, and the client application fetching data from it. However, Spring Cloud Config offers you many options to choose a backend for your configuration data, so feel free to try it out in your project.

Poznaj mageek of j‑labs i daj się zadziwić, jak może wyglądać praca z j‑People!

Skontaktuj się z nami