├── .circleci └── config.yml ├── caller-service ├── pom.xml └── src │ ├── main │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── services │ │ │ └── caller │ │ │ ├── CallerApplication.java │ │ │ └── CallerController.java │ └── resources │ │ └── bootstrap.yml │ └── test │ └── java │ └── pl │ └── piomin │ └── services │ └── caller │ └── CallerCallmeTest.java ├── callme-service ├── pom.xml └── src │ ├── main │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── services │ │ │ └── callme │ │ │ ├── CallmeApplication.java │ │ │ └── CallmeController.java │ └── resources │ │ └── bootstrap.yml │ └── test │ ├── java │ └── pl │ │ └── piomin │ │ └── services │ │ └── callme │ │ └── CallmeControllerTests.java │ └── resources │ └── bootstrap-test.yml ├── config └── gateway-service.yml ├── gateway-service ├── pom.xml └── src │ └── main │ ├── java │ └── pl │ │ └── piomin │ │ └── services │ │ └── gateway │ │ └── GatewayApplication.java │ └── resources │ └── bootstrap.yml ├── pom.xml ├── readme.md └── renovate.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | build: 5 | docker: 6 | - image: 'cimg/openjdk:21.0.6' 7 | steps: 8 | - checkout 9 | - run: 10 | name: Analyze on SonarCloud 11 | command: mvn verify sonar:sonar 12 | 13 | executors: 14 | jdk: 15 | docker: 16 | - image: 'cimg/openjdk:21.0.6' 17 | 18 | orbs: 19 | maven: circleci/maven@2.0.0 20 | 21 | workflows: 22 | maven_test: 23 | jobs: 24 | - maven/test: 25 | executor: jdk 26 | - build: 27 | context: SonarCloud -------------------------------------------------------------------------------- /caller-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | pl.piomin.services 7 | sample-spring-cloud-microservices-future 8 | 1.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | caller-service 13 | 14 | 15 | ${project.artifactId} 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-actuator 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-consul-discovery 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-netflix-hystrix 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-starter-netflix-ribbon 38 | 39 | 40 | 41 | 42 | org.springframework.cloud 43 | spring-cloud-starter-consul-config 44 | 45 | 46 | org.springframework.cloud 47 | spring-cloud-loadbalancer 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-test 52 | test 53 | 54 | 55 | org.junit.vintage 56 | junit-vintage-engine 57 | 58 | 59 | 60 | 61 | io.specto 62 | hoverfly-java-junit5 63 | 0.20.2 64 | test 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 74 | 75 | org.jacoco 76 | jacoco-maven-plugin 77 | 0.8.13 78 | 79 | 80 | 81 | prepare-agent 82 | 83 | 84 | 85 | report 86 | test 87 | 88 | report 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /caller-service/src/main/java/pl/piomin/services/caller/CallerApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.caller; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.client.RestTemplate; 8 | 9 | @SpringBootApplication 10 | public class CallerApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(CallerApplication.class, args); 14 | } 15 | 16 | @LoadBalanced 17 | @Bean 18 | RestTemplate template() { 19 | return new RestTemplate(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /caller-service/src/main/java/pl/piomin/services/caller/CallerController.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.caller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.core.env.Environment; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | @RestController 14 | @RequestMapping("/caller") 15 | public class CallerController { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(CallerController.class); 18 | 19 | @Autowired 20 | Environment environment; 21 | @Autowired 22 | RestTemplate template; 23 | 24 | @GetMapping 25 | public String call() { 26 | String url = "http://callme-service/callme"; 27 | String callmeResponse = template.getForObject(url, String.class); 28 | LOGGER.info("Response: {}", callmeResponse); 29 | return "I'm Caller running on port " + environment.getProperty("local.server.port") 30 | + " calling-> " + callmeResponse; 31 | } 32 | 33 | @GetMapping("/slow") 34 | public String slow() { 35 | String url = "http://callme-service/callme/slow"; 36 | String callmeResponse = template.getForObject(url, String.class); 37 | LOGGER.info("Response: {}", callmeResponse); 38 | return "I'm Caller running on port " + environment.getProperty("local.server.port") 39 | + " calling-> " + callmeResponse; 40 | } 41 | } -------------------------------------------------------------------------------- /caller-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: caller-service 4 | cloud: 5 | consul: 6 | discovery: 7 | hostname: localhost 8 | register-health-check: false -------------------------------------------------------------------------------- /caller-service/src/test/java/pl/piomin/services/caller/CallerCallmeTest.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.caller; 2 | 3 | import io.specto.hoverfly.junit.core.Hoverfly; 4 | import io.specto.hoverfly.junit5.HoverflyExtension; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.ExtendWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.boot.test.web.client.TestRestTemplate; 10 | import org.springframework.boot.test.web.server.LocalServerPort; 11 | 12 | import static io.specto.hoverfly.junit.core.SimulationSource.dsl; 13 | import static io.specto.hoverfly.junit.dsl.HoverflyDsl.service; 14 | import static io.specto.hoverfly.junit.dsl.ResponseCreators.success; 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | 17 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, 18 | properties = { 19 | "spring.application.name=xxx", 20 | "spring.cloud.consul.discovery.enabled=false", 21 | "spring.cloud.consul.discovery.fail-fast=false", 22 | "spring.cloud.consul.config.enabled=false", 23 | "spring.cloud.consul.discovery.catalogServicesWatch.enabled=false", 24 | "VERSION = v2" 25 | } 26 | ) 27 | @ExtendWith(HoverflyExtension.class) 28 | public class CallerCallmeTest { 29 | 30 | @LocalServerPort 31 | int port; 32 | @Autowired 33 | TestRestTemplate restTemplate; 34 | 35 | @Test 36 | public void callmeIntegration(Hoverfly hoverfly) { 37 | hoverfly.simulate( 38 | dsl(service("http://callme-service") 39 | .get("/callme") 40 | .willReturn(success().body("I'm callme-service v1."))) 41 | ); 42 | String response = restTemplate.getForObject("/caller", String.class); 43 | // assertEquals("I'm Caller running on port " + port 44 | // + " calling-> I'm callme-service v1.", response); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /callme-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | pl.piomin.services 7 | sample-spring-cloud-microservices-future 8 | 1.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | callme-service 13 | 14 | 15 | ${project.artifactId} 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-actuator 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-consul-discovery 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-netflix-hystrix 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-starter-netflix-ribbon 38 | 39 | 40 | 41 | 42 | org.springframework.cloud 43 | spring-cloud-starter-consul-config 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | org.jacoco 60 | jacoco-maven-plugin 61 | 0.8.13 62 | 63 | 64 | 65 | prepare-agent 66 | 67 | 68 | 69 | report 70 | test 71 | 72 | report 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /callme-service/src/main/java/pl/piomin/services/callme/CallmeApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.callme; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CallmeApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CallmeApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /callme-service/src/main/java/pl/piomin/services/callme/CallmeController.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.callme; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.core.env.Environment; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/callme") 11 | public class CallmeController { 12 | 13 | @Autowired 14 | Environment environment; 15 | 16 | @GetMapping 17 | public String call() { 18 | return "I'm Callme running on port " + environment.getProperty("local.server.port"); 19 | } 20 | 21 | @GetMapping("/slow") 22 | public String slow() { 23 | try { 24 | Thread.sleep(5000); 25 | } catch (InterruptedException e) { 26 | 27 | } 28 | return "I'm Slow Callme running on port " + environment.getProperty("local.server.port"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /callme-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: callme-service 4 | cloud: 5 | consul: 6 | host: localhost 7 | discovery: 8 | hostname: localhost 9 | register-health-check: false 10 | config: 11 | import: optional:consul:localhost:8500 -------------------------------------------------------------------------------- /callme-service/src/test/java/pl/piomin/services/callme/CallmeControllerTests.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.callme; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.boot.test.web.client.TestRestTemplate; 7 | import org.springframework.boot.test.web.server.LocalServerPort; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | import static org.junit.jupiter.api.Assertions.assertNotNull; 11 | 12 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, 13 | properties = { 14 | "spring.application.name=xxx", 15 | "spring.cloud.consul.discovery.enabled=false", 16 | "spring.cloud.consul.discovery.fail-fast=false", 17 | "spring.cloud.consul.config.enabled=false", 18 | "spring.cloud.consul.discovery.catalogServicesWatch.enabled=false", 19 | "VERSION: v1" 20 | } 21 | ) 22 | public class CallmeControllerTests { 23 | 24 | @LocalServerPort 25 | int port; 26 | 27 | @Autowired 28 | TestRestTemplate restTemplate; 29 | 30 | @Test 31 | void call() { 32 | String res = restTemplate.getForObject("/callme", String.class); 33 | assertNotNull(res); 34 | assertEquals("I'm Callme running on port " + port, res); 35 | } 36 | 37 | @Test 38 | void slow() { 39 | String res = restTemplate.getForObject("/callme/slow", String.class); 40 | assertNotNull(res); 41 | assertEquals("I'm Slow Callme running on port " + port, res); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /callme-service/src/test/resources/bootstrap-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: callme-service 4 | cloud: 5 | consul: 6 | discovery: 7 | enabled: false 8 | config: 9 | import: optional:consul:localhost:8500 10 | 11 | #spring.cloud.consul.discovery.enabled: false 12 | #spring.cloud.consul.config.enabled: false 13 | #spring.cloud.consul.discovery.catalogServicesWatch.enabled: false -------------------------------------------------------------------------------- /config/gateway-service.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | gateway: 4 | discovery: 5 | locator: 6 | enabled: true 7 | routes: 8 | - id: caller-service 9 | uri: lb://caller-service 10 | predicates: 11 | - Path=/caller/** 12 | filters: 13 | - RewritePath=/caller/(?.*), /$\{path} 14 | - id: callme-service 15 | uri: lb://callme-service 16 | predicates: 17 | - Path=/callme/** 18 | filters: 19 | - RewritePath=/callme/(?.*), /$\{path} -------------------------------------------------------------------------------- /gateway-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | pl.piomin.services 7 | sample-spring-cloud-microservices-future 8 | 1.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | gateway-service 13 | 14 | 15 | ${project.artifactId} 16 | 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-consul-discovery 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-consul-config 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-starter-gateway 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | org.jacoco 60 | jacoco-maven-plugin 61 | 0.8.13 62 | 63 | 64 | 65 | prepare-agent 66 | 67 | 68 | 69 | report 70 | test 71 | 72 | report 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /gateway-service/src/main/java/pl/piomin/services/gateway/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient 9 | public class GatewayApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(GatewayApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /gateway-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: gateway-service 4 | cloud: 5 | consul: 6 | host: localhost 7 | config: 8 | format: YAML 9 | discovery: 10 | register-health-check: false 11 | 12 | loadbalancer: 13 | ribbon: 14 | enabled: false 15 | 16 | server.port: 8080 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 3.5.0 11 | 12 | 13 | 14 | pl.piomin.services 15 | sample-spring-cloud-microservices-future 16 | 1.1-SNAPSHOT 17 | pom 18 | 19 | 20 | piomin_spring-cloud-microservices-future 21 | piomin 22 | https://sonarcloud.io 23 | 21 24 | 2025.0.0 25 | 26 | 27 | 28 | gateway-service 29 | caller-service 30 | callme-service 31 | 32 | 33 | 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-dependencies 38 | ${spring-cloud.version} 39 | pom 40 | import 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## The Future of Spring Cloud Microservices After Netflix Era [![Twitter](https://img.shields.io/twitter/follow/piotr_minkowski.svg?style=social&logo=twitter&label=Follow%20Me)](https://twitter.com/piotr_minkowski) 2 | 3 | [![CircleCI](https://circleci.com/gh/piomin/sample-spring-cloud-microservices-future.svg?style=svg)](https://circleci.com/gh/piomin/sample-spring-cloud-microservices-future) 4 | 5 | [![SonarCloud](https://sonarcloud.io/images/project_badges/sonarcloud-black.svg)](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future) 6 | [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=piomin_sample-spring-cloud-microservices-future&metric=bugs)](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future) 7 | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=piomin_sample-spring-cloud-microservices-future&metric=coverage)](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future) 8 | [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=piomin_sample-spring-cloud-microservices-future&metric=ncloc)](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future) 9 | 10 | Detailed description can be found here: [The Future of Spring Cloud Microservices After Netflix Era](https://piotrminkowski.com/2019/04/05/the-future-of-spring-cloud-microservices-after-netflix-era/) 11 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base",":dependencyDashboard" 5 | ], 6 | "packageRules": [ 7 | { 8 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"], 9 | "automerge": true 10 | } 11 | ] 12 | } --------------------------------------------------------------------------------