Skip to content

Latest commit

 

History

History
2004 lines (1634 loc) · 55.2 KB

File metadata and controls

2004 lines (1634 loc) · 55.2 KB

TODO

  • Section Introduction to Web Services --- If you already did our course on spring web services, you can directly jump to section on Microservices
  • Monolith Applications!
  • Updates to Step 29 - Overview of Connecting RESTful Service to JPA

Introduction to the Course

0001 - Microservices and RESTful APIs with Spring Boot and Spring Cloud - Preview 0002 - Microservices and RESTful APIs with Spring Boot and Spring Cloud - Course Overview 0003 - Microservices and RESTful APIs with Spring Boot and Spring Cloud - Git Repository 0004 - Microservices and RESTful APIs with Spring Boot and Spring Cloud - Installing Basic Tools

Introduction to Web Services

What is a Web Service? Important How Questions related to Web Services Web Services - Key Terminology Introduction to SOAP Web Services Introduction to RESTful Web Services SOAP vs RESTful Web Services

Restful Web Services with Spring Boot

0005 - Section Introduction 02 - RESTful Web Services Step 01 - Initializing a RESTful Services Project with Spring Boot Step 02 - Understanding the RESTful Services we would create in this course Step 03 - Creating a Hello World Service Step 04 - Enhancing the Hello World Service to return a Bean Step 05 - Quick Review of Spring Boot Auto Configuration and Dispatcher Servlet Step 06 - Enhancing the Hello World Service with a Path Variable Step 07 - Creating User Bean and User Service Step 08 - Implementing GET Methods for User Resource Step 09 - Implementing POST Method to create User Resource Step 10 - Enhancing POST Method to return correct HTTP Status Code and Location Step 11 - Implementing Exception Handling - 404 Resource Not Found Step 12 - Implementing Generic Exception Handling for all Resources Step 13 - Exercise : User Post Resource and Exception Handling Step 14 - Implementing DELETE Method to delete a User Resource Step 15 - Implementing Validations for RESTful Services Step 16 - Implementing HATEOAS for RESTful Services Step 17 - Overview of Advanced RESTful Service Features Step 18 - Internationalization for RESTful Services Step 19 - Content Negotiation - Implementing Support for XML Step 20 - Configuring Auto Generation of Swagger Documentation Step 21 - Introduction to Swagger Documentation Format Step 22 - Enhancing Swagger Documentation with Custom Annotations Step 23 - Monitoring APIs with Spring Boot Actuator Step 24 - Implementing Static Filtering for RESTful Service Step 25 - Implementing Dynamic Filtering for RESTful Service Step 26 - Versioning RESTful Services - Basic Approach with URIs Step 27 - Versioning RESTful Services - Header and Content Negotiation Approach Step 28 - Implementing Basic Authentication with Spring Security Step 29 - Overview of Connecting RESTful Service to JPA Step 30 - Creating User Entity and some test data Step 31 - Updating GET methods on User Resource to use JPA Step 32 - Updating POST and DELETE methods on User Resource to use JPA Step 33 - Creating Post Entity and Many to One Relationship with User Entity Step 34 - Implementing a GET service to retrieve all Posts of a User Step 35 - Implementing a POST service to create a Post for a User Step 36 - Richardson Maturity Model Step 37 - RESTful Web Services - Best Practices

Microservices with Spring Cloud

