Configuring the Spring Cloud application
One of the major issues of the cloud-native application is maintaining and distributing configuration across the distributed services.
Spring Cloud provides a module or sub-project for this cloud-native problem. This module is known as a Spring Cloud Config. It provides a server and client approach to store and serve distributed configurations across several environments and distributed systems.
By default, the Spring Cloud Config Server uses Git implementation. It also easily supports labelled versions of configuration environments. But you can easily add alternative implementations and plug them in with Spring configuration.
Creating the configuration producer Spring Cloud Config Server
We'll explore an example of how to set up a Git-backed Config Server and use it in a simple REST application server.
Project setup
cd ~
spring init -d=cloud-config-server -n=cloud-config-app cloud-config-app
Using service at https://start.spring.io
Project extracted to '/home/hadoop/cloud-config-app'
Implementing Cloud Config Server
Let's implement an application main class that has more special annotations. Here, @SpringBootApplication will pull all the default and required configurations, and another annotation, @EnableConfigServer, will turn our application into a configuration server
cd cloud-config-app
cat << EOF > src/main/java/com/example/cloudconfigapp/CloudConfigAppApplication.java
package com.example.cloudconfigapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class CloudConfigAppApplication {
public static void main(String[] args) {
SpringApplication.run(CloudConfigAppApplication.class, args);
}
}
EOF
Configuring the application.properties file
By default, the server port will be 8080. We can change this default port configuration, and we have to provide the Git URI, which provides our version-controlled configuration content.
echo '
server.port=8888
spring.application.name=cloud-config
spring.cloud.config.server.git.uri=file://${user.home}/app-config-repo
' | tee -a src/main/resources/application.properties
where ${user.home}/app-config-repo is a Git repository containing YAML and properties files.
Creating a Git repository as configuration storage
cd ~
git config --global user.email "adithya.j@admatic.in"
git config --global user.name "Adithya J"
mkdir app-config-repo
cd app-config-repo
git init .
echo 'user.role=Dev' > application-dev.properties
echo 'user.role=Admin' > application-prod.properties
git add .
git commit -m 'Initial commit for application properties'
Running your configuration application
cd ~/cloud-config-app/
mvn spring-boot:run
The Git-backed configuration API provided by our server can be queried using the following paths:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Let's retrieve the configuration as the following URI: /{application}/{profile}[/{label}]
http http://localhost:8888/cloudconfig/dev/master
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Date: Mon, 17 Dec 2018 09:44:49 GMT
Transfer-Encoding: chunked
{
"label": "master",
"name": "cloudconfig",
"profiles": [
"dev"
],
"propertySources": [
{
"name": "file:///home/hadoop/app-config-repo/application-dev.properties",
"source": {
"user.role": "Dev"
}
}
],
"state": null,
"version": "37cf5bed67e00867a971a567fbb865a7bde59bd2"
}
Let's retrieve the configuration as the following URI: /{application}-{profile}.yml
http http://localhost:8888/cloudconfig-dev.yml
HTTP/1.1 200
Content-Length: 18
Content-Type: text/plain
Date: Mon, 17 Dec 2018 09:45:13 GMT
user:
role: Dev
Creating the configuration consumer Spring Cloud Config Client
Let's create a Spring Boot application that connects with the Spring Config Server to take advantage of reading external property sources from the central configuration server.
Project setup
cd ~
spring init -d=cloud-config-client,web -n=cloud-config-client cloud-config-client
Using service at https://start.spring.io
Project extracted to '/home/hadoop/cloud-config-client'
Implementing Cloud Config Server
Next, let's create a client class that is a simple REST controller with one GET method mapping:
cd ~/cloud-config-client
echo '
package com.example.cloudconfigclient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigClientController {
@Value("${user.role}")
private String role;
@GetMapping("/profile/{name}")
public String getActiveProfile(@PathVariable String name) {
return "Hello " + name + "! active profile name is " + role;
}
}
' | tee src/main/java/com/example/cloudconfigclient/ConfigClientController.java
As you can see, the REST controller class has one request handler method and one role property. This property is annotated with the @Value annotation to populate the value of ${user.role}. It will be fetched from our Cloud Config Server hosted at http://localhost:8888/. But it must be placed in a resource file named bootstrap.properties, because this file will be loaded very early while the application starts.
cat << EOF > src/main/resources/bootstrap.properties
spring.application.name=config-client
spring.profiles.active=dev
spring.cloud.config.uri=http://localhost:8888
EOF
Let's run the client application and see the output of the REST service:
mvn spring-boot:run
curl localhost:8080/profile/Admatic
Hello Admatic! active profile name is Dev
The role of the user is fetched from the Spring Cloud Config Server.