Spring Cloud Config
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 propertySources
. EnvironmentRepository
serves property sources from /{application}/{profile}/{label}
, where each variable has it’s corresponding client side mapping:
application
is aspring.application.name
on the client sideprofile
is aspring.profiles.active
on the client sidelabel
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.