Spring Cloud step-by-step (part 2)
Tags: spring, cloud, cloudconfig
Published: 2018-06-21 10:44:58

---
title: Spring Cloud step-by-step (part 2)
published: true
description: Transform Spring Web app into cloud native. Adding centralized configuration.
tags: spring,cloud,cloud config
---
In the [previous post](https://dev.to/piczmar_0/spring-cloud-step-by-step-part-1-1670) we created basic Spring Web REST API for rental pricing.

In this post, we will transform it into Spring Cloud project and add the centralized configuration.

It means we will keep configuration for all our services in single place, easy for modification and all the changes will be discovered by services without the necessity of changing their code.

The project for this post is available at GitHub branch [spring-cloud-2](https://github.com/piczmar/spring-cloud-rental/tree/spring-cloud-2)

### Configuring Config Service
We need another application which will be our Config Service and Pricing Service will connect to it.

We can generate Config Service app with Spring Initializr at [http://start.spring.io](http://start.spring.io). 

All we need is to choose "Config Server" and "Web" from dependencies.


![Generate project](https://thepracticaldev.s3.amazonaws.com/i/m1p4aejb2jt57ggpvf6k.png)


This would generate app with maven dependencies in pom.xml:
```xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
```

Then we need to tell Spring Boot that this is a Config Service app with annotation on main class:

```java
@EnableConfigServer
```

It will add some new REST mappings to the application which we can see in logs when the application starts.

![console log](https://thepracticaldev.s3.amazonaws.com/i/yd17shqa50pv02mfmcpv.png)

Then add these properties in `application.properties`

```
server.port=8888
spring.cloud.config.server.git.uri=${HOME}/cloudconfigs
```

The last property tells Config Service where to look for services configurations, e.g. we can use local git repo, GitHub or bitbucket.

We will use local git repo. Let's create it. Execute commands in bash:

```
mkdir -p ${HOME}/cloudconfigs
cd ${HOME}/cloudconfigs
git init
```

Then create a new file `pricing-service.yaml` in `${HOME}/cloudconfigs`  and add these properties: 

```
pricing:
  plan:
    basic: 5
    standard: 200
    vip: 500
```

Commit the file.


```
git add pricing-service.yaml
git commit -m 'added config'
```

Here we use different values than in the initial Pricing Service configuration to spot the difference.

These values will overwrite any local configuration in Pricing Service.

If we wanted, we could also add `application.properties` or `application.yaml` to the repo which would keep common properties for all services.

E.g. we could put

```
pricing:
  plan:
    basic: 1
```

but in this case, if we start Config Service and query for configuration for pricing-service the value will be overridden with setting from `pricing-service.yaml`
We can check this at [http://localhost:8888/pricing-service/default](http://localhost:8888/pricing-service/default)
It would respond with JSON like: 

```json
{
   "name":"pricing-service",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":"8ab2211dd33751b797afa3d0a0eea8fccc10e676",
   "state":null,
   "propertySources":[
      {
         "name":"/home/marcin/tmp/cloudconfig/application.yaml",
         "source":{
            "pricing.plan.basic":5,
            "pricing.plan.standard":200,
            "pricing.plan.vip":500
         }
      }
   ]
}
```

### Configuring config client
In Pricing Service we need to add a dependency

```xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
```

and `dependencyManagement` section:

```xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
```

and version configuration in `properties`:

```xml
<properties>
    ...
    <spring-cloud.version>Finchley.RC2</spring-cloud.version>
</properties>

```

Then add a file `resources/bootstrap.yaml`

This is a property file which will be read as first when the application starts.

It is how Spring Cloud works. It first reads `bootstrap.yaml` to determine additional configuration to be used.

In our cases, it will use the configuration from Config Service.

The file will look as follows:
```
spring:
  application:
    name: pricing-service
  cloud:
    config:
      uri: http://localhost:8888
```

where `spring.application.name` will be the name of the service telling Config Service which file to grab from config git repo and `spring.cloud.config.uri` is a URL of Config Service. 

By default Config Service starts on `localhost:8888`.

Now if we start Pricing Service the order in which properties are resolved is the following: 
- `pricing-service.properties` in config git repo
- `application.yaml` in config git repo (if property not present in `pricing-service.properties`)
- `application.yaml` in pricing service (if property not present in `application.yaml` in config git repo)

What would happen if the Config Service was down? The local properties from Pricing Service will be used.

Config Service has many nice features like properties per spring profile or label and properties encryption.
You can check a nice explanation [here](http://www.baeldung.com/spring-cloud-configuration) or of course in [Spring Cloud docs](https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html)


The final code for this part is available at GitHub [spring-cloud-2](https://github.com/piczmar/spring-cloud-rental/tree/spring-cloud-2) branch.

We have now centralized configuration for our services delivered by Config Service, but all services would need to have URL to the Config Service given at runtime (either in local `application.yaml` or through environment variable). 

This is a bit cumbersome if there are different URLs for integration, QA, PROD environments. 

In the next post we will add service discovery mechanism so that services can use only a friendly name and the URL will be provided from the service registry.