Spring Cloud Configuration- Externalize Configuration

Spring cloud config provides both server and client side support for externalizing the configurations in a distributed system. Remember the bad days when we put the configuration constants in a class file and package it inside a war/ear and then deploy it. It had caused a lot of troubles and mess. Twelve-factor app, a methodology for building distributed applications that run in the cloud, strictly suggests us to separate the configuration from the source code being deployed. The Spring cloud config is the savior. There are many reasons to use spring cloud config. Some of them are:

  • Spring Cloud configuration server is easy to set up and use.
  • Spring Cloud configuration tightly integrates with Spring Boot. You can literally read all your application’s configuration data with a few simple-to-use annotations.
  • Spring Cloud configuration server can integrate directly with the Git source control platform.

It supports different stores like Git, SVN, and file system. One can use anyone depending on their choice but for this article, we are going to use Git as a backend store for storing configuration properties. We will be creating two projects i.e config-server and config-client. We will also create a git repository for storing the configuration files. Let’s get started.

The git repository will have two property files from config-client named as config-client.properties and config-client-test.properties. ({application-name}-{profile}.properties pattern). It looks like:

No alt text provided for this image

config-client.properties contains:

message = Hello Folks!

config-client-test.properties contains:

message = Hello Folks From Test Profile !

You can check it to be sure of it!

Let’s create a config-server project

No alt text provided for this image

Generate a new spring boot project from spring initializr with Config Server dependency. Our application.yml looks like:

No alt text provided for this image

In the application.yml, we changed the default server port to 8888 and application name to config-server. We are using git as a store, so the url to git can be pointed by the property spring.cloud.config.server.git.uri.

Now use the annotation @EnableConfigServer and you’re done. Hey, Spring ! Thanks for being so declarative. This annotation will do the magic of enabling the required configuration for spring cloud config. It will also expose some rest endpoints needed to externalize configuration.

No alt text provided for this image

Let’s run the application and in the browser enter the url http://localhost:8888/{application-name}-{profile}

for eg: http://localhost:8888/config-client-test.properties will give you:

No alt text provided for this image

http://localhost:8888/config-client-test.properties will give you:

No alt text provided for this image

Voila, you are able to fetch the property files from git repository. Congratulations !

Let’s create a config-client project

No alt text provided for this image

Generate a new spring boot project from spring initializr with Config Client, Actuator and Web dependencies. You might be thinking why do we need actuator here. I will explain it in a bit. Create your bootstrap.yml or bootstrap.properties file. This file is used to fetch the configuration from the configuration server and is loaded before application properties. My bootstrap.yml file looks like:

No alt text provided for this image

In the bootstrap file, we set the name of the application and defined the cloud config uri. Our config-server application is running on http://localhost:8888. The value * of property management.endpoints.web.exposure.include will expose all the web endpoints from the actuator. We needed it to call the refresh endpoint that I will explain later.

Now let’s create a controller class that will read a value from the configuration file stored in the git repository and produces a JSON response. The MessageController and MessageService class look like:

MessageController.java

No alt text provided for this image

MessageService.java

No alt text provided for this image

Call the rest endpoint (http://localhost:8080/message) and see the JSON response. We got the expected response.

No alt text provided for this image

Change the value of message in config-client.properties from a git repository and call the same endpoint. I did it more than a hundred times but still getting the same old JSON response.

To refresh these properties, spring provides @RefreshScope annotation. By default, the configuration values are read on the client’s startup, and not again. You can force a bean to refresh its configuration – to pull updated values from the Config Server – by annotating with @RefreshScope. The MessageService annotated with refresh scope now looks like:

No alt text provided for this image

I changed the value of message from Hello Folks to Hello updated Folks! The value should have been updated. Don’t you think so? The updated config-client.properties looks like:

No alt text provided for this image

And the response of the end-point is still the same.

No alt text provided for this image

You can invoke the refresh actuator endpoint by sending an empty HTTP Post request to the client’s refresh endpoint. This will trigger the @RefreshScope annotation. Let’s do it.

No alt text provided for this image

We can see the response from curl that message property was changed. Let’s access the endpoint and see if the value is updated or not. And yes, we are finally done.

No alt text provided for this image

That’s how spring cloud config works. We can also encrypt and decrypt the configuration files. Play with it.

Thank you for reading my article. The whole projects can be found on Github.

Thank you for reading my article.
https://www.linkedin.com/pulse/spring-cloud-configuration-externalize-configuration-suraj-gautam/

Connect with me in linkedin.