├── .gitignore ├── zipkin-service ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── pl │ │ └── piomin │ │ └── microservices │ │ └── zipkin │ │ └── ZipkinServiceApplication.java ├── .gitignore ├── Dockerfile └── pom.xml ├── account-service ├── .gitignore ├── Dockerfile ├── src │ └── main │ │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── microservices │ │ │ └── account │ │ │ ├── model │ │ │ └── Account.java │ │ │ ├── exceptions │ │ │ └── AccountNotFoundException.java │ │ │ ├── AccountServiceApplication.java │ │ │ ├── config │ │ │ └── AccountConfiguration.java │ │ │ └── api │ │ │ └── Api.java │ │ └── resources │ │ └── application.yml ├── Jenkinsfile └── pom.xml ├── customer-service ├── .gitignore ├── src │ └── main │ │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── microservices │ │ │ └── customer │ │ │ ├── model │ │ │ ├── CustomerType.java │ │ │ ├── Account.java │ │ │ └── Customer.java │ │ │ ├── exceptions │ │ │ └── CustomerNotFoundException.java │ │ │ ├── config │ │ │ └── CustomerConfiguration.java │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── intercomm │ │ │ └── AccountClient.java │ │ │ └── api │ │ │ └── Api.java │ │ └── resources │ │ ├── application.yml │ │ └── bootstrap.yml ├── Dockerfile ├── Jenkinsfile └── pom.xml ├── discovery-service ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── pl │ │ └── piomin │ │ └── microservices │ │ └── eureka │ │ └── DiscoveryServiceApplication.java ├── Dockerfile ├── Jenkinsfile └── pom.xml ├── gateway-service ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ └── application.yml │ │ └── java │ │ └── pl │ │ └── piomin │ │ └── microservices │ │ └── edge │ │ ├── GatewayServiceApplication.java │ │ └── config │ │ └── CustomerConfiguration.java ├── Dockerfile ├── Jenkinsfile └── pom.xml ├── JenkinsFile ├── docker-compose.yml ├── pom.xml ├── .github └── workflows │ └── codeql.yml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | *.idea 3 | *.iml -------------------------------------------------------------------------------- /zipkin-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:9411} -------------------------------------------------------------------------------- /account-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /discovery-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /gateway-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /zipkin-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /gateway-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: gateway-server -------------------------------------------------------------------------------- /JenkinsFile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | stages { 4 | stage('build') { 5 | steps { 6 | sh 'mvn --version' 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/model/CustomerType.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.model; 2 | 3 | public enum CustomerType { 4 | INDIVIDUAL, COMPANY; 5 | } 6 | -------------------------------------------------------------------------------- /zipkin-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:11 2 | MAINTAINER Ramazan Sakin 3 | ADD target/*.jar zipkin-service.jar 4 | EXPOSE 9411 5 | ENTRYPOINT ["java", "-jar", "/zipkin-service.jar"] 6 | -------------------------------------------------------------------------------- /discovery-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:8761} 3 | 4 | eureka: 5 | instance: 6 | hostname: localhost 7 | client: 8 | registerWithEureka: false 9 | fetchRegistry: false 10 | server: 11 | enableSelfPreservation: false -------------------------------------------------------------------------------- /account-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:11 2 | MAINTAINER Piotr Minkowski 3 | MAINTAINER Ramazan Sakin 4 | ADD target/account-service.jar account-service.jar 5 | EXPOSE 2222 6 | ENTRYPOINT ["java", "-jar", "/account-service.jar"] -------------------------------------------------------------------------------- /gateway-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:11 2 | MAINTAINER Piotr Minkowski 3 | MAINTAINER Ramazan Sakin 4 | ADD target/gateway-service.jar gateway-service.jar 5 | EXPOSE 8765 6 | ENTRYPOINT ["java", "-jar", "/gateway-service.jar"] 7 | -------------------------------------------------------------------------------- /customer-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:11 2 | MAINTAINER Piotr Minkowski 3 | MAINTAINER Ramazan Sakin 4 | ADD target/customer-service.jar customer-service.jar 5 | EXPOSE 3333 6 | ENTRYPOINT ["java", "-jar", "/customer-service.jar"] 7 | -------------------------------------------------------------------------------- /discovery-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:11 2 | MAINTAINER Piotr Minkowski 3 | MAINTAINER Ramazan Sakin 4 | ADD target/discovery-service.jar discovery-service.jar 5 | EXPOSE 8761 6 | ENTRYPOINT ["java", "-jar", "/discovery-service.jar"] 7 | -------------------------------------------------------------------------------- /customer-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:3333} 3 | 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:8761/eureka/ 8 | instance: 9 | leaseRenewalIntervalInSeconds: 1 10 | leaseExpirationDurationInSeconds: 2 11 | 12 | ribbon: 13 | eureka: 14 | enabled: true -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/model/Account.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class Account { 11 | 12 | private Integer id; 13 | private String number; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /account-service/src/main/java/pl/piomin/microservices/account/model/Account.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.account.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class Account { 11 | 12 | private Integer id; 13 | private Integer customerId; 14 | private String number; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /customer-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: customer-service 4 | logging: 5 | pattern: 6 | console: "%clr(%d{yyyy-MM-dd HH:mm:ss}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" 7 | level: 8 | org.springframework: WARN 9 | org.hibernate: WARN -------------------------------------------------------------------------------- /zipkin-service/src/main/java/pl/piomin/microservices/zipkin/ZipkinServiceApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.zipkin; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import zipkin.server.EnableZipkinServer; 6 | 7 | @SpringBootApplication 8 | @EnableZipkinServer 9 | public class ZipkinServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ZipkinServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /account-service/src/main/java/pl/piomin/microservices/account/exceptions/AccountNotFoundException.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.account.exceptions; 2 | 3 | import org.springframework.web.bind.annotation.ResponseStatus; 4 | 5 | @ResponseStatus(org.springframework.http.HttpStatus.NOT_FOUND) 6 | public class AccountNotFoundException extends Exception { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public AccountNotFoundException(String cause) { 11 | super("No such account with " + cause); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/exceptions/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.exceptions; 2 | 3 | import org.springframework.web.bind.annotation.ResponseStatus; 4 | 5 | @ResponseStatus(org.springframework.http.HttpStatus.NOT_FOUND) 6 | public class CustomerNotFoundException extends Exception { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public CustomerNotFoundException(String cause) { 11 | super("No such customer with " + cause); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /account-service/src/main/java/pl/piomin/microservices/account/AccountServiceApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.account; 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 AccountServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(AccountServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /discovery-service/src/main/java/pl/piomin/microservices/eureka/DiscoveryServiceApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.eureka; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class DiscoveryServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DiscoveryServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /gateway-service/src/main/java/pl/piomin/microservices/edge/GatewayServiceApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.edge; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 6 | 7 | @SpringBootApplication 8 | @EnableZuulProxy 9 | public class GatewayServiceApplication { 10 | public static void main(String[] args) { 11 | new SpringApplicationBuilder(GatewayServiceApplication.class).web(true).run(args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /account-service/src/main/java/pl/piomin/microservices/account/config/AccountConfiguration.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.account.config; 2 | 3 | import org.springframework.cloud.sleuth.sampler.AlwaysSampler; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | @ComponentScan("pl.piomin.microservices.account") 10 | public class AccountConfiguration { 11 | 12 | @Bean 13 | public AlwaysSampler defaultSampler() { 14 | return new AlwaysSampler(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/config/CustomerConfiguration.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.config; 2 | 3 | import org.springframework.cloud.sleuth.sampler.AlwaysSampler; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | @ComponentScan("pl.piomin.microservices.customer") 10 | public class CustomerConfiguration { 11 | 12 | @Bean 13 | public AlwaysSampler defaultSampler() { 14 | return new AlwaysSampler(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /gateway-service/src/main/java/pl/piomin/microservices/edge/config/CustomerConfiguration.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.edge.config; 2 | 3 | import org.springframework.cloud.sleuth.sampler.AlwaysSampler; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | @ComponentScan("pl.piomin.microservices.edge") 10 | public class CustomerConfiguration { 11 | 12 | @Bean 13 | public AlwaysSampler defaultSampler() { 14 | return new AlwaysSampler(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableFeignClients 11 | public class CustomerServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(CustomerServiceApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/model/Customer.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class Customer { 13 | 14 | private Integer id; 15 | private String pesel; 16 | private String name; 17 | private CustomerType type; 18 | private List accounts; 19 | 20 | public Customer(int id, String pesel, String name, CustomerType type) { 21 | this.id = id; 22 | this.pesel = pesel; 23 | this.name = name; 24 | this.type = type; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/intercomm/AccountClient.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.intercomm; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | 10 | import pl.piomin.microservices.customer.model.Account; 11 | 12 | @FeignClient("account-service") 13 | public interface AccountClient { 14 | 15 | @RequestMapping(method = RequestMethod.GET, value = "/customer/{customerId}") 16 | List getAccounts(@PathVariable("customerId") Integer customerId); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /gateway-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | info: 2 | component: Edge Server 3 | 4 | endpoints: 5 | restart: 6 | enabled: true 7 | shutdown: 8 | enabled: true 9 | health: 10 | sensitive: false 11 | 12 | zuul: 13 | prefix: /api 14 | routes: 15 | account: 16 | path: /accounts/** 17 | serviceId: account-service 18 | customer: 19 | path: /customers/** 20 | serviceId: customer-service 21 | 22 | ribbon: 23 | eureka: 24 | enabled: true 25 | 26 | eureka: 27 | client: 28 | serviceUrl: 29 | defaultZone: http://localhost:8761/eureka/ 30 | registerWithEureka: false 31 | 32 | server: 33 | port: 8765 34 | 35 | logging: 36 | level: 37 | ROOT: INFO 38 | org.springframework.web: DEBUG -------------------------------------------------------------------------------- /account-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:2222} 3 | 4 | spring: 5 | application: 6 | name: account-service 7 | logging: 8 | pattern: 9 | console: "%clr(%d{yyyy-MM-dd HH:mm:ss}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" 10 | level: 11 | org.springframework: WARN 12 | org.hibernate: WARN 13 | 14 | eureka: 15 | client: 16 | serviceUrl: 17 | defaultZone: http://localhost:8761/eureka/ 18 | instance: 19 | leaseRenewalIntervalInSeconds: 1 20 | leaseExpirationDurationInSeconds: 2 21 | 22 | ribbon: 23 | eureka: 24 | enabled: true -------------------------------------------------------------------------------- /gateway-service/Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | 3 | withMaven(maven:'maven') { 4 | 5 | stage('Checkout') { 6 | git url: 'https://github.com/piomin/sample-spring-microservices.git', credentialsId: 'github-piomin', branch: 'master' 7 | } 8 | 9 | stage('Build') { 10 | sh 'mvn clean install' 11 | 12 | def pom = readMavenPom file:'pom.xml' 13 | print pom.version 14 | env.version = pom.version 15 | } 16 | 17 | stage('Image') { 18 | dir ('gateway-service') { 19 | def app = docker.build "localhost:5000/gateway-service:${env.version}" 20 | app.push() 21 | } 22 | } 23 | 24 | stage ('Run') { 25 | docker.image("localhost:5000/gateway-service:${env.version}").run('-p 3333:3333 -h gateway --name gateway --link discovery --link account --link customer') 26 | } 27 | 28 | 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /discovery-service/Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | 3 | withMaven(maven:'maven') { 4 | 5 | stage('Checkout') { 6 | git url: 'https://github.com/piomin/sample-spring-microservices.git', credentialsId: 'github-piomin', branch: 'master' 7 | } 8 | 9 | stage('Build') { 10 | sh 'mvn clean install' 11 | 12 | def pom = readMavenPom file:'pom.xml' 13 | print pom.version 14 | env.version = pom.version 15 | } 16 | 17 | stage('Image') { 18 | dir ('discovery-service') { 19 | def app = docker.build "localhost:5000/discovery-service:${env.version}" 20 | app.push() 21 | } 22 | } 23 | 24 | stage ('Run') { 25 | docker.image("localhost:5000/discovery-service:${env.version}").run('-p 8761:8761 -h discovery --name discovery') 26 | } 27 | 28 | stage ('Final') { 29 | build job: 'account-service-pipeline', wait: false 30 | } 31 | 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /customer-service/Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | 3 | withMaven(maven:'maven') { 4 | 5 | stage('Checkout') { 6 | git url: 'https://github.com/piomin/sample-spring-microservices.git', credentialsId: 'github-piomin', branch: 'master' 7 | } 8 | 9 | stage('Build') { 10 | sh 'mvn clean install' 11 | 12 | def pom = readMavenPom file:'pom.xml' 13 | print pom.version 14 | env.version = pom.version 15 | } 16 | 17 | stage('Image') { 18 | dir ('customer-service') { 19 | def app = docker.build "localhost:5000/customer-service:${env.version}" 20 | app.push() 21 | } 22 | } 23 | 24 | stage ('Run') { 25 | docker.image("localhost:5000/customer-service:${env.version}").run('-p 3333:3333 -h customer --name customer --link discovery --link account') 26 | } 27 | 28 | stage ('Final') { 29 | build job: 'gateway-service-pipeline', wait: false 30 | } 31 | 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /account-service/Jenkinsfile: -------------------------------------------------------------------------------- 1 | using hostname. 2 | 3 | [code language="java"] 4 | node { 5 | 6 | withMaven(maven:'maven') { 7 | 8 | stage('Checkout') { 9 | git url: 'https://github.com/piomin/sample-spring-microservices.git', credentialsId: 'github-piomin', branch: 'master' 10 | } 11 | 12 | stage('Build') { 13 | sh 'mvn clean install' 14 | 15 | def pom = readMavenPom file:'pom.xml' 16 | print pom.version 17 | env.version = pom.version 18 | } 19 | 20 | stage('Image') { 21 | dir ('account-service') { 22 | def app = docker.build "localhost:5000/account-service:${env.version}" 23 | app.push() 24 | } 25 | } 26 | 27 | stage ('Run') { 28 | docker.image("localhost:5000/account-service:${env.version}").run('-p 2222:2222 -h account --name account --link discovery') 29 | } 30 | 31 | stage ('Final') { 32 | build job: 'customer-service-pipeline', wait: false 33 | } 34 | 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | discovery: 4 | image: piomin/discovery-service 5 | container_name: discovery-service 6 | build: 7 | context: ./discovery-service 8 | dockerfile: Dockerfile 9 | ports: 10 | - "8761:8761" 11 | 12 | gateway: 13 | image: piomin/gateway-service 14 | container_name: service-gateway 15 | build: 16 | context: ./gateway-service 17 | dockerfile: Dockerfile 18 | ports: 19 | - "8765:8765" 20 | environment: 21 | EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka 22 | links: 23 | - discovery 24 | 25 | zipkin-service: 26 | image: piomin/zipkin-service 27 | container_name: zipkin-service 28 | build: 29 | context: ./zipkin-service 30 | dockerfile: Dockerfile 31 | ports: 32 | - "9411:9411" 33 | 34 | account-service: 35 | image: piomin/account-service 36 | container_name: account-service 37 | build: 38 | context: ./account-service 39 | dockerfile: Dockerfile 40 | ports: 41 | - "2222:2222" 42 | environment: 43 | EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka 44 | links: 45 | - discovery 46 | 47 | customer-service: 48 | image: piomin/customer-service 49 | container_name: customer-service 50 | build: 51 | context: ./customer-service 52 | dockerfile: Dockerfile 53 | ports: 54 | - "3333:3333" 55 | environment: 56 | EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka 57 | links: 58 | - discovery -------------------------------------------------------------------------------- /discovery-service/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | pl.piomin 7 | sample-spring-microservices 8 | 2.0 9 | 10 | discovery-service 11 | 12 | 13 | 14 | org.springframework.cloud 15 | spring-cloud-starter-eureka-server 16 | 17 | 18 | 19 | 20 | discovery-service 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-maven-plugin 25 | 26 | pl.piomin.microservices.eureka.DiscoveryServiceApplication 27 | true 28 | 29 | 30 | 31 | 32 | repackage 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /zipkin-service/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | zipkin-service 6 | 7 | pl.piomin 8 | sample-spring-microservices 9 | 2.0 10 | 11 | 12 | 13 | 14 | io.zipkin.java 15 | zipkin-server 16 | 17 | 18 | io.zipkin.java 19 | zipkin 20 | 21 | 22 | io.zipkin.java 23 | zipkin-autoconfigure-ui 24 | 25 | 26 | 27 | 28 | zipkin-service 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-maven-plugin 33 | 34 | pl.piomin.microservices.zipkin.ZipkinServiceApplication 35 | true 36 | 37 | 38 | 39 | 40 | repackage 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | pl.piomin 5 | sample-spring-microservices 6 | 2.0 7 | pom 8 | 9 | 10 | org.springframework.cloud 11 | spring-cloud-starter-parent 12 | Brixton.RELEASE 13 | 14 | 15 | 16 | 11 17 | 2.1.5.RELEASE 18 | 1.2.2.RELEASE 19 | 20 | 21 | 22 | discovery-service 23 | account-service 24 | gateway-service 25 | customer-service 26 | zipkin-service 27 | 28 | 29 | 30 | 31 | org.projectlombok 32 | lombok 33 | 1.18.20 34 | 35 | 36 | 37 | jakarta.xml.bind 38 | jakarta.xml.bind-api 39 | 2.3.2 40 | 41 | 42 | 43 | 44 | org.glassfish.jaxb 45 | jaxb-runtime 46 | 2.3.2 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /account-service/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | account-service 6 | 7 | pl.piomin 8 | sample-spring-microservices 9 | 2.0 10 | 11 | 12 | 13 | 14 | org.springframework.cloud 15 | spring-cloud-starter-eureka 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-actuator 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-sleuth 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-sleuth-zipkin 28 | 29 | 30 | 31 | 32 | account-service 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-maven-plugin 37 | 38 | pl.piomin.microservices.account.AccountServiceApplication 39 | true 40 | 41 | 42 | 43 | 44 | repackage 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /customer-service/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | pl.piomin 7 | sample-spring-microservices 8 | 2.0 9 | 10 | customer-service 11 | 12 | 13 | 14 | org.springframework.cloud 15 | spring-cloud-starter-eureka 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-actuator 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-feign 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-sleuth 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-sleuth-zipkin 32 | 33 | 34 | 35 | 36 | customer-service 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-maven-plugin 41 | 42 | pl.piomin.microservices.customer.CustomerServiceApplication 43 | true 44 | 45 | 46 | 47 | 48 | repackage 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /gateway-service/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | gateway-service 6 | 7 | pl.piomin 8 | sample-spring-microservices 9 | 2.0 10 | 11 | 12 | 13 | 14 | org.springframework.cloud 15 | spring-cloud-starter-eureka 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter 20 | 21 | 22 | org.springframework 23 | spring-web 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-zuul 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-sleuth 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-sleuth-zipkin 40 | 41 | 42 | 43 | 44 | gateway-service 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | pl.piomin.microservices.edge.GatewayServiceApplication 51 | true 52 | 53 | 54 | 55 | 56 | repackage 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '38 3 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 27 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 28 | permissions: 29 | actions: read 30 | contents: read 31 | security-events: write 32 | 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | language: [ 'java' ] 37 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] 38 | # Use only 'java' to analyze code written in Java, Kotlin or both 39 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 40 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 41 | 42 | steps: 43 | - name: Checkout repository 44 | uses: actions/checkout@v3 45 | 46 | # Initializes the CodeQL tools for scanning. 47 | - name: Initialize CodeQL 48 | uses: github/codeql-action/init@v2 49 | with: 50 | languages: ${{ matrix.language }} 51 | # If you wish to specify custom queries, you can do so here or in a config file. 52 | # By default, queries listed here will override any specified in a config file. 53 | # Prefix the list here with "+" to use these queries and those in the config file. 54 | 55 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 56 | # queries: security-extended,security-and-quality 57 | 58 | 59 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 60 | # If this step fails, then you should remove it and run the build manually (see below) 61 | - name: Autobuild 62 | uses: github/codeql-action/autobuild@v2 63 | 64 | # ℹ️ Command-line programs to run using the OS shell. 65 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 66 | 67 | # If the Autobuild fails above, remove it and uncomment the following three lines. 68 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 69 | 70 | # - run: | 71 | # echo "Run, Build Application using script" 72 | # ./location_of_script_within_repo/buildscript.sh 73 | 74 | - name: Perform CodeQL Analysis 75 | uses: github/codeql-action/analyze@v2 76 | with: 77 | category: "/language:${{matrix.language}}" 78 | -------------------------------------------------------------------------------- /account-service/src/main/java/pl/piomin/microservices/account/api/Api.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.account.api; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.web.bind.annotation.*; 5 | import pl.piomin.microservices.account.exceptions.AccountNotFoundException; 6 | import pl.piomin.microservices.account.model.Account; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | @RestController 13 | @Slf4j 14 | public class Api { 15 | 16 | private List accounts; 17 | 18 | public Api() { 19 | accounts = new ArrayList<>(); 20 | accounts.add(new Account(1, 1, "111111")); 21 | accounts.add(new Account(2, 2, "222222")); 22 | accounts.add(new Account(3, 3, "333333")); 23 | accounts.add(new Account(4, 4, "444444")); 24 | accounts.add(new Account(5, 1, "555555")); 25 | accounts.add(new Account(6, 2, "666666")); 26 | accounts.add(new Account(7, 2, "777777")); 27 | } 28 | 29 | @RequestMapping(method = RequestMethod.GET, value = "/number/{number}") 30 | public Account findByNumber(@PathVariable("number") String number) throws AccountNotFoundException { 31 | log.info(String.format("Account.findByNumber(%s)", number)); 32 | return accounts.stream() 33 | .filter(it -> it.getNumber().equals(number)) 34 | .findFirst() 35 | .orElseThrow(() -> new AccountNotFoundException("number : " + number)); 36 | } 37 | 38 | @RequestMapping(method = RequestMethod.GET, value = "/customer/{customer}") 39 | public List findByCustomer(@PathVariable("customer") Integer customerId) { 40 | log.info(String.format("Account.findByCustomer(%s)", customerId)); 41 | return accounts.stream() 42 | .filter(it -> it.getCustomerId().intValue() == customerId.intValue()) 43 | .collect(Collectors.toList()); 44 | } 45 | 46 | @RequestMapping(method = RequestMethod.GET, value = "") 47 | public List findAll() { 48 | log.info("Account.findAll()"); 49 | return accounts; 50 | } 51 | 52 | @RequestMapping(method = RequestMethod.GET, value = "/{id}") 53 | public Account findById(@PathVariable Integer id) throws AccountNotFoundException { 54 | log.info("Account.findAll()"); 55 | return accounts.stream() 56 | .filter(it -> it.getId().equals(id)) 57 | .findFirst() 58 | .orElseThrow(() -> new AccountNotFoundException("id : " + id)); 59 | } 60 | 61 | @RequestMapping(method = RequestMethod.POST, value = "") 62 | public Account createNewAccount(@RequestBody Account account) { 63 | log.info("Account.createNewAccount()"); 64 | if (account.getId() != null) { 65 | return null; 66 | } 67 | int size = accounts.size(); 68 | account.setId(size + 1); 69 | accounts.add(account); 70 | return account; 71 | } 72 | 73 | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}") 74 | public boolean deleteAccount(@PathVariable Integer id) { 75 | log.info("Account.deleteAccount()"); 76 | try { 77 | Account byId = findById(id); 78 | accounts.remove(byId); 79 | } catch (AccountNotFoundException e) { 80 | return false; 81 | } 82 | return true; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /customer-service/src/main/java/pl/piomin/microservices/customer/api/Api.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.microservices.customer.api; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.*; 6 | import pl.piomin.microservices.customer.exceptions.CustomerNotFoundException; 7 | import pl.piomin.microservices.customer.intercomm.AccountClient; 8 | import pl.piomin.microservices.customer.model.Account; 9 | import pl.piomin.microservices.customer.model.Customer; 10 | import pl.piomin.microservices.customer.model.CustomerType; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | @RestController 16 | @Slf4j 17 | public class Api { 18 | 19 | @Autowired 20 | private AccountClient accountClient; 21 | 22 | private List customers; 23 | 24 | public Api() { 25 | customers = new ArrayList<>(); 26 | customers.add(new Customer(1, "12345", "Adam Kowalski", CustomerType.INDIVIDUAL)); 27 | customers.add(new Customer(2, "12346", "Anna Malinowska", CustomerType.INDIVIDUAL)); 28 | customers.add(new Customer(3, "12347", "Paweł Michalski", CustomerType.INDIVIDUAL)); 29 | customers.add(new Customer(4, "12348", "Karolina Lewandowska", CustomerType.INDIVIDUAL)); 30 | } 31 | 32 | @RequestMapping(method = RequestMethod.GET, value = "/pesel/{pesel}") 33 | public Customer findByPesel(@PathVariable("pesel") String pesel) throws CustomerNotFoundException { 34 | log.info(String.format("Customer.findByPesel(%s)", pesel)); 35 | return customers.stream() 36 | .filter(it -> it.getPesel().equals(pesel)) 37 | .findFirst() 38 | .orElseThrow(() -> new CustomerNotFoundException("pesel : " + pesel)); 39 | } 40 | 41 | @RequestMapping(method = RequestMethod.GET, value = "") 42 | public List findAll() { 43 | log.info("Customer.findAll()"); 44 | return customers; 45 | } 46 | 47 | @RequestMapping(method = RequestMethod.GET, value = "/{id}") 48 | public Customer findById(@PathVariable("id") Integer id) throws CustomerNotFoundException { 49 | log.info(String.format("Customer.findById(%s)", id)); 50 | Customer customer = customers.stream() 51 | .filter(it -> it.getId().intValue() == id.intValue()) 52 | .findFirst().orElseThrow(() -> new CustomerNotFoundException("id : " + id)); 53 | 54 | List accounts = accountClient.getAccounts(id); 55 | customer.setAccounts(accounts); 56 | return customer; 57 | } 58 | 59 | @RequestMapping(method = RequestMethod.POST, value = "") 60 | public Customer createNewCustomer(@RequestBody Customer customer) { 61 | log.info("Customer.createNewCustomer()"); 62 | if (customer.getId() != null) { 63 | return null; 64 | } 65 | int size = customers.size(); 66 | customer.setId(size + 1); 67 | customers.add(customer); 68 | return customer; 69 | } 70 | 71 | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}") 72 | public boolean deleteCustomer(@PathVariable Integer id) { 73 | log.info("Customer.deleteCustomer()"); 74 | try { 75 | Customer byId = findById(id); 76 | customers.remove(byId); 77 | } catch (CustomerNotFoundException e) { 78 | return false; 79 | } 80 | return true; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Microservices with Spring Cloud Demo Project [![Twitter](https://img.shields.io/twitter/follow/piotr_minkowski.svg?style=social&logo=twitter&label=Follow%20Me)](https://twitter.com/piotr_minkowski) 2 | 3 | In this project I'm demonstrating you the most interesting features of [Spring Cloud Project](https://spring.io/projects/spring-cloud) for building microservice-based architecture. Most of examples are based on **Spring Boot 1.5**. 4 | 5 | > :warning: This repository contains examples of Spring Boot 1.5 and won't be updated. **If you are looking for the repository with the latest versions of Spring Boot/Spring Cloud please refer to that: https://github.com/piomin/sample-spring-microservices-new**. It is automatically updated to the latest versions of all frameworks and libraries. 6 | 7 | ## Getting Started 8 | Currently you may find here some examples of microservices implementation using different projects from Spring Cloud. All the examples are divided into the branches and described in a separated articles on my blog. Here's a full list of available examples: 9 | 1. Introduction to Spring Cloud components like discovery with **Eureka**, load balancing with **Ribbon**, REST client **Feign**, API gataway with **Zuul**. The example is available in the branch [master](https://github.com/piomin/sample-spring-microservices/tree/master). A detailed description can be found here: [Part 1: Creating microservice using Spring Cloud, Eureka and Zuul](https://piotrminkowski.com/2017/02/05/part-1-creating-microservice-using-spring-cloud-eureka-and-zuul/) 10 | 2. Introduction to Spring Cloud components used for microservices monitoring like **Spring Cloud Sleuth** and **Zipkin**. Integration with **Logstash** for sending logs to ELK. The example is available in the branch [logstash](https://github.com/piomin/sample-spring-microservices/tree/logstash). A detailed description can be found here: [Part 2: Creating microservices – monitoring with Spring Cloud Sleuth, ELK and Zipkin](https://piotrminkowski.com/2017/04/05/part-2-creating-microservices-monitoring-with-spring-cloud-sleuth-elk-and-zipkin/) 11 | 3. Introduction to load balancing with **Ribbon** and **Feign** declarative HTTP client, circuit braker and fallback with **Hystrix**. The example is available in the branch [hystrix](https://github.com/piomin/sample-spring-microservices/tree/hystrix). A detailed description can be found here: [Part 3: Creating Microservices: Circuit Breaker, Fallback and Load Balancing with Spring Cloud](https://piotrminkowski.com/2017/05/15/part-3-creating-microservices-circuit-breaker-fallback-and-load-balancing-with-spring-cloud/) 12 | 4. Using tool **Spring Boot Admin** for managing and monitoring microservices-based system. The example is available in the branch [admin](https://github.com/piomin/sample-spring-microservices/tree/admin). A detailed description can be found here: [Monitoring Microservices With Spring Boot Admin](https://piotrminkowski.com/2017/06/26/monitoring-microservices-with-spring-boot-admin/) 13 | 5. Deploying and running Spring Boot microservices on **Kubernetes** including inter-service communication using **Feign** client and integration with database **Mongo**. The example is available in the branch [kubernetes](https://github.com/piomin/sample-spring-microservices/tree/kubernetes). A detailed description can be found here: [Microservices with Kubernetes and Docker](https://piotrminkowski.com/2017/03/31/microservices-with-kubernetes-and-docker) 14 | 15 | 16 | ### Usage 17 | 18 | In the most cases you need to have Maven, JDK8+ and Docker for running third-party software like Zipkin or Logstash. In the fifth example with Kubernetes you will have to run **Minikube** on your local machine. The best way to run the sample applications is with IDEs like IntelliJ IDEA or Eclipse. 19 | 20 | ### How to Run 21 | 22 | docker-compose up 23 | 24 | If you want to change anything on any service(s), you need to build the service(s) you changed and then : 25 | 26 | docker-compose build 27 | docker-compose up 28 | 29 | ### How to Run 30 | 31 | docker-compose down 32 | 33 | ## Architecture 34 | 35 | Our sample microservices-based system consists of the following modules: 36 | - **gateway-service** - a module that Spring Cloud Netflix Zuul for running Spring Boot application that acts as a proxy/gateway in our architecture. 37 | - **config-service** - a module that uses Spring Cloud Config Server for running configuration server in the `native` mode. The configuration files are placed on the classpath. 38 | - **discovery-service** - a module that depending on the example it uses Spring Cloud Netflix Eureka as an embedded discovery server. 39 | - **account-service** - a module containing the first of our sample microservices that allows to perform CRUD operation on in-memory repository of accounts 40 | - **customer-service** - a module containing the second of our sample microservices that allows to perform CRUD operation on in-memory repository of customers. It communicates with account-service. 41 | - **zipkin-service** - a module that runs embedded Zipkin instance. 42 | 43 | The following picture illustrates the architecture described above. 44 | 45 |
46 | 47 | In case of Kubernetes deployment we use only some of Spring Cloud components like Spring Cloud **Feign** or **Sleuth** without discovery or config server. 48 | 49 | 50 | 51 | For similar examples of microservice applications with Spring Boot 2 you may refer to the repository https://github.com/piomin/sample-spring-microservices-new 52 | --------------------------------------------------------------------------------