diff --git a/03.microservices/currency-conversion-service/pom.xml b/03.microservices/currency-conversion-service/pom.xml
index dbf98db9..cff4927d 100644
--- a/03.microservices/currency-conversion-service/pom.xml
+++ b/03.microservices/currency-conversion-service/pom.xml
@@ -40,6 +40,11 @@
spring-cloud-starter-feign
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
org.springframework.cloud
spring-cloud-starter-ribbon
diff --git a/03.microservices/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java b/03.microservices/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java
index 6042ed2e..c53627b4 100644
--- a/03.microservices/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java
+++ b/03.microservices/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java
@@ -2,10 +2,12 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients("com.in28minutes.microservices.currencyconversionservice")
+@EnableDiscoveryClient
public class CurrencyConversionServiceApplication {
public static void main(String[] args) {
diff --git a/03.microservices/currency-conversion-service/src/main/resources/application.properties b/03.microservices/currency-conversion-service/src/main/resources/application.properties
index 769573e5..8831ae2b 100644
--- a/03.microservices/currency-conversion-service/src/main/resources/application.properties
+++ b/03.microservices/currency-conversion-service/src/main/resources/application.properties
@@ -1,3 +1,4 @@
spring.application.name=currency-conversion-service
server.port=8100
-currency-exchange-service.ribbon.listOfServers=http://localhost:8000,http://localhost:8001
\ No newline at end of file
+eureka.client.service-url.default-zone=http://localhost:8761/eureka
+#currency-exchange-service.ribbon.listOfServers=http://localhost:8000,http://localhost:8001
\ No newline at end of file
diff --git a/03.microservices/currency-exchange-service/pom.xml b/03.microservices/currency-exchange-service/pom.xml
index 4427f086..5d60cefb 100644
--- a/03.microservices/currency-exchange-service/pom.xml
+++ b/03.microservices/currency-exchange-service/pom.xml
@@ -34,6 +34,11 @@
org.springframework.cloud
spring-cloud-starter-config
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
org.springframework.boot
spring-boot-starter-web
diff --git a/03.microservices/currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java b/03.microservices/currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java
index a2cfa381..2c3481b5 100644
--- a/03.microservices/currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java
+++ b/03.microservices/currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java
@@ -2,8 +2,10 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
+@EnableDiscoveryClient
public class CurrencyExchangeServiceApplication {
public static void main(String[] args) {
diff --git a/03.microservices/currency-exchange-service/src/main/resources/application.properties b/03.microservices/currency-exchange-service/src/main/resources/application.properties
index 78b15c1f..a3688a2e 100644
--- a/03.microservices/currency-exchange-service/src/main/resources/application.properties
+++ b/03.microservices/currency-exchange-service/src/main/resources/application.properties
@@ -2,4 +2,6 @@ spring.application.name=currency-exchange-service
server.port=8000
spring.jpa.show-sql=true
-spring.h2.console.enabled=true
\ No newline at end of file
+spring.h2.console.enabled=true
+
+eureka.client.service-url.default-zone=http://localhost:8761/eureka
\ No newline at end of file
diff --git a/03.microservices/netflix-eureka-naming-server/.DS_Store b/03.microservices/netflix-eureka-naming-server/.DS_Store
new file mode 100644
index 00000000..5008ddfc
Binary files /dev/null and b/03.microservices/netflix-eureka-naming-server/.DS_Store differ
diff --git a/03.microservices/netflix-eureka-naming-server/pom.xml b/03.microservices/netflix-eureka-naming-server/pom.xml
new file mode 100644
index 00000000..a2313ba3
--- /dev/null
+++ b/03.microservices/netflix-eureka-naming-server/pom.xml
@@ -0,0 +1,114 @@
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ netflix-eureka-naming-server
+ 0.0.1-SNAPSHOT
+ jar
+
+ netflix-eureka-naming-server
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
diff --git a/03.microservices/netflix-eureka-naming-server/src/main/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplication.java b/03.microservices/netflix-eureka-naming-server/src/main/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplication.java
new file mode 100644
index 00000000..5b8f2fac
--- /dev/null
+++ b/03.microservices/netflix-eureka-naming-server/src/main/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplication.java
@@ -0,0 +1,14 @@
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+@SpringBootApplication
+@EnableEurekaServer
+public class NetflixEurekaNamingServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(NetflixEurekaNamingServerApplication.class, args);
+ }
+}
diff --git a/03.microservices/netflix-eureka-naming-server/src/main/resources/application.properties b/03.microservices/netflix-eureka-naming-server/src/main/resources/application.properties
new file mode 100644
index 00000000..61d9e1bd
--- /dev/null
+++ b/03.microservices/netflix-eureka-naming-server/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+
+spring.application.name=netflix-eureka-naming-server
+server.port=8761
+
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
\ No newline at end of file
diff --git a/03.microservices/netflix-eureka-naming-server/src/test/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplicationTests.java b/03.microservices/netflix-eureka-naming-server/src/test/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplicationTests.java
new file mode 100644
index 00000000..265d4494
--- /dev/null
+++ b/03.microservices/netflix-eureka-naming-server/src/test/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplicationTests.java
@@ -0,0 +1,16 @@
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class NetflixEurekaNamingServerApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/03.microservices/step25.md b/03.microservices/step25.md
new file mode 100644
index 00000000..27691f16
--- /dev/null
+++ b/03.microservices/step25.md
@@ -0,0 +1,1283 @@
+
+## Complete Code Example
+
+
+### /currency-conversion-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ currency-conversion-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ currency-conversion-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionBean.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import java.math.BigDecimal;
+
+public class CurrencyConversionBean {
+ private Long id;
+ private String from;
+ private String to;
+ private BigDecimal conversionMultiple;
+ private BigDecimal quantity;
+ private BigDecimal totalCalculatedAmount;
+ private int port;
+
+ public CurrencyConversionBean() {
+
+ }
+
+ public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,
+ BigDecimal totalCalculatedAmount, int port) {
+ super();
+ this.id = id;
+ this.from = from;
+ this.to = to;
+ this.conversionMultiple = conversionMultiple;
+ this.quantity = quantity;
+ this.totalCalculatedAmount = totalCalculatedAmount;
+ this.port = port;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public void setTo(String to) {
+ this.to = to;
+ }
+
+ public BigDecimal getConversionMultiple() {
+ return conversionMultiple;
+ }
+
+ public void setConversionMultiple(BigDecimal conversionMultiple) {
+ this.conversionMultiple = conversionMultiple;
+ }
+
+ public BigDecimal getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(BigDecimal quantity) {
+ this.quantity = quantity;
+ }
+
+ public BigDecimal getTotalCalculatedAmount() {
+ return totalCalculatedAmount;
+ }
+
+ public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) {
+ this.totalCalculatedAmount = totalCalculatedAmount;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionController.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+public class CurrencyConversionController {
+
+ @Autowired
+ private CurrencyExchangeServiceProxy proxy;
+
+ @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")
+ public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,
+ @PathVariable BigDecimal quantity) {
+
+ // Feign - Problem 1
+ Map uriVariables = new HashMap<>();
+ uriVariables.put("from", from);
+ uriVariables.put("to", to);
+
+ ResponseEntity responseEntity = new RestTemplate().getForEntity(
+ "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class,
+ uriVariables);
+
+ CurrencyConversionBean response = responseEntity.getBody();
+
+ return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
+ quantity.multiply(response.getConversionMultiple()), response.getPort());
+ }
+
+ @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}")
+ public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to,
+ @PathVariable BigDecimal quantity) {
+
+ CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to);
+
+ return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
+ quantity.multiply(response.getConversionMultiple()), response.getPort());
+ }
+
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableFeignClients("com.in28minutes.microservices.currencyconversionservice")
+public class CurrencyConversionServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CurrencyConversionServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyExchangeServiceProxy.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.cloud.netflix.ribbon.RibbonClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+//@FeignClient(name="currency-exchange-service", url="localhost:8000")
+@FeignClient(name="currency-exchange-service")
+@RibbonClient(name="currency-exchange-service")
+public interface CurrencyExchangeServiceProxy {
+ @GetMapping("/currency-exchange/from/{from}/to/{to}")
+ public CurrencyConversionBean retrieveExchangeValue
+ (@PathVariable("from") String from, @PathVariable("to") String to);
+}
+```
+---
+
+### /currency-conversion-service/src/main/resources/application.properties
+
+```properties
+spring.application.name=currency-conversion-service
+server.port=8100
+currency-exchange-service.ribbon.listOfServers=http://localhost:8000,http://localhost:8001
+```
+---
+
+### /currency-conversion-service/src/test/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CurrencyConversionServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /currency-exchange-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ currency-exchange-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ currency-exchange-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeController.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class CurrencyExchangeController {
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private ExchangeValueRepository repository;
+
+ @GetMapping("/currency-exchange/from/{from}/to/{to}")
+ public ExchangeValue retrieveExchangeValue
+ (@PathVariable String from, @PathVariable String to){
+
+ ExchangeValue exchangeValue =
+ repository.findByFromAndTo(from, to);
+
+ exchangeValue.setPort(
+ Integer.parseInt(environment.getProperty("local.server.port")));
+
+ return exchangeValue;
+ }
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CurrencyExchangeServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CurrencyExchangeServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/ExchangeValue.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class ExchangeValue {
+
+ @Id
+ private Long id;
+
+ @Column(name="currency_from")
+ private String from;
+
+ @Column(name="currency_to")
+ private String to;
+
+ private BigDecimal conversionMultiple;
+ private int port;
+
+ public ExchangeValue() {
+
+ }
+
+
+ public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
+ super();
+ this.id = id;
+ this.from = from;
+ this.to = to;
+ this.conversionMultiple = conversionMultiple;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public BigDecimal getConversionMultiple() {
+ return conversionMultiple;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/ExchangeValueRepository.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ExchangeValueRepository extends
+ JpaRepository{
+ ExchangeValue findByFromAndTo(String from, String to);
+}
+```
+---
+
+### /currency-exchange-service/src/main/resources/application.properties
+
+```properties
+spring.application.name=currency-exchange-service
+server.port=8000
+
+spring.jpa.show-sql=true
+spring.h2.console.enabled=true
+```
+---
+
+### /currency-exchange-service/src/main/resources/data.sql
+
+```
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10001,'USD','INR',65,0);
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10002,'EUR','INR',75,0);
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10003,'AUD','INR',25,0);
+```
+---
+
+### /currency-exchange-service/src/test/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CurrencyExchangeServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /git-localconfig-repo/limits-service-dev.properties
+
+```properties
+limits-service.minimum=1
+```
+---
+
+### /git-localconfig-repo/limits-service-qa.properties
+
+```properties
+limits-service.minimum=2
+limits-service.maximum=222
+```
+---
+
+### /git-localconfig-repo/limits-service.properties
+
+```properties
+limits-service.minimum=8
+limits-service.maximum=888
+```
+---
+
+### /limits-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ limits-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ limits-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/bean/LimitConfiguration.java
+
+```java
+package com.in28minutes.microservices.limitsservice.bean;
+
+public class LimitConfiguration {
+ private int maximum;
+ private int minimum;
+
+ protected LimitConfiguration() {
+
+ }
+
+ public LimitConfiguration(int maximum, int minimum) {
+ super();
+ this.maximum = maximum;
+ this.minimum = minimum;
+ }
+
+ public int getMaximum() {
+ return maximum;
+ }
+
+ public int getMinimum() {
+ return minimum;
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/Configuration.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("limits-service")
+public class Configuration {
+
+ private int minimum;
+ private int maximum;
+
+ public void setMinimum(int minimum) {
+ this.minimum = minimum;
+ }
+
+ public void setMaximum(int maximum) {
+ this.maximum = maximum;
+ }
+
+ public int getMinimum() {
+ return minimum;
+ }
+
+ public int getMaximum() {
+ return maximum;
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/LimitsConfigurationController.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.in28minutes.microservices.limitsservice.bean.LimitConfiguration;
+
+@RestController
+public class LimitsConfigurationController {
+
+ @Autowired
+ private Configuration configuration;
+
+ @GetMapping("/limits")
+ public LimitConfiguration retrieveLimitsFromConfigurations() {
+ return new LimitConfiguration(configuration.getMaximum(),
+ configuration.getMinimum());
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/LimitsServiceApplication.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LimitsServiceApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(LimitsServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /limits-service/src/main/resources/bootstrap.properties
+
+```properties
+spring.application.name=limits-service
+spring.cloud.config.uri=http://localhost:8888
+spring.profiles.active=qa
+```
+---
+
+### /limits-service/src/test/java/com/in28minutes/microservices/limitsservice/LimitsServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class LimitsServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /netflix-eureka-naming-server/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ netflix-eureka-naming-server
+ 0.0.1-SNAPSHOT
+ jar
+
+ netflix-eureka-naming-server
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /netflix-eureka-naming-server/src/main/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplication.java
+
+```java
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+@SpringBootApplication
+@EnableEurekaServer
+public class NetflixEurekaNamingServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(NetflixEurekaNamingServerApplication.class, args);
+ }
+}
+```
+---
+
+### /netflix-eureka-naming-server/src/main/resources/application.properties
+
+```properties
+
+spring.application.name=netflix-eureka-naming-server
+server.port=8761
+
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+```
+---
+
+### /netflix-eureka-naming-server/src/test/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplicationTests.java
+
+```java
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class NetflixEurekaNamingServerApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /spring-cloud-config-server/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ spring-cloud-config-server
+ 0.0.1-SNAPSHOT
+ jar
+
+ spring-cloud-config-server
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /spring-cloud-config-server/src/main/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplication.java
+
+```java
+package com.in28minutes.microservices.springcloudconfigserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+@EnableConfigServer
+@SpringBootApplication
+public class SpringCloudConfigServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringCloudConfigServerApplication.class, args);
+ }
+}
+```
+---
+
+### /spring-cloud-config-server/src/main/resources/application.properties
+
+```properties
+spring.application.name=spring-cloud-config-server
+server.port=8888
+spring.cloud.config.server.git.uri=file:///in28Minutes/git/spring-micro-services/03.microservices/git-localconfig-repo
+```
+---
+
+### /spring-cloud-config-server/src/test/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplicationTests.java
+
+```java
+package com.in28minutes.microservices.springcloudconfigserver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringCloudConfigServerApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
diff --git a/03.microservices/step25.zip b/03.microservices/step25.zip
new file mode 100644
index 00000000..b95839ef
Binary files /dev/null and b/03.microservices/step25.zip differ
diff --git a/03.microservices/step29.md b/03.microservices/step29.md
new file mode 100644
index 00000000..dd81d07f
--- /dev/null
+++ b/03.microservices/step29.md
@@ -0,0 +1,1300 @@
+
+## Complete Code Example
+
+
+### /currency-conversion-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ currency-conversion-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ currency-conversion-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionBean.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import java.math.BigDecimal;
+
+public class CurrencyConversionBean {
+ private Long id;
+ private String from;
+ private String to;
+ private BigDecimal conversionMultiple;
+ private BigDecimal quantity;
+ private BigDecimal totalCalculatedAmount;
+ private int port;
+
+ public CurrencyConversionBean() {
+
+ }
+
+ public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,
+ BigDecimal totalCalculatedAmount, int port) {
+ super();
+ this.id = id;
+ this.from = from;
+ this.to = to;
+ this.conversionMultiple = conversionMultiple;
+ this.quantity = quantity;
+ this.totalCalculatedAmount = totalCalculatedAmount;
+ this.port = port;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public void setTo(String to) {
+ this.to = to;
+ }
+
+ public BigDecimal getConversionMultiple() {
+ return conversionMultiple;
+ }
+
+ public void setConversionMultiple(BigDecimal conversionMultiple) {
+ this.conversionMultiple = conversionMultiple;
+ }
+
+ public BigDecimal getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(BigDecimal quantity) {
+ this.quantity = quantity;
+ }
+
+ public BigDecimal getTotalCalculatedAmount() {
+ return totalCalculatedAmount;
+ }
+
+ public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) {
+ this.totalCalculatedAmount = totalCalculatedAmount;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionController.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+public class CurrencyConversionController {
+
+ @Autowired
+ private CurrencyExchangeServiceProxy proxy;
+
+ @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")
+ public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,
+ @PathVariable BigDecimal quantity) {
+
+ // Feign - Problem 1
+ Map uriVariables = new HashMap<>();
+ uriVariables.put("from", from);
+ uriVariables.put("to", to);
+
+ ResponseEntity responseEntity = new RestTemplate().getForEntity(
+ "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class,
+ uriVariables);
+
+ CurrencyConversionBean response = responseEntity.getBody();
+
+ return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
+ quantity.multiply(response.getConversionMultiple()), response.getPort());
+ }
+
+ @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}")
+ public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to,
+ @PathVariable BigDecimal quantity) {
+
+ CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to);
+
+ return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
+ quantity.multiply(response.getConversionMultiple()), response.getPort());
+ }
+
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableFeignClients("com.in28minutes.microservices.currencyconversionservice")
+@EnableDiscoveryClient
+public class CurrencyConversionServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CurrencyConversionServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyExchangeServiceProxy.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.cloud.netflix.ribbon.RibbonClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+//@FeignClient(name="currency-exchange-service", url="localhost:8000")
+@FeignClient(name="currency-exchange-service")
+@RibbonClient(name="currency-exchange-service")
+public interface CurrencyExchangeServiceProxy {
+ @GetMapping("/currency-exchange/from/{from}/to/{to}")
+ public CurrencyConversionBean retrieveExchangeValue
+ (@PathVariable("from") String from, @PathVariable("to") String to);
+}
+```
+---
+
+### /currency-conversion-service/src/main/resources/application.properties
+
+```properties
+spring.application.name=currency-conversion-service
+server.port=8100
+eureka.client.service-url.default-zone=http://localhost:8761/eureka
+#currency-exchange-service.ribbon.listOfServers=http://localhost:8000,http://localhost:8001
+```
+---
+
+### /currency-conversion-service/src/test/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.currencyconversionservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CurrencyConversionServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /currency-exchange-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ currency-exchange-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ currency-exchange-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeController.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class CurrencyExchangeController {
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private ExchangeValueRepository repository;
+
+ @GetMapping("/currency-exchange/from/{from}/to/{to}")
+ public ExchangeValue retrieveExchangeValue
+ (@PathVariable String from, @PathVariable String to){
+
+ ExchangeValue exchangeValue =
+ repository.findByFromAndTo(from, to);
+
+ exchangeValue.setPort(
+ Integer.parseInt(environment.getProperty("local.server.port")));
+
+ return exchangeValue;
+ }
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplication.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+@SpringBootApplication
+@EnableDiscoveryClient
+public class CurrencyExchangeServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CurrencyExchangeServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/ExchangeValue.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class ExchangeValue {
+
+ @Id
+ private Long id;
+
+ @Column(name="currency_from")
+ private String from;
+
+ @Column(name="currency_to")
+ private String to;
+
+ private BigDecimal conversionMultiple;
+ private int port;
+
+ public ExchangeValue() {
+
+ }
+
+
+ public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
+ super();
+ this.id = id;
+ this.from = from;
+ this.to = to;
+ this.conversionMultiple = conversionMultiple;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public BigDecimal getConversionMultiple() {
+ return conversionMultiple;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+}
+```
+---
+
+### /currency-exchange-service/src/main/java/com/in28minutes/microservices/currencyexchangeservice/ExchangeValueRepository.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ExchangeValueRepository extends
+ JpaRepository{
+ ExchangeValue findByFromAndTo(String from, String to);
+}
+```
+---
+
+### /currency-exchange-service/src/main/resources/application.properties
+
+```properties
+spring.application.name=currency-exchange-service
+server.port=8000
+
+spring.jpa.show-sql=true
+spring.h2.console.enabled=true
+
+eureka.client.service-url.default-zone=http://localhost:8761/eureka
+```
+---
+
+### /currency-exchange-service/src/main/resources/data.sql
+
+```
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10001,'USD','INR',65,0);
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10002,'EUR','INR',75,0);
+insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
+values(10003,'AUD','INR',25,0);
+```
+---
+
+### /currency-exchange-service/src/test/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.currencyexchangeservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CurrencyExchangeServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /git-localconfig-repo/limits-service-dev.properties
+
+```properties
+limits-service.minimum=1
+```
+---
+
+### /git-localconfig-repo/limits-service-qa.properties
+
+```properties
+limits-service.minimum=2
+limits-service.maximum=222
+```
+---
+
+### /git-localconfig-repo/limits-service.properties
+
+```properties
+limits-service.minimum=8
+limits-service.maximum=888
+```
+---
+
+### /limits-service/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ limits-service
+ 0.0.1-SNAPSHOT
+ jar
+
+ limits-service
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/bean/LimitConfiguration.java
+
+```java
+package com.in28minutes.microservices.limitsservice.bean;
+
+public class LimitConfiguration {
+ private int maximum;
+ private int minimum;
+
+ protected LimitConfiguration() {
+
+ }
+
+ public LimitConfiguration(int maximum, int minimum) {
+ super();
+ this.maximum = maximum;
+ this.minimum = minimum;
+ }
+
+ public int getMaximum() {
+ return maximum;
+ }
+
+ public int getMinimum() {
+ return minimum;
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/Configuration.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("limits-service")
+public class Configuration {
+
+ private int minimum;
+ private int maximum;
+
+ public void setMinimum(int minimum) {
+ this.minimum = minimum;
+ }
+
+ public void setMaximum(int maximum) {
+ this.maximum = maximum;
+ }
+
+ public int getMinimum() {
+ return minimum;
+ }
+
+ public int getMaximum() {
+ return maximum;
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/LimitsConfigurationController.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.in28minutes.microservices.limitsservice.bean.LimitConfiguration;
+
+@RestController
+public class LimitsConfigurationController {
+
+ @Autowired
+ private Configuration configuration;
+
+ @GetMapping("/limits")
+ public LimitConfiguration retrieveLimitsFromConfigurations() {
+ return new LimitConfiguration(configuration.getMaximum(),
+ configuration.getMinimum());
+ }
+
+}
+```
+---
+
+### /limits-service/src/main/java/com/in28minutes/microservices/limitsservice/LimitsServiceApplication.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LimitsServiceApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(LimitsServiceApplication.class, args);
+ }
+}
+```
+---
+
+### /limits-service/src/main/resources/bootstrap.properties
+
+```properties
+spring.application.name=limits-service
+spring.cloud.config.uri=http://localhost:8888
+spring.profiles.active=qa
+```
+---
+
+### /limits-service/src/test/java/com/in28minutes/microservices/limitsservice/LimitsServiceApplicationTests.java
+
+```java
+package com.in28minutes.microservices.limitsservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class LimitsServiceApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /netflix-eureka-naming-server/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ netflix-eureka-naming-server
+ 0.0.1-SNAPSHOT
+ jar
+
+ netflix-eureka-naming-server
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /netflix-eureka-naming-server/src/main/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplication.java
+
+```java
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+@SpringBootApplication
+@EnableEurekaServer
+public class NetflixEurekaNamingServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(NetflixEurekaNamingServerApplication.class, args);
+ }
+}
+```
+---
+
+### /netflix-eureka-naming-server/src/main/resources/application.properties
+
+```properties
+
+spring.application.name=netflix-eureka-naming-server
+server.port=8761
+
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+```
+---
+
+### /netflix-eureka-naming-server/src/test/java/com/in28minutes/microservices/netflixeurekanamingserver/NetflixEurekaNamingServerApplicationTests.java
+
+```java
+package com.in28minutes.microservices.netflixeurekanamingserver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class NetflixEurekaNamingServerApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
+
+### /spring-cloud-config-server/pom.xml
+
+```xml
+
+
+ 4.0.0
+
+ com.in28minutes.microservices
+ spring-cloud-config-server
+ 0.0.1-SNAPSHOT
+ jar
+
+ spring-cloud-config-server
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.M3
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.M2
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+```
+---
+
+### /spring-cloud-config-server/src/main/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplication.java
+
+```java
+package com.in28minutes.microservices.springcloudconfigserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+@EnableConfigServer
+@SpringBootApplication
+public class SpringCloudConfigServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringCloudConfigServerApplication.class, args);
+ }
+}
+```
+---
+
+### /spring-cloud-config-server/src/main/resources/application.properties
+
+```properties
+spring.application.name=spring-cloud-config-server
+server.port=8888
+spring.cloud.config.server.git.uri=file:///in28Minutes/git/spring-micro-services/03.microservices/git-localconfig-repo
+```
+---
+
+### /spring-cloud-config-server/src/test/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplicationTests.java
+
+```java
+package com.in28minutes.microservices.springcloudconfigserver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringCloudConfigServerApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
+```
+---
diff --git a/03.microservices/step29.zip b/03.microservices/step29.zip
new file mode 100644
index 00000000..106054ad
Binary files /dev/null and b/03.microservices/step29.zip differ