├── .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 [](https://twitter.com/piotr_minkowski)
2 |
3 | [](https://circleci.com/gh/piomin/sample-spring-cloud-microservices-future)
4 |
5 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future)
6 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future)
7 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-cloud-microservices-future)
8 | [](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 | }
--------------------------------------------------------------------------------