0005 - Section Introduction 03 - Microservices with Spring Cloud Step 00 - 01 - Introduction to Microservices Step 00 - 02 - Challenges with Microservices Step 00 - 03 - Introduction to Spring Cloud Step 00 - 04 - Advantages of Microservices Architectures Step 00 - 05 - Microservice Components - Standardizing Ports and URL Step 01 - Part 1 - Introduction to Limits Microservice and Spring Cloud Config Server Step 01 - Part 2 - Setting up Limits Microservice Step 02 - Creating a hard coded limits service Step 03 - Enhance limits service to pick up configuration from application properties Step 04 - Setting up Spring Cloud Config Server Step 05 - Installing Git Step 06 - Creating Local Git Repository Step 07 - Connect Spring Cloud Config Server to Local Git Repository Step 08 - Configuration for Multiple Environments in Git Repository Step 09 - Connect Limits Service to Spring Cloud Config Server Step 10 - Configuring Profiles for Limits Service Step 11 - A review of Spring Cloud Config Server Step 12 - Introduction to Currency Conversion and Currency Exchange Microservices Step 13 - Setting up Currency Exchange Microservice Step 14 - Create a simple hard coded currency exchange service Step 15 - Setting up Dynamic Port in the the Response Step 16 - Configure JPA and Initialized Data Step 17 - Create a JPA Repository Step 18 - Setting up Currency Conversion Microservice Step 19 - Creating a service for currency conversion Step 20 - Invoking Currency Exchange Microservice from Currency Conversion Microservice Step 21 - Using Feign REST Client for Service Invocation Step 22 - Setting up client side load balancing with Ribbon Step 23 - Running client side load balancing with Ribbon Step 24 - Understand the need for a Naming Server Step 25 - Setting up Eureka Naming Server Step 26 - Connecting Currency Conversion Microservice to Eureka Step 27 - Connecting Currency Exchange Microservice to Eureka Step 28 - Distributing calls using Eureka and Ribbon Step 29 - A review of implementing Eureka, Ribbon and Feign Step 30 - Introduction to API Gateways Step 31 - Setting up Zuul API Gateway Step 32 - Implementing Zuul Logging Filter Step 33 - Executing a request through Zuul API Gateway Step 34 - Setting up Zuul API Gateway between microservice invocations Step 35 - Introduction to Distributed Tracing Step 36 - Implementing Spring Cloud Sleuth Step 37 - Introduction to Distributed Tracing with Zipkin Step 38 - Installing Rabbit MQ Step 39 - Setting up Distributed Tracing with Zipkin Step 40 - Connecting microservices to Zipkin Step 41 - Using Zipkin UI Dashboard to trace requests Step 42 - Understanding the need for Spring Cloud Bus Step 43 - Implementing Spring Cloud Bus Step 44 - Fault Tolerance with Hystrix Step 99 - FAQ 01 - Microservices Characteristics Step 99 - FAQ 02 - What do you do next?

9999 - Microservices and RESTful APIs with Spring Boot and Spring Cloud - Conclusion

Appendix - Introduction to Spring Boot in 10 Steps

0005 - Section Introduction 04 - Introduction to Spring Boot in 10 Steps Step 1 : Introduction to Spring Boot - Goals and Important Features Step 2 : Developing Spring Applications before Spring Boot Step 3 : Using Spring Initializr to create Step 4 : Creating a Simple REST Controller Step 5 : What is Spring Boot Auto Configuration? Step 6 : Spring Boot vs Spring vs Spring MVC Step 7 : Spring Boot Starter Projects - Starter Web and Starter JPA Step 8 : Overview of different Spring Boot Starter Projects Step 9 : Spring Boot Actuator Step 10 : Spring Boot Developer Tools

Appendix - Introduction to JPA in 10 Steps

0005 - Section Introduction 05 - Introduction to JPA in 10 Steps Introduction to JPA - An Overview Step 1 : Object Relational Impedence Mismatch Step 2 : World before JPA - JDBC, Spring JDBC and myBatis Step 3 : Introduction to JPA Step 4 : Creating a JPA Project using Spring Initializr Step 5 : Defining a JPA Entity - User Step 6 : Defining a Service to manage the Entity - UserService and EntityManager Step 7 : Using a Command Line Runner to save the User to database. Step 8 : Magic of Spring Boot and In Memory Database H2 Step 9 : Introduction to Spring Data JPA Step 10 : More JPA Repository : findById and findAll

Versions

  • 1.5.2.RELEASE
  • Dalston.RC1

URLs

