Image of Spring Cloud Config Server

ADVERTISEMENT

Introduction

Managing the configuration of microservices in a distributed system has been a tedious and time-consuming task especially if we’re talking about huge systems which consist of considerable amount of microservices.

Each time you need to change the configuration of a microservice, you would go to the corresponding project, change its configuration and then restart the application for the change to take effect.

This challenge has been solved by introducing Spring Cloud config utility project which provides support for externalized configuration in a distributed system, exposing the following features:

  1. Manage the configuration of all modules of a distributed system in one central repository.
  2. Refresh the configuration dynamically without the need to restart each service after a configuration change.

In this tutorial, we provide a step-by-step guide for setting-up a Spring Cloud configuration service, in addition to building a client which consumes the central configuration on startup then refreshes its configuration without restart.

1- Create the config service project

Open eclipse then create a new maven project and name it as SpringCloudConfigServer.

2- Add dependencies

Add the Spring Cloud Config server dependency:

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

Then add the following dependency management attribute:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Nothing more than that, just add the Spring boot starter parent and you’re good to go.

Following is a full pom.xml for reference:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.programmer.gate</groupId>
  <artifactId>SpringCloudConfigServer</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
      <plugins>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
      </plugins>
      </build>
</project>

3- Create configuration repository The next step is to create the repository which would store all the configuration files, you can choose any repository system like: GIT, SVN .. In this tutorial, we use GitHub.

  • Create a new folder named as spring-cloud-repo on desktop.
  • Create 2 property files named as client-A.properties and client-B.properties respectively.
  • Both property files hold just a simple attribute as the following:
hello.message=Hello from Client A
hello.message=Hello from Client B
  • Each property file corresponds to a microservice module and should be named as .properties.
  • The name of the microservice is defined using “spring.application.name” at the client project.
  • We can also add a common file named as “application.properties” in order to store common configuration for all clients.
  • Commit and push the folder to GIT.

4- Configure application.properties

Create application.properties under src/main/resources and add the following configuration:

server.port=8888
spring.cloud.config.server.git.uri=https://github.com/husseinterek/spring-cloud-repo.git

Here we define a custom port for the configuration server and we also define the path of the repository which stores the configuration files, the path of the repository is copied from our previously created GIT project.

P.S: if we don’t define a custom port, Spring Cloud config server automatically runs on localhost:8888

5- Application.java

Create the starter class and annotate it with @EnableConfigServer, this is the annotation which marks our project as a configuration server.

package com.programmer.gate;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
 
@EnableConfigServer
@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

6- Start the configuration server

Start the server as an executable jar and make sure that it’s functioning as a configuration server and exposing the configuration files of the clients through running the following url:

http://localhost:8888//default

This URL should return the configuration attributes defined under the requested configuration file in a JSON format.

We got the following results after we test the configuration of our clients:

local host

7- Create Spring Cloud Client

Now we’re going to create a client which consumes the central configuration exposed by the configuration server.

Go to eclipse again and create a new maven project and name it as SpringCloudConfigClientA.

8- Add Client dependencies

Go to pom.xml and add the following dependencies:

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

Here we import the spring cloud configuration libraries to our project and define it as a web application.

The “spring-boot-starter-actuator” dependency exposes utility methods which check the health of the configuration server and refresh the configuration after change.

9- bootstrap.properties

Create bootstrap.properties under src/main/resources.

spring.application.name=client-A
spring.cloud.config.uri=http://localhost:8888

This file is run at the startup of the client application, it defines a unique name for the client application in addition to the path of the configuration server.

The name defined under “spring.application.name” should be similar to the name of the configuration file stored under the repository.

P.S: the default url of the configuration server is localhost:8888, so if we remove it from here , we will still be able to connect to the configuration service.

10- application.properties

Create application.properties under src/main/resources.

server.port:9095

In this file, we define the configuration which requires a restart after each change, here we just define a custom port for the application.

11- Create the REST controller

Create Application.java under com.programmer.gate:

package com.programmer.gate;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@SpringBootApplication
@RefreshScope
@RestController
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @Value("${hello.message}")
    private String message;
 
    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}

We define our class as a controller which exposes a simple method “/message” that prints out the value of “hello.message” attribute in order to make sure that our client is successfully reading from the configuration service.

We also annotate our class with @RefreshScope, this annotation refreshes the configuration attributes used under the defined class whenever a refresh event is issued.

12- Refresh the configuration

We go back to our repository and modify the value of “hello.message” attribute under client-A.properties to be:

hello.message=Hello from Client A updated

In order to reflect this change to Client A application, you should run the following POST URL:

http://localhost:9095/actuator/refresh

Now when you run http://localhost:9095/message, you get the following result:

Hello from Client A updated

Summary

Managing the configuration of microservices in a distributed system has been a tedious and time-consuming task especially if we’re talking about huge systems which consist of considerable amount of microservices.

Next Steps

If you're interested in learning more about the basics of Java, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.