Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Intro to Spring Cloud Config Server

DZone's Guide to

Intro to Spring Cloud Config Server

Learn how to centralize your service configuration in Spring with Spring Cloud Config Server as well as how you can have your configurations consumed without restarts.

· Java Zone ·
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

In this tutorial, we will review the basics of Spring Cloud Config Server. We will set up a Config Server and then build a client application that consumes the configuration on startup and then refreshes the configuration without restarting. The application we are building is the same “Hello World” application discussed in the Centralized Configuration Getting Started Guide, but we go into more depth about the concepts of Spring Cloud Config Server in this article.

The full source code for the tutorial is on GitHub.

What Is Spring Cloud Config Server?

As the documentation succinctly states, “Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system.” The default implementation of the server storage backend uses git, so it supports labeled versions of configuration environments with ease and is accessible to many tools for managing the content.

Spring Cloud Config fits very well into Spring applications because its concepts of both client and server map precisely to the Spring Environment and PropertySource abstractions. However, Spring Cloud Config can be used with any application running in any language.

Create a Multi-Module Project

The application we are creating will have two modules: one for the Configuration Service and the other for the Configuration client. Because of this, we need to create a parent pom.

Parent

In our IDE, let’s create a new project. I’m using Spring Tool Suite, but that’s just a personal preference.

In our pom.xml, let’s specify our two modules:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.michaelcgood</groupId>
    <artifactId>com.michaelcgood</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>

    <name>michaelcgood-spring-cloud-config-server</name>
    <description>Intro to Spring Cloud Config Server</description>


    <modules>
        <module>mcg-configuration-client</module>
        <module>mcg-configuration-service</module>
    </modules>

</project>


Configuration Service

In our IDE, let’s create a new Maven module for our configuration service and insert this in our pom:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.michaelcgood</groupId>
  <artifactId>mcg-configuration-service</artifactId>
  <version>0.0.1</version>
  <packaging>jar</packaging>
  <name>mcg-configuration-service</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</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>


Configuration Client

Now we just need to make a module for our configuration client. So, let’s make another Maven module and insert this into our POM:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.michaelcgood</groupId>
  <artifactId>mcg-configuration-client</artifactId>
  <version>0.0.1</version>
  <packaging>jar</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</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>


Our project structure looks like this now:

Image title

Config Server

Now we will create a Config Service to act as an intermediary between our client and a git repository.

Enable Config Server

We use Spring Cloud’s @EnableConfigServer to create a config server that can be communicated with. So, this is just a normal Spring Boot application with one annotation added to enable the Config Server.:

@EnableConfigServer
@SpringBootApplication
public class ConfigServiceApplication {

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


application.properties

To ensure that there is no conflict between ports for our Config Service and client, we specify a different port for the Config Service:

server.port=8888

spring.cloud.config.server.git.uri=${HOME}/Desktop/mcg-config


The second line spring.cloud.config.server.git.uri=${HOME}/Desktop/mcg-config points to a git repository, which we will create next.

Git

On a *nix system, we can do everything on the command line.

We make a folder on our desktop:

mkdir mcg-config


We create a file named a-bootiful-client.properties using vim:

vim a-bootiful-client.properties


We add the message, “Hello World” but this could be whatever we would like. After we write (:w) we quit (:q) vim.

Now let’s create a new repo:

git init


Now we add the file that contains our message:

git add a-bootiful-client.properties


Let’s commit:

git commit


Configuration Client

Now let’s create a new Spring Boot application that uses the Config Server to load its own configuration and that refreshes its configuration to reflect changes to the Config Server on-demand, without restarting the JVM.

Spring will see the configuration property files just like it would any property file loaded from application.propertiesapplication.yml or any other PropertySource.

Reflecting Changes

The client may access any value in the Config Server using the standard Spring ways, such as @ConfigurationProperties or @Value(“${…}”).

With this in mind, we create a REST controller that returns the resolved message property’s value:

@SpringBootApplication
public class ConfigClientApplication {

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

@RefreshScope
@RestController
class MessageRestController {

    @Value("${message:Hello default}")
    private String message;

    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}


The default configuration only allows the values to be read on the client’s startup and not again. So, using @RefreshScope we force the bean to refresh its configuration, which means it will pull updated values from the Config Server, and then trigger a refresh event.

bootstrap.properties

The properties to configure the Config Client must be read in before the rest of the application’s configuration is read from the Config Server, during the bootstrap phase.

We specify the client’s spring.application.name and the location of the Config Server spring.cloud.config.uri:

spring.application.name=a-bootiful-client
spring.cloud.config.uri=http://localhost:8888
management.security.enabled=false


Note: We disabled security with our setting management.security.enabled=false to make testing and tinkering easy for us.

Demo

First, we need to change directory to our configuration service and start it:

mcg-configuration-service mike$  mvn spring-boot:run


And then do the same for our client:

mcg-configuration-client mike$  mvn spring-boot:run


We can see in our terminal for configuration service when the a-bootiful-client.properties is added:

INFO 5921 --- [nio-8888-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/dk/48l9cm2x3vnfl5ymh6dtxpwc0000gn/T/config-repo-7195892194658362240/a-bootiful-client.properties

Let’s open our browser and visit http://localhost:8080/message. We see “Hello World”.

Now let’s change the message in a-bootiful-client.properties again and this time put, “Hi! :-)”.

After saving and doing a commit, we visit http://localhost:8888/a-bootiful-client/default to confirm our change.

Now we invoke the Spring Boot Actuator refersh endpoint to refresh our client:

curl -X POST http://localhost:8080/refresh


We visit http://localhost:8080/message and see our message “Hi! :-)” is displayed.

For more information on Spring Boot Actuator, see the tutorial Building Spring Boot RESTful Service + Spring Boot Actuator.

Conclusion

We just completed centralizing configuration of our services in Spring. We accomplished this by standing up a Spring Cloud Config Server and creating a client to consume the configuration on startup and then refresh the configuration without restarting.

Many other things can be done with Spring Cloud Config Server that we did not touch on, such as:

  • Have the Config Server register with the Discovery Service for Spring Cloud Netflix, Eureka Service Discovery or Spring Cloud Consul
  • Serve configuration in YAML or Properties format
  • Serve plain text configuration files
  • Embed the config server in an application

The full source code can be found on GitHub.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:
java ,spring cloud config ,config server ,hot swapping ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}