Nowadays no one disputes the need to save application settings in the environment and not within the software component. This is one of the premises when we are developing software. In fact, this is one of the twelve-factor app methodology points.

The people from Spring (Pivotal Company) have developed a Java solution for Centralized Configuration Management as part of their open source tools for Cloud Systems. The name of this solution is Cloud Spring Config and it is currently in version 1.1.1. Its first release was in March 2015.

The main idea of this system is to manage the configuration of different applications in different environments. Thus, this service can handle the configuration of different environments from development to production.

The services exposed by this system are based on HTTP, so any application developed in almost any language can use it. If the application is built on Spring Boot, integration is almost transparent because it is done by configuration.

This service is really useful if you have to handle several systems and environments. For example, if you are using Microservices or SOA, where there could be many applications in a solution, it should be easy if you have a centralized configuration model. Spring Config Cloud services settings return JSON format, but they could also return a plain text file.

The sequence for using these services is simple: when the application starts, it queries Spring Cloud Config services to get the settings.

The Config Server does not send a notification to applications about configuration changes, but it is possible to allow refresh at runtime through events using Spring Cloud Bus. To do this, Spring Beans that should be refreshed when there is a configuration change have to be annotated with @RefreshScope. Thus, once a configuration change is detected, a new event will be sent to applications to reset Spring Beans. Default configuration works with GitHub, GitLab, Bitbucket and local Git repositories.

Spring Cloud Config handles the following concepts for resolution settings:

  • Application: name of the application.
  • Profile: logical grouping connected with environments.
  • Label: name of a version marker, for example a Git branch.
  • Path: an environment-specific plain text config file.

HTTP request paths are formed using the above concepts:

/{application}/{profile}[/{label}]

And you can directly obtain the file using the following path:

/{application}/{profile}/{label}/{path}

Spring Cloud Config uses a pluggable repository layer that supports local storage, Git, and Subversion. The latter two repositories provide the ability to maintain versioning changes made to the configuration.

Another feature is the possibility of encrypting configuration parameters using both symmetric and asymmetric encryption algorithms. This is a mandatory requirement due to sensitive data that might be stored, such as usernames and database passwords.

Another advantage of Spring Cloud Config is the possibility of having global configurations at the application level that can be overridden by more specific configurations at the profile and label levels. This prevents you from having to rewrite the same properties values in several places.

In order to start Spring Cloud Config it is only necessary to add the dependency “spring-cloud-starter-config” in a project using Spring Boot and add the @EnableConfigServer annotation in a Spring Bean configuration, which has the annotation @Configuration. That’s all.

In this way you can customize the server by adding security or monitoring, using another project such as Spring Security or Actuator. If it seemed easy to start the server to configure a Java client, using Spring Boot is even easier. You only need to have the dependency “spring-cloud-starter-config” and Spring Boot will try to find the settings in the default port of Spring Cloud Config. Amazing!

The properties initialized remotely by Spring Cloud Config cannot be locally overwritten, except when there is a flag that allows it on the Config Server. This way you can avoid configuration errors.

Although creating the server is very simple, there is a Docker image parameterized to do some tests. The image is documented in https://hub.docker.com/r/hyness/spring-cloud-config-server/.

The following is an example of an HTTP request on the example container:

Path: /stores/cloud/master/

{

 "name": "stores",

 "profiles": [

    "cloud"

 ],

 "label": "master",

 "version": "115be7a7479730e59568d70bac1377a692142dd7",

 "propertySources": [

    {

     "name": "https://github.com/spring-cloud-samples/config-repo/stores.yml#cloud",

     "source": {

       "spring.profiles": "cloud",

       "spring.data.mongodb.uri": "${vcap.services.${PREFIX:}mongodb.credentials.uri}"

     }

    },

    {

     "name": "https://github.com/spring-cloud-samples/config-repo/application.yml#cloud",

     "source": {

       "spring.profiles": "cloud",

       "spring.cloud.config.uri": "${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@${PREFIX:}configserver.${application.domain:cfapps.io}}",

       "oauth2.client.tokenUri": "${vcap.services.${PREFIX:}sso.credentials.tokenUri:}",

       "oauth2.client.authorizationUri": "${vcap.services.${PREFIX:}sso.credentials.authorizationUri:}",

       "oauth2.client.clientId": "${vcap.services.${PREFIX:}sso.credentials.clientId:}",

       "oauth2.client.clientSecret": "${vcap.services.${PREFIX:}sso.credentials.clientSecret:}",

       "oauth2.resource.tokenInfoUri": "${vcap.services.${OAUTH2_RESOURCE_SERVICEID:${oauth2.resource.serviceId:sso}}.credentials.tokenInfoUri:}",

       "oauth2.resource.serviceId": "${PREFIX:}resource",

       "application.domain": "${APPLICATION_DOMAIN:cfapps.io}",

       "endpoints.restart": "enabled",

       "eureka.password": "password",

       "eureka.instance.hostname": "${vcap.application.uris[0]:localhost}",

       "eureka.instance.nonSecurePort": 80,

       "eureka.client.serviceUrl.defaultZone": "${vcap.services.${PREFIX:}eureka.credentials.uri:http://user:${eureka.password:}@${PREFIX:}eureka.${application.domain:cfapps.io}}/eureka/",

       "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": 60000,

       "ribbon.ConnectTimeout": 3000,

       "ribbon.ReadTimeout": 60000

     }

    },

    {

     "name": "https://github.com/spring-cloud-samples/config-repo/stores.yml",

     "source": {

       "foo": "AQCST0WVyBi2M5w1KWyzV6DNGXKBgk5Yd9QnbVv4rSj+7HhgsJh5gQTI/CZvV/wHZqYtYrGxJJ3TCdXc/gBP4dbkBDdOEJOq+u7UUqNTOd2693FgOp5CeoMREUOmLp9r0CtF4TZLdjZfs4kxiBPVPd5fEaz9ULIgtgLSdS2oUEg6UXr3LA/M7P8YchkEPYUyf+VxGUDe587XPffHMU4zmvhmoTSen9BAc5BuGK+FZ3GFe12MDEPkNQ0uY002FitEfmgON65Xh3eJtNxCbUXJTj+oDc0icePqOgnG0gc17MymZdcJCIhP+cCiS6LzS57vhP+xGZvBBBHnw00ZVzHX73UfKkC9GLsnEVVQO5Xf2COR/rGZqvLJNKgvSHcbf03PrhQ="

     }

    },

    {

     "name": "https://github.com/spring-cloud-samples/config-repo/application.yml",

     "source": {

       "info.description": "Spring Cloud Samples",

       "info.url": "https://github.com/spring-cloud-samples",

       "eureka.client.serviceUrl.defaultZone": "http://localhost:8761/eureka/"

     }

    }

 ]

 

Although the project is new, only about 1 year old, it can still grow. For example, it does not yet have a web page that enables you to easily view the configurations that were installed.

In my opinion, this project, like others in the Spring Cloud solution, is one that marks the way forward in software development and especially in the Java language.

0
Menu