Spring Cloud step-by-step (part 3)
Tags: spring, cloud, clouddiscovery
Published: 2018-06-21 10:52:19

---
title: Spring Cloud step-by-step (part 3)
published: true
description: Using service discovery
tags: spring,cloud,cloud discovery
---
This is a continuation of previous blog posts: 
 - [Spring Cloud step-by-step (part 1)](https://dev.to/piczmar_0/spring-cloud-step-by-step-part-1-1670)
 - [Spring Cloud step-by-step (part 2)](https://dev.to/piczmar_0/spring-cloud-step-by-step-part-2-12o2)

Source code for this part can be found at GitHub in [spring-cloud-3](https://github.com/piczmar/spring-cloud-rental/tree/spring-cloud-3) branch.

Let's say we don't want to hardcode the URL to Config Service in our application properties because it may change from environment to environment.
Of course, we could pass this property as JVM environment variable on each environment, but then we need to worry about it in application startup scripts.
Instead, we could use service registry (such as [Netflix Eureka](https://github.com/Netflix/eureka)) and only use a friendly name for a service, instead of its URL.

Here we will update Config Service and Pricing Service applications to use service discovery mechanism with Spring Cloud Discovery.

## Configuring Eureka Server

Similarly, like we configured Config Service we will configure Eureka Server.
We can generate Config Service app with Spring Initializr at [http://start.spring.io](http://start.spring.io) again. 

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


![Generate project](https://thepracticaldev.s3.amazonaws.com/i/50iw2gzd2hj36jqxd9yh.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-starter-netflix-eureka-server</artifactId>
        </dependency>
```

Then we need to enable discovery server with annotation on main class:

```java
@EnableEurekaServer
```

and configure Eureka Server to not try to connect to itself - add `resources/application.yalm` with content:

```
server:
  port: ${PORT:8761}

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
    server:
      waitTimeInMsWhenSyncEmpty: 0
```

## Configuring Eureka clients

In Pricing Service and Config Service we need to add a dependency

```xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
```

and add Eureka client autoconfiguration with annotation

```java
@EnableEurekaClient 
```

Note the fact that in some examples in the web you may find annotation `@EnableDiscoveryClient` which basically does the same if you have Eureka dependencies in the classpath, but it has subtle difference.
There are multiple implementations of Discovery Service in Spring Cloud, such as Eureka, Consul, Zookeeper. 

`@EnableDiscoveryClient` lives in [spring-cloud-commons](https://github.com/spring-cloud/spring-cloud-commons) and chooses the implementation from the classpath.

`@EnableEurekaClient` lives in [spring-cloud-netflix](https://github.com/spring-cloud/spring-cloud-netflix/) and only works for Eureka.


Once we have an annotation on main class, when we start the app, it will try to contact the Eureka server on `http://localhost:8761` (the default value of `eureka.client.serviceUrl.defaultZone`)

Now start Eureka Service and Config Service and go to Eureka console at [http://localhost:8761](http://localhost:8761)

You would see an UNKNOWN service in the registry. 

![Eureka dashboard](https://thepracticaldev.s3.amazonaws.com/i/nwp3uhxyptwmebqj3rxq.png)


This is because we have not specified Config Service name.

In Config Service create file `resources/bootstrap.properties` and add property:

```
spring.application.name=config-service
```

This is a similar property to the one which we have added in Pricing Service `bootstrap.properties` and this is how Spring Cloud allows identifying a service by name.

We could actually add this property in `application.properties` and in this case it would still work but there are cases when the name is required yet before application context starts to initialize
and `bootstrap.properties` is the one which is loaded at very first place when application starts so it's safer to put `spring.application.name` already there.

Now when we restart Config Service it will be named in Eureka dashboard list.

Similarly, we can configure Pricing Service with Eureka.

We need to add the same dependencies as we added in Config Service, then `@EnableEurekaClient` annotation on main class. 

Pricing Service already has `spring.application.name` property configured before.

What is left is to replace hard-coded URL to Config Service with Eureka discovery.

Before we added Eureka we had such configuration in Pricing Service `bootstrap.yaml`:

```
spring:
  application:
    name: pricing-service
  cloud:
    config:
      uri: http://localhost:8888
```

Even though we added Config Service registration in Eureka, by default it does not affect other services which use Config Service.
We have to explicitly tell that we want to use Eureka client library to discover Config Service by setting property `spring.cloud.config.discovery.enabled=true` in Pricing Service `bootstrap.yaml`.

[Spring documentation](https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_spring_cloud_config_client) states: 
 __The price for using this option is an extra network round trip on startup to locate the service registration. The benefit is that the Config Service can change its coordinates, as long as the Discovery Service is a fixed point.__


Eureka client will try to find service named `configserver` in Eureka registry, but won't find such, as we named Config Service differently by setting the property `spring.application.name=config-service` in Config Service `bootstrap.yaml`.

Then we have to explicitly define the name of Config Service in Pricing Server `bootstrap.properties`. The final configuration will look as follows:

```
spring:
  application:
    name: pricing-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-service

```

When we start Pricing Service we should see a log like: 

```
c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.43.107:8888/
```

It means Eureka client managed to resolve the location of Config Service.

It was handled automagically by Spring, but we have not seen how to call other services manually from java code (e.g. with RestTemplate).

I will explain how to do it in next post soon.