Application URL
Limits Service http://localhost:8080/limits
Spring Cloud Config Server http://localhost:8888/limits-service/default http://localhost:8888/limits-service/dev
Currency Converter Service - Direct Call http://localhost:8100/currency-converter/from/USD/to/INR//usr/local/var/log/rabbitmq/rabbit@localhost.log/usr/local/var/log/rabbitmq/rabbit@localhost.logquantity/10
Currency Converter Service - Feign http://localhost:8100/currency-converter-feign/from/EUR/to/INR/quantity/10000
Currency Exchange Service http://localhost:8000/currency-exchange/from/EUR/to/INR http://localhost:8001/currency-exchange/from/USD/to/INR
Eureka http://localhost:8761/
Zuul - Currency Exchange & Exchange Services http://localhost:8765/currency-exchange-service/currency-exchange/from/EUR/to/INR http://localhost:8765/currency-conversion-service/currency-converter-feign/from/USD/to/INR/quantity/10

VM Argument

-Dserver.port=8001

Commands

  • mkdir git-configuration-repo
  • cd git-configuration-repo/
  • git init
  • git add -A
  • git commit -m "first commit"

Ports

Application Port
Limits Service 8080, 8081, ...
Spring Cloud Config Server 8888
Currency Exchange Service 8000, 8001, 8002, ..
Currency Conversion Service 8100, 8101, 8102, ...
Netflix Eureka Naming Server 8761
Netflix Zuul API Gateway Server 8765
Zipkin Distributed Tracing Server 9411

Diagrams



MicroserviceCommunication
~~~~~~~~~~~~~~~~~~~~~~~~~
digraph architecture {
  rankdir=TB;
{rank=same; MovieService, CustomerService, ReviewService, BookingService, FareCalculationService};
DB1,DB2,DB3,DB4,DB5[shape=cylinder]
MovieService, CustomerService, ReviewService, BookingService, FareCalculationService[shape=component]

  MovieService->DB1;
  CustomerService->DB2;
ReviewService->DB3;
BookingService ->DB4;
FareCalculationService ->DB5;


}

digraph architecture {
  rankdir=TB;
{rank=same; MovieApplication};
LARGEDB[shape=cylinder];
  MovieApplication->LARGEDB;

}

digraph architecture {
  rankdir=TB;
{rank=same; CurrencyCalculationService, CurrencyExchangeService, LimitsService};
Configuration[shape=cylinder]
Database[shape=cylinder]
LimitsService, CurrencyCalculationService, CurrencyExchangeService[shape=component]

  CurrencyCalculationService -> CurrencyExchangeService -> LimitsService;
  
  CurrencyExchangeService->Database;
  LimitsService->Configuration;

}

Microservices-Environments
~~~~~~~~~~~~~~~~~~~~~~~~~~~`
digraph architecture {
  rankdir=LR;

node[shape=record]
LimitsService, CurrencyCalculationService, CurrencyExchangeService[shape=component]

  CurrencyCalculationService -> CurrencyExchangeService -> LimitsService

  subgraph CurrencyCalculationService {
      {rank=same; CurrencyCalculationService,CCDEV,CCQA,CCSTAGE, CCPROD};
  }
 
  subgraph CurrencyExchangeService {
      CurrencyExchangeService;
      {rank=same; CurrencyExchangeService,CEDEV,CEQA, CESTAGE, CEPROD};
  }
  
  subgraph LimitsService {
      CurrencyExchangeService;
      {rank=same; LimitsService,LSDEV,LSQA, LSSTAGE, LSPROD};
  }
 
}


SpringCloudConfigServer
#######################
digraph architecture {
rankdir = TB;
node[shape=component]
Git[shape=cylinder]
{rank=same; CurrencyCalculationService, CurrencyExchangeService, LimitsService};
CurrencyExchangeService -> SpringCloudConfigServer;
CurrencyCalculationService -> SpringCloudConfigServer;
LimitsService -> SpringCloudConfigServer
SpringCloudConfigServer -> Git

}

EUREKANAMINGSERVER
#######################
digraph architecture {
rankdir = TB;
node[shape=component]
{rank=same; CurrencyCalculationService, CurrencyExchangeService, LimitsService};
CurrencyExchangeService -> EurekaNamingServer;
CurrencyCalculationService -> EurekaNamingServer;
LimitsService -> EurekaNamingServer
}

RibbonClientSideLoadBalancing
#######################
digraph architecture {
rankdir = TB;
node[shape=component]
Ribbon[shape=underline]

{rank=same; CurrencyExchangeService1, CurrencyExchangeService2, CurrencyExchangeService3};
{rank=same; Ribbon, NamingServer };
Ribbon -> CurrencyExchangeService1
Ribbon -> CurrencyExchangeService2
Ribbon -> CurrencyExchangeService3
CurrencyCalculationService -> Ribbon
Ribbon -> NamingServer

}

ZipkinDistributedTracingServer
###############################
digraph architecture {
rankdir = TB;
node[shape=component]
Database[shape=cylinder]
RabbitMQ[shape=underline]
{rank=same; CurrencyCalculationService, CurrencyExchangeService, LimitsService};
CurrencyExchangeService -> RabbitMQ
CurrencyCalculationService -> RabbitMQ;
LimitsService -> RabbitMQ
RabbitMQ -> ZipkinDistributedTracingServer
ZipkinDistributedTracingServer -> Database

}

CurrencyExchangeMicroserviceDeployment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~``
digraph architecture {
rankdir = TB;
node[shape=record]
{rank=same; DEV, QA, STAGE, PROD};

DEV -> DEV1

QA -> QA1
QA -> QA2

STAGE -> STAGE1

PROD -> PROD1
PROD -> PROD2
PROD -> PROD3
PROD -> PROD4

}

CurrencyConversionMicroserviceDeployment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~``
digraph architecture {
rankdir = TB;
node[shape=record]
{rank=same; DEV, QA, STAGE, PROD};

DEV -> DEV1

QA -> QA1
QA -> QA2

STAGE -> STAGE1

PROD -> PROD1

}


Complete Code Example

/config-example-service/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>config-example-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>config-example-service</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Dalston.SR3</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

/config-example-service/src/main/java/com/in28minutes/microservices/configexampleservice/ConfigExampleServiceApplication.java

package com.in28minutes.microservices.configexampleservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConfigExampleServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigExampleServiceApplication.class, args);
	}
}

/config-example-service/src/main/java/com/in28minutes/microservices/configexampleservice/ConfigurationController.java

package com.in28minutes.microservices.configexampleservice;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigurationController {

	@Autowired
	private Configuration configuration;

	@GetMapping("/limits")
	public Limit retrieveLimits() {
		Limit limit = new Limit();
		limit.setMinimum(configuration.getMinimum());
		limit.setMaximum(configuration.getMaximum());
		return limit;
	}

}

class Limit {
	private int maximum;
	private int minimum;

	public int getMaximum() {
		return maximum;
	}

	public int getMinimum() {
		return minimum;
	}

	public void setMaximum(int maximum) {
		this.maximum = maximum;
	}

	public void setMinimum(int minimum) {
		this.minimum = minimum;
	}

}

@Component
@ConfigurationProperties("config")
class Configuration {
	private int minimum;
	private int maximum;

	public int getMinimum() {
		return minimum;
	}

	public void setMinimum(int minimum) {
		this.minimum = minimum;
	}

	public int getMaximum() {
		return maximum;
	}

	public void setMaximum(int maximum) {
		this.maximum = maximum;
	}

}

/config-example-service/src/main/resources/bootstrap.properties

#config.maximum=100
#config.minimum=10

spring.application.name=limits-service
spring.cloud.config.uri=http://localhost:8888
spring.profiles.active=qa
management.security.enabled=false

/config-example-service/src/test/java/com/in28minutes/microservices/configexampleservice/ConfigExampleServiceApplicationTests.java

package com.in28minutes.microservices.configexampleservice;

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 ConfigExampleServiceApplicationTests {

	@Test
	public void contextLoads() {
	}

}

/currency-conversion-service/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>currency-conversion-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>currency-conversion-service</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-sleuth</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-sleuth-zipkin</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>

	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>
	<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>

</project>

/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionBean.java

package com.in28minutes.microservices.currencyconversionservice;

import java.math.BigDecimal;

public class CurrencyConversionBean {
	private String fromCurrency;
	private String toCurrency;
	private BigDecimal inputAmount;
	private BigDecimal outputAmount;
	private Long id;

	public CurrencyConversionBean() {
		
	}
	
	public CurrencyConversionBean(Long id,String from, String to, BigDecimal inputValue, BigDecimal outputValue) {
		super();
		this.id = id;
		this.fromCurrency = from;
		this.toCurrency = to;
		this.inputAmount = inputValue;
		this.outputAmount = outputValue;
	}

	public String getFromCurrency() {
		return fromCurrency;
	}

	public String getToCurrency() {
		return toCurrency;
	}

	public BigDecimal getInputAmount() {
		return inputAmount;
	}

	public BigDecimal getOutputAmount() {
		return outputAmount;
	}

	public Long getId() {
		return id;
	}
}

/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionController.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;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class CurrencyConversionController {

	@Autowired
	CurrencyExchangeServiceProxy proxy;

	@HystrixCommand(fallbackMethod="getDefaultConversionResponse")
	@GetMapping("/currency-converter-direct/from/{from}/to/{to}/amount/{amount}")
	public CurrencyConversionBean conversion(@PathVariable String from, @PathVariable String to,
			@PathVariable BigDecimal amount) {

		Map<String, String> uriVariables = new HashMap<>();
		uriVariables.put("from", from);
		uriVariables.put("to", to);
		
		ResponseEntity<CurrencyConversionBean> responseEntity = new RestTemplate().getForEntity(
				"http://localhost:8000/currency-exchange/from/{from}/to/{to}",
				CurrencyConversionBean.class, uriVariables);

		return new CurrencyConversionBean(responseEntity.getBody().getId(),from, to, amount, responseEntity.getBody().getInputAmount().multiply(amount));
	}
	
	public CurrencyConversionBean getDefaultConversionResponse(String from, String to,
			 BigDecimal amount){
		return new CurrencyConversionBean(0L,from, to, BigDecimal.ONE, BigDecimal.ONE.multiply(amount));
	}

	@GetMapping("/currency-converter-feign/from/{from}/to/{to}/amount/{amount}")
	public CurrencyConversionBean conversionFeign(@PathVariable("from") String from, @PathVariable("to") String to,
			@PathVariable("amount") BigDecimal amount) {
		CurrencyConversionBean result = proxy.findByCurrencyFromAndCurrencyTo(from, to);

		return new CurrencyConversionBean(result.getId(),from, to, amount, result.getInputAmount().multiply(amount));
	}

}

/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.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;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients("com.in28minutes.microservices.currencyconversionservice")
public class CurrencyConversionServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(CurrencyConversionServiceApplication.class, args);
	}

	@Bean
	public AlwaysSampler defaultSampler() {
		return new AlwaysSampler();
	}

}

/currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyExchangeServiceProxy.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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

//@FeignClient(name = "currency-exchange-service", url = "localhost:8000")
//@FeignClient(name = "currency-exchange-service")
@FeignClient(name = "zuul-api-gateway-server")
@RibbonClient(name = "currency-exchange-service")
public interface CurrencyExchangeServiceProxy {
	//@RequestMapping(method=RequestMethod.GET, value = "/currency-exchange/from/{from}/to/{to}")
	@RequestMapping(method=RequestMethod.GET, value = "/currency-exchange-service/currency-exchange/from/{from}/to/{to}")
	CurrencyConversionBean findByCurrencyFromAndCurrencyTo(@PathVariable("from") String from,
			@PathVariable("to") String to);
}

/currency-conversion-service/src/main/resources/application.properties

server.port=8100
spring.application.name=currency-conversion-service

#currency-exchange-service.ribbon.listOfServers=http://localhost:8000,http://localhost:8001
eureka.client.service-url.default-zone=http://localhost:8761/eureka

/currency-conversion-service/src/test/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplicationTests.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/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>currency-exchange-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>currency-exchange-service</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-sleuth</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-sleuth-zipkin</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

	<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>

</project>

/currency-exchange/src/main/java/com/in28minutes/microservices/currencyexchange/CurrencyExchangeApplication.java

package com.in28minutes.microservices.currencyexchange;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableDiscoveryClient
public class CurrencyExchangeApplication {

	public static void main(String[] args) {
		SpringApplication.run(CurrencyExchangeApplication.class, args);
	}

	@Bean
	public AlwaysSampler defaultSampler() {
		return new AlwaysSampler();
	}

}

/currency-exchange/src/main/java/com/in28minutes/microservices/currencyexchange/entity/Currency.java

package com.in28minutes.microservices.currencyexchange.entity;

public enum Currency {
	INR,USD,EUR
}

/currency-exchange/src/main/java/com/in28minutes/microservices/currencyexchange/entity/ExchangeValue.java

package com.in28minutes.microservices.currencyexchange.entity;

import java.math.BigDecimal;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;

@Entity
public class ExchangeValue {
	
	@Id
	private Long id;
	
	@Enumerated(EnumType.STRING)
	private Currency currencyFrom;
	
	@Enumerated(EnumType.STRING)
	private Currency currencyTo;

	private BigDecimal inputAmount;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Currency getCurrencyFrom() {
		return currencyFrom;
	}

	public void setCurrencyFrom(Currency currencyFrom) {
		this.currencyFrom = currencyFrom;
	}

	public Currency getCurrencyTo() {
		return currencyTo;
	}

	public void setCurrencyTo(Currency currencyTo) {
		this.currencyTo = currencyTo;
	}

	public BigDecimal getInputAmount() {
		return inputAmount;
	}

	public void setInputAmount(BigDecimal inputAmount) {
		this.inputAmount = inputAmount;
	}
}

/currency-exchange/src/main/java/com/in28minutes/microservices/currencyexchange/entity/ExchangeValueController.java

package com.in28minutes.microservices.currencyexchange.entity;

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 ExchangeValueController {

	@Autowired
	ExchangeValueRepository repository;

	@Autowired
	Environment environment;
	
	@GetMapping("/currency-exchange/from/{from}/to/{to}")
	public ExchangeValue exchangeService(@PathVariable String from, @PathVariable String to) {
		ExchangeValue exchangeValue = repository.findByCurrencyFromAndCurrencyTo(Currency.valueOf(from), Currency.valueOf(to));
		exchangeValue.setId(Long.parseLong(environment.getProperty("local.server.port")));
		return exchangeValue;
	}

}

/currency-exchange/src/main/java/com/in28minutes/microservices/currencyexchange/entity/ExchangeValueRepository.java

package com.in28minutes.microservices.currencyexchange.entity;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ExchangeValueRepository extends JpaRepository<ExchangeValue, Long> {
	ExchangeValue findByCurrencyFromAndCurrencyTo(Currency from, Currency to);
}

/currency-exchange/src/main/resources/application.properties

server.port=8000
spring.application.name=currency-exchange-service

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

eureka.client.service-url.default-zone=http://localhost:8761/eureka

/currency-exchange/src/main/resources/data.sql

insert into exchange_value
values(10001, 'USD', 'INR', 65);
insert into exchange_value
values(10002, 'EUR', 'INR', 75);

/currency-exchange/src/test/java/com/in28minutes/microservices/currencyexchange/CurrencyExchangeApplicationTests.java

package com.in28minutes.microservices.currencyexchange;

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 CurrencyExchangeApplicationTests {

	@Test
	public void contextLoads() {
	}

}

/eureka-server/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>eureka-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>eureka-server</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>

/eureka-server/src/main/java/com/in28minutes/microservices/eurekaserver/EurekaServerApplication.java

package com.in28minutes.microservices.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}

/eureka-server/src/main/resources/application.properties

server.port=8761
spring.application.name=eureka-server

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

/eureka-server/src/test/java/com/in28minutes/microservices/eurekaserver/EurekaServerApplicationTests.java

package com.in28minutes.microservices.eurekaserver;

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 EurekaServerApplicationTests {

	@Test
	public void contextLoads() {
	}

}

/git-configuration-repo/limits-service-qa.properties

config.maximum=78
config.minimum=66

/git-configuration-repo/limits-service.properties

config.maximum=99
config.minimum=9

/spring-cloud-config-server/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>spring-cloud-config-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-cloud-config-server</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>

/spring-cloud-config-server/src/main/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplication.java

package com.in28minutes.microservices.springcloudconfigserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class SpringCloudConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudConfigServerApplication.class, args);
	}
}

/spring-cloud-config-server/src/main/resources/application.properties

server.port=8888
spring.application.name=spring-cloud-config-server

spring.cloud.config.server.git.uri=file:///in28Minutes/git/getting-started-in-5-steps/zzz-microservices/git-configuration-repo

/spring-cloud-config-server/src/test/java/com/in28minutes/microservices/springcloudconfigserver/SpringCloudConfigServerApplicationTests.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() {
	}

}

/zipkin-server/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>zipkin-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>zipkin-server</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
		</dependency>

		<dependency>
			<groupId>io.zipkin.java</groupId>
			<artifactId>zipkin-autoconfigure-ui</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>

/zipkin-server/src/main/java/com/in28minutes/microservices/zipkinserver/ZipkinServerApplication.java

package com.in28minutes.microservices.zipkinserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import zipkin.server.EnableZipkinServer;

@SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ZipkinServerApplication.class, args);
	}
}

/zipkin-server/src/main/resources/application.properties

server.port=9411
spring.application.name=zipkin-server

/zipkin-server/src/test/java/com/in28minutes/microservices/zipkinserver/ZipkinServerApplicationTests.java

package com.in28minutes.microservices.zipkinserver;

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 ZipkinServerApplicationTests {

	@Test
	public void contextLoads() {
	}

}

/zuul-api-gateway-server/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.in28minutes.microservices</groupId>
	<artifactId>zuul-api-gateway-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>zuul-api-gateway-server</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.M3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.M2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-sleuth</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-sleuth-zipkin</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>

/zuul-api-gateway-server/src/main/java/com/in28minutes/microservices/zuulapigatewayserver/SimpleLoggingFilter.java

package com.in28minutes.microservices.zuulapigatewayserver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

@Component
public class SimpleLoggingFilter extends ZuulFilter {

	Logger log = LoggerFactory.getLogger(this.getClass());

	@Override
	public Object run() {
		RequestContext context = RequestContext.getCurrentContext();

		log.info("{} {} {}", 
				context, 
				context.getRequest().getRequestURL(), 
				context.getZuulRequestHeaders());
		return null;
	}

	@Override
	public boolean shouldFilter() {
		return true;
	}

	@Override
	public int filterOrder() {
		return 1;
	}

	@Override
	public String filterType() {
		return "pre";
	}

}

/zuul-api-gateway-server/src/main/java/com/in28minutes/microservices/zuulapigatewayserver/ZuulApiGatewayServerApplication.java

package com.in28minutes.microservices.zuulapigatewayserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Bean;

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApiGatewayServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ZuulApiGatewayServerApplication.class, args);
	}
	
	@Bean
	public AlwaysSampler defaultSampler() {
		return new AlwaysSampler();
	}
}

/zuul-api-gateway-server/src/main/resources/application.properties

server.port=8765
spring.application.name=zuul-api-gateway-server

eureka.client.service-url.default-zone=http://localhost:8761/eureka

/zuul-api-gateway-server/src/test/java/com/in28minutes/microservices/zuulapigatewayserver/ZuulApiGatewayServerApplicationTests.java

package com.in28minutes.microservices.zuulapigatewayserver;

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 ZuulApiGatewayServerApplicationTests {

	@Test
	public void contextLoads() {
	}

}