├── .gitignore
├── department-service
├── .gitignore
├── nbactions.xml
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── py
│ │ │ └── department
│ │ │ ├── DepartmentApplication.java
│ │ │ ├── client
│ │ │ └── EmployeeClient.java
│ │ │ ├── controller
│ │ │ └── DepartmentController.java
│ │ │ ├── model
│ │ │ ├── Department.java
│ │ │ └── Employee.java
│ │ │ └── repository
│ │ │ └── DepartmentRepository.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── DepartmentRepositoryTest.java
├── discovery-service
├── .gitignore
├── nb-configuration.xml
├── nbactions.xml
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── py
│ │ └── discovery
│ │ └── DiscoveryApplication.java
│ └── resources
│ └── application.yml
├── employee-service
├── .gitignore
├── nbactions.xml
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── py
│ │ │ └── employee
│ │ │ ├── EmployeeApplication.java
│ │ │ ├── controller
│ │ │ └── EmployeeController.java
│ │ │ ├── model
│ │ │ └── Employee.java
│ │ │ └── repository
│ │ │ └── EmployeeRepository.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── pl
│ └── piomin
│ └── services
│ └── employee
│ └── EmployeeRepositoryTest.java
├── gateway-service
├── .gitignore
├── nbactions.xml
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── py
│ │ └── gateway
│ │ └── GatewayApplication.java
│ └── resources
│ └── application.yml
├── organization-service
├── .gitignore
├── nbactions.xml
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── py
│ │ │ └── organization
│ │ │ ├── OrganizationApplication.java
│ │ │ ├── client
│ │ │ ├── DepartmentClient.java
│ │ │ └── EmployeeClient.java
│ │ │ ├── controller
│ │ │ └── OrganizationController.java
│ │ │ ├── model
│ │ │ ├── Department.java
│ │ │ ├── Employee.java
│ │ │ └── Organization.java
│ │ │ └── repository
│ │ │ └── OrganizationRepository.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── OrganizationRepositoryTest.java
├── pom.xml
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.project
2 | /.settings/
3 |
--------------------------------------------------------------------------------
/department-service/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.classpath
3 | /.project
4 | /.settings/
5 |
--------------------------------------------------------------------------------
/department-service/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | process-classes
10 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
11 |
12 |
13 |
14 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
15 |
16 | com.py.department.DepartmentApplication
17 | java
18 |
19 |
20 |
21 | debug
22 |
23 | jar
24 |
25 |
26 | process-classes
27 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
28 |
29 |
30 | -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}
31 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
32 |
33 | com.py.department.DepartmentApplication
34 | java
35 | true
36 |
37 |
38 |
39 | profile
40 |
41 | jar
42 |
43 |
44 | process-classes
45 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
46 |
47 |
48 |
49 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
50 | com.py.department.DepartmentApplication
51 | java
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/department-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | org.springframework.boot
5 | spring-boot-starter-parent
6 | 2.6.1
7 |
8 |
9 | department-service
10 | com.py
11 | 1.2-SNAPSHOT
12 |
13 |
14 | 17
15 | 2021.0.0
16 |
17 |
18 |
19 |
20 |
21 | org.springframework.cloud
22 | spring-cloud-dependencies
23 | ${spring-cloud.version}
24 | pom
25 | import
26 |
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.cloud
33 | spring-cloud-starter-netflix-eureka-client
34 |
35 |
36 | org.springframework.cloud
37 | spring-cloud-starter-openfeign
38 |
39 |
40 | org.springframework.cloud
41 | spring-cloud-openfeign-core
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-web
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-starter-actuator
50 |
51 |
52 | org.springframework.cloud
53 | spring-cloud-starter-sleuth
54 |
55 |
56 | org.springdoc
57 | springdoc-openapi-webmvc-core
58 | 1.5.13
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-test
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-maven-plugin
72 |
73 |
74 | org.jacoco
75 | jacoco-maven-plugin
76 | 0.8.7
77 |
78 |
79 |
80 | prepare-agent
81 |
82 |
83 |
84 | report
85 | test
86 |
87 | report
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/DepartmentApplication.java:
--------------------------------------------------------------------------------
1 | package com.py.department;
2 |
3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4 | import io.swagger.v3.oas.annotations.info.Info;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 | import org.springframework.context.annotation.Bean;
9 | import com.py.department.model.Department;
10 | import com.py.department.repository.DepartmentRepository;
11 |
12 | @SpringBootApplication
13 | @EnableFeignClients
14 | @OpenAPIDefinition(info =
15 | @Info(title = "Department API", version = "1.0", description = "Documentation Department API v1.0")
16 | )
17 | public class DepartmentApplication {
18 |
19 | public static void main(String[] args) {
20 | SpringApplication.run(DepartmentApplication.class, args);
21 | }
22 |
23 | @Bean
24 | DepartmentRepository repository() {
25 | DepartmentRepository repository = new DepartmentRepository();
26 | repository.add(new Department(1L, "Development"));
27 | repository.add(new Department(1L, "Operations"));
28 | repository.add(new Department(2L, "Development"));
29 | repository.add(new Department(2L, "Operations"));
30 | return repository;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/client/EmployeeClient.java:
--------------------------------------------------------------------------------
1 | package com.py.department.client;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 |
9 | import com.py.department.model.Employee;
10 |
11 | @FeignClient(name = "employee-service")
12 | public interface EmployeeClient {
13 |
14 | @GetMapping("/department/{departmentId}")
15 | List findByDepartment(@PathVariable("departmentId") Long departmentId);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/controller/DepartmentController.java:
--------------------------------------------------------------------------------
1 | package com.py.department.controller;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.web.bind.annotation.*;
6 | import com.py.department.client.EmployeeClient;
7 | import com.py.department.model.Department;
8 | import com.py.department.repository.DepartmentRepository;
9 |
10 | import java.util.List;
11 |
12 | @RestController
13 | public class DepartmentController {
14 |
15 | private static final Logger LOGGER = LoggerFactory.getLogger(DepartmentController.class);
16 |
17 | DepartmentRepository repository;
18 | EmployeeClient employeeClient;
19 |
20 | public DepartmentController(DepartmentRepository repository, EmployeeClient employeeClient) {
21 | this.repository = repository;
22 | this.employeeClient = employeeClient;
23 | }
24 |
25 | @PostMapping("/")
26 | public Department add(@RequestBody Department department) {
27 | LOGGER.info("Department add: {}", department);
28 | return repository.add(department);
29 | }
30 |
31 | @GetMapping("/{id}")
32 | public Department findById(@PathVariable("id") Long id) {
33 | LOGGER.info("Department find: id={}", id);
34 | return repository.findById(id);
35 | }
36 |
37 | @GetMapping("/")
38 | public List findAll() {
39 | LOGGER.info("Department find");
40 | return repository.findAll();
41 | }
42 |
43 | @GetMapping("/organization/{organizationId}")
44 | public List findByOrganization(@PathVariable("organizationId") Long organizationId) {
45 | LOGGER.info("Department find: organizationId={}", organizationId);
46 | return repository.findByOrganization(organizationId);
47 | }
48 |
49 | @GetMapping("/organization/{organizationId}/with-employees")
50 | public List findByOrganizationWithEmployees(@PathVariable("organizationId") Long organizationId) {
51 | LOGGER.info("Department find: organizationId={}", organizationId);
52 | List departments = repository.findByOrganization(organizationId);
53 | departments.forEach(d -> d.setEmployees(employeeClient.findByDepartment(d.getId())));
54 | return departments;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/model/Department.java:
--------------------------------------------------------------------------------
1 | package com.py.department.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Department {
7 |
8 | private Long id;
9 | private Long organizationId;
10 | private String name;
11 | private List employees = new ArrayList<>();
12 |
13 | public Department() {
14 |
15 | }
16 |
17 | public Department(Long organizationId, String name) {
18 | super();
19 | this.organizationId = organizationId;
20 | this.name = name;
21 | }
22 |
23 | public Long getId() {
24 | return id;
25 | }
26 |
27 | public void setId(Long id) {
28 | this.id = id;
29 | }
30 |
31 | public Long getOrganizationId() {
32 | return organizationId;
33 | }
34 |
35 | public void setOrganizationId(Long organizationId) {
36 | this.organizationId = organizationId;
37 | }
38 |
39 | public String getName() {
40 | return name;
41 | }
42 |
43 | public void setName(String name) {
44 | this.name = name;
45 | }
46 |
47 | public List getEmployees() {
48 | return employees;
49 | }
50 |
51 | public void setEmployees(List employees) {
52 | this.employees = employees;
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return "Department [id=" + id + ", organizationId=" + organizationId + ", name=" + name + "]";
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/model/Employee.java:
--------------------------------------------------------------------------------
1 | package com.py.department.model;
2 |
3 | public class Employee {
4 |
5 | private Long id;
6 | private String name;
7 | private int age;
8 | private String position;
9 |
10 | public Employee() {
11 |
12 | }
13 |
14 | public Employee(String name, int age, String position) {
15 | this.name = name;
16 | this.age = age;
17 | this.position = position;
18 | }
19 |
20 | public Long getId() {
21 | return id;
22 | }
23 |
24 | public void setId(Long id) {
25 | this.id = id;
26 | }
27 |
28 | public String getName() {
29 | return name;
30 | }
31 |
32 | public void setName(String name) {
33 | this.name = name;
34 | }
35 |
36 | public int getAge() {
37 | return age;
38 | }
39 |
40 | public void setAge(int age) {
41 | this.age = age;
42 | }
43 |
44 | public String getPosition() {
45 | return position;
46 | }
47 |
48 | public void setPosition(String position) {
49 | this.position = position;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "Employee [id=" + id + ", name=" + name + ", position=" + position + "]";
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/department-service/src/main/java/com/py/department/repository/DepartmentRepository.java:
--------------------------------------------------------------------------------
1 | package com.py.department.repository;
2 |
3 | import com.py.department.model.Department;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class DepartmentRepository {
9 |
10 | private List departments = new ArrayList<>();
11 |
12 | public Department add(Department department) {
13 | department.setId((long) (departments.size()+1));
14 | departments.add(department);
15 | return department;
16 | }
17 |
18 | public Department findById(Long id) {
19 | return departments.stream()
20 | .filter(a -> a.getId().equals(id))
21 | .findFirst()
22 | .orElseThrow();
23 | }
24 |
25 | public List findAll() {
26 | return departments;
27 | }
28 |
29 | public List findByOrganization(Long organizationId) {
30 | return departments.stream()
31 | .filter(a -> a.getOrganizationId().equals(organizationId))
32 | .toList();
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/department-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: department-service
4 |
5 | server:
6 | port: 0
7 |
8 | eureka:
9 | client:
10 | serviceUrl:
11 | defaultZone: http://localhost:8061/eureka/
12 |
13 | logging:
14 | pattern:
15 | console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"
16 |
17 | springdoc:
18 | packagesToScan: com.py.department
--------------------------------------------------------------------------------
/department-service/src/test/java/DepartmentRepositoryTest.java:
--------------------------------------------------------------------------------
1 | import org.junit.jupiter.api.MethodOrderer;
2 | import org.junit.jupiter.api.Order;
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.TestMethodOrder;
5 | import org.springframework.util.Assert;
6 | import com.py.department.model.Department;
7 | import com.py.department.repository.DepartmentRepository;
8 |
9 | import java.util.List;
10 |
11 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
12 | public class DepartmentRepositoryTest {
13 |
14 | private static final DepartmentRepository repository = new DepartmentRepository();
15 |
16 | @Test
17 | @Order(1)
18 | void testAddDepartment() {
19 | Department department = new Department(1L, "Test");
20 | department = repository.add(department);
21 | Assert.notNull(department, "Department is null.");
22 | Assert.isTrue(department.getId() == 1L, "Department bad id.");
23 | }
24 |
25 | @Test
26 | @Order(2)
27 | void testFindAll() {
28 | List departments = repository.findAll();
29 | Assert.isTrue(departments.size() == 1, "Departments size is wrong.");
30 | Assert.isTrue(departments.get(0).getId() == 1L, "Department bad id.");
31 | }
32 |
33 | @Test
34 | @Order(3)
35 | void testFindByOrganization() {
36 | List departments = repository.findByOrganization(1L);
37 | Assert.isTrue(departments.size() == 1, "Departments size is wrong.");
38 | Assert.isTrue(departments.get(0).getId() == 1L, "Department bad id.");
39 | }
40 |
41 | @Test
42 | @Order(4)
43 | void testFindById() {
44 | Department department = repository.findById(1L);
45 | Assert.notNull(department, "Department not found.");
46 | Assert.isTrue(department.getId() == 1L, "Department bad id.");
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/discovery-service/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.settings/
3 | /.classpath
4 | /.project
5 |
--------------------------------------------------------------------------------
/discovery-service/nb-configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 | true
17 |
18 |
19 |
--------------------------------------------------------------------------------
/discovery-service/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | process-classes
10 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
11 |
12 |
13 |
14 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
15 |
16 | com.py.discovery.DiscoveryApplication
17 | java
18 |
19 |
20 |
21 | debug
22 |
23 | jar
24 |
25 |
26 | process-classes
27 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
28 |
29 |
30 | -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}
31 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
32 |
33 | com.py.discovery.DiscoveryApplication
34 | java
35 | true
36 |
37 |
38 |
39 | profile
40 |
41 | jar
42 |
43 |
44 | process-classes
45 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
46 |
47 |
48 |
49 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
50 | com.py.discovery.DiscoveryApplication
51 | java
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/discovery-service/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.springframework.boot
6 | spring-boot-starter-parent
7 | 2.6.1
8 |
9 |
10 | discovery-service
11 | com.py
12 | 1.0-SNAPSHOT
13 |
14 |
15 | 17
16 | 2021.0.0
17 |
18 |
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-dependencies
24 | ${spring-cloud.version}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 | org.springframework.cloud
34 | spring-cloud-starter-netflix-eureka-server
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-maven-plugin
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/discovery-service/src/main/java/com/py/discovery/DiscoveryApplication.java:
--------------------------------------------------------------------------------
1 | package com.py.discovery;
2 |
3 | import org.springframework.boot.autoconfigure.SpringBootApplication;
4 | import org.springframework.boot.builder.SpringApplicationBuilder;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class DiscoveryApplication {
10 |
11 | public static void main(String[] args) {
12 | new SpringApplicationBuilder(DiscoveryApplication.class).run(args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/discovery-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: discovery-service
4 |
5 | server:
6 | port: 8061
7 |
8 | eureka:
9 | instance:
10 | hostname: localhost
11 | client:
12 | registerWithEureka: false
13 | fetchRegistry: false
14 | serviceUrl:
15 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
--------------------------------------------------------------------------------
/employee-service/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.classpath
3 | /.project
4 | /.settings/
5 |
--------------------------------------------------------------------------------
/employee-service/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | process-classes
10 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
11 |
12 |
13 |
14 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
15 |
16 | com.py.employee.EmployeeApplication
17 | java
18 |
19 |
20 |
21 | debug
22 |
23 | jar
24 |
25 |
26 | process-classes
27 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
28 |
29 |
30 | -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}
31 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
32 |
33 | com.py.employee.EmployeeApplication
34 | java
35 | true
36 |
37 |
38 |
39 | profile
40 |
41 | jar
42 |
43 |
44 | process-classes
45 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
46 |
47 |
48 |
49 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
50 | com.py.employee.EmployeeApplication
51 | java
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/employee-service/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.springframework.boot
6 | spring-boot-starter-parent
7 | 2.6.1
8 |
9 |
10 | employee-service
11 | com.py
12 | 1.0-SNAPSHOT
13 |
14 |
15 | 17
16 | 2021.0.0
17 |
18 |
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-dependencies
24 | ${spring-cloud.version}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 | org.springframework.cloud
34 | spring-cloud-starter-netflix-eureka-client
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-web
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-actuator
43 |
44 |
45 | org.springframework.cloud
46 | spring-cloud-starter-sleuth
47 |
48 |
49 | org.springdoc
50 | springdoc-openapi-webmvc-core
51 | 1.5.13
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-starter-test
56 | test
57 |
58 |
59 |
60 |
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-maven-plugin
65 |
66 |
67 | org.jacoco
68 | jacoco-maven-plugin
69 | 0.8.7
70 |
71 |
72 |
73 | prepare-agent
74 |
75 |
76 |
77 | report
78 | test
79 |
80 | report
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/employee-service/src/main/java/com/py/employee/EmployeeApplication.java:
--------------------------------------------------------------------------------
1 | package com.py.employee;
2 |
3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4 | import io.swagger.v3.oas.annotations.info.Info;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 | import com.py.employee.model.Employee;
9 | import com.py.employee.repository.EmployeeRepository;
10 |
11 | @SpringBootApplication
12 | @OpenAPIDefinition(info =
13 | @Info(title = "Employee API", version = "1.0", description = "Documentation Employee API v1.0")
14 | )
15 | public class EmployeeApplication {
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(EmployeeApplication.class, args);
19 | }
20 |
21 | @Bean
22 | EmployeeRepository repository() {
23 | EmployeeRepository repository = new EmployeeRepository();
24 | repository.add(new Employee(1L, 1L, "John Smith", 34, "Analyst"));
25 | repository.add(new Employee(1L, 1L, "Darren Hamilton", 37, "Manager"));
26 | repository.add(new Employee(1L, 1L, "Tom Scott", 26, "Developer"));
27 | repository.add(new Employee(1L, 2L, "Anna London", 39, "Analyst"));
28 | repository.add(new Employee(1L, 2L, "Patrick Dempsey", 27, "Developer"));
29 | repository.add(new Employee(2L, 3L, "Kevin Price", 38, "Developer"));
30 | repository.add(new Employee(2L, 3L, "Ian Scott", 34, "Developer"));
31 | repository.add(new Employee(2L, 3L, "Andrew Campton", 30, "Manager"));
32 | repository.add(new Employee(2L, 4L, "Steve Franklin", 25, "Developer"));
33 | repository.add(new Employee(2L, 4L, "Elisabeth Smith", 30, "Developer"));
34 | return repository;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/employee-service/src/main/java/com/py/employee/controller/EmployeeController.java:
--------------------------------------------------------------------------------
1 | package com.py.employee.controller;
2 |
3 | import java.util.List;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | import com.py.employee.model.Employee;
15 | import com.py.employee.repository.EmployeeRepository;
16 |
17 | @RestController
18 | public class EmployeeController {
19 |
20 | private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeController.class);
21 |
22 | @Autowired
23 | EmployeeRepository repository;
24 |
25 | @PostMapping("/")
26 | public Employee add(@RequestBody Employee employee) {
27 | LOGGER.info("Employee add: {}", employee);
28 | return repository.add(employee);
29 | }
30 |
31 | @GetMapping("/{id}")
32 | public Employee findById(@PathVariable("id") Long id) {
33 | LOGGER.info("Employee find: id={}", id);
34 | return repository.findById(id);
35 | }
36 |
37 | @GetMapping("/")
38 | public List findAll() {
39 | LOGGER.info("Employee find");
40 | return repository.findAll();
41 | }
42 |
43 | @GetMapping("/department/{departmentId}")
44 | public List findByDepartment(@PathVariable("departmentId") Long departmentId) {
45 | LOGGER.info("Employee find: departmentId={}", departmentId);
46 | return repository.findByDepartment(departmentId);
47 | }
48 |
49 | @GetMapping("/organization/{organizationId}")
50 | public List findByOrganization(@PathVariable("organizationId") Long organizationId) {
51 | LOGGER.info("Employee find: organizationId={}", organizationId);
52 | return repository.findByOrganization(organizationId);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/employee-service/src/main/java/com/py/employee/model/Employee.java:
--------------------------------------------------------------------------------
1 | package com.py.employee.model;
2 |
3 | public class Employee {
4 |
5 | private Long id;
6 | private Long organizationId;
7 | private Long departmentId;
8 | private String name;
9 | private int age;
10 | private String position;
11 |
12 | public Employee() {
13 |
14 | }
15 |
16 | public Employee(Long organizationId, Long departmentId, String name, int age, String position) {
17 | this.organizationId = organizationId;
18 | this.departmentId = departmentId;
19 | this.name = name;
20 | this.age = age;
21 | this.position = position;
22 | }
23 |
24 | public Long getId() {
25 | return id;
26 | }
27 |
28 | public void setId(Long id) {
29 | this.id = id;
30 | }
31 |
32 | public Long getOrganizationId() {
33 | return organizationId;
34 | }
35 |
36 | public void setOrganizationId(Long organizationId) {
37 | this.organizationId = organizationId;
38 | }
39 |
40 | public Long getDepartmentId() {
41 | return departmentId;
42 | }
43 |
44 | public void setDepartmentId(Long departmentId) {
45 | this.departmentId = departmentId;
46 | }
47 |
48 | public String getName() {
49 | return name;
50 | }
51 |
52 | public void setName(String name) {
53 | this.name = name;
54 | }
55 |
56 | public int getAge() {
57 | return age;
58 | }
59 |
60 | public void setAge(int age) {
61 | this.age = age;
62 | }
63 |
64 | public String getPosition() {
65 | return position;
66 | }
67 |
68 | public void setPosition(String position) {
69 | this.position = position;
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return "Employee [id=" + id + ", organizationId=" + organizationId + ", departmentId=" + departmentId
75 | + ", name=" + name + ", position=" + position + "]";
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/employee-service/src/main/java/com/py/employee/repository/EmployeeRepository.java:
--------------------------------------------------------------------------------
1 | package com.py.employee.repository;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Optional;
6 | import java.util.stream.Collectors;
7 |
8 | import com.py.employee.model.Employee;
9 |
10 | public class EmployeeRepository {
11 |
12 | private List employees = new ArrayList<>();
13 |
14 | public Employee add(Employee employee) {
15 | employee.setId((long) (employees.size()+1));
16 | employees.add(employee);
17 | return employee;
18 | }
19 |
20 | public Employee findById(Long id) {
21 | return employees.stream()
22 | .filter(a -> a.getId().equals(id))
23 | .findFirst()
24 | .orElseThrow();
25 | }
26 |
27 | public List findAll() {
28 | return employees;
29 | }
30 |
31 | public List findByDepartment(Long departmentId) {
32 | return employees.stream()
33 | .filter(a -> a.getDepartmentId().equals(departmentId))
34 | .toList();
35 | }
36 |
37 | public List findByOrganization(Long organizationId) {
38 | return employees.stream()
39 | .filter(a -> a.getOrganizationId().equals(organizationId))
40 | .toList();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/employee-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: employee-service
4 |
5 | server:
6 | port: 0
7 |
8 | eureka:
9 | client:
10 | serviceUrl:
11 | defaultZone: http://localhost:8061/eureka/
12 |
13 | logging:
14 | pattern:
15 | console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"
16 |
17 | springdoc:
18 | packagesToScan: com.py.employee
--------------------------------------------------------------------------------
/employee-service/src/test/java/pl/piomin/services/employee/EmployeeRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.py.employee;
2 |
3 | import org.junit.jupiter.api.MethodOrderer;
4 | import org.junit.jupiter.api.Order;
5 | import org.junit.jupiter.api.Test;
6 | import org.junit.jupiter.api.TestMethodOrder;
7 | import org.springframework.util.Assert;
8 | import com.py.employee.model.Employee;
9 | import com.py.employee.repository.EmployeeRepository;
10 |
11 | import java.util.List;
12 |
13 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
14 | public class EmployeeRepositoryTest {
15 |
16 | private static final EmployeeRepository repository = new EmployeeRepository();
17 |
18 | @Test
19 | @Order(1)
20 | void testAddEmployee() {
21 | Employee employee = new Employee(1L, 1L, "Test Test", 100, "Test");
22 | employee = repository.add(employee);
23 | Assert.notNull(employee, "Employee is null.");
24 | Assert.isTrue(employee.getId() == 1L, "Employee bad id.");
25 | }
26 |
27 | @Test
28 | @Order(2)
29 | void testFindAll() {
30 | List employees = repository.findAll();
31 | Assert.isTrue(employees.size() == 1, "Employees size is wrong.");
32 | Assert.isTrue(employees.get(0).getId() == 1L, "Employee bad id.");
33 | }
34 |
35 | @Test
36 | @Order(3)
37 | void testFindByDepartment() {
38 | List employees = repository.findByDepartment(1L);
39 | Assert.isTrue(employees.size() == 1, "Employees size is wrong.");
40 | Assert.isTrue(employees.get(0).getId() == 1L, "Employee bad id.");
41 | }
42 |
43 | @Test
44 | @Order(4)
45 | void testFindByOrganization() {
46 | List employees = repository.findByOrganization(1L);
47 | Assert.isTrue(employees.size() == 1, "Employees size is wrong.");
48 | Assert.isTrue(employees.get(0).getId() == 1L, "Employee bad id.");
49 | }
50 |
51 | @Test
52 | @Order(5)
53 | void testFindById() {
54 | Employee employee = repository.findById(1L);
55 | Assert.notNull(employee, "Employee not found.");
56 | Assert.isTrue(employee.getId() == 1L, "Employee bad id.");
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/gateway-service/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.classpath
3 | /.project
4 | /.settings/
5 |
--------------------------------------------------------------------------------
/gateway-service/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | process-classes
10 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
11 |
12 |
13 |
14 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
15 |
16 | com.py.gateway.GatewayApplication
17 | java
18 |
19 |
20 |
21 | debug
22 |
23 | jar
24 |
25 |
26 | process-classes
27 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
28 |
29 |
30 | -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}
31 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
32 |
33 | com.py.gateway.GatewayApplication
34 | java
35 | true
36 |
37 |
38 |
39 | profile
40 |
41 | jar
42 |
43 |
44 | process-classes
45 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
46 |
47 |
48 |
49 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
50 | com.py.gateway.GatewayApplication
51 | java
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/gateway-service/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.springframework.boot
6 | spring-boot-starter-parent
7 | 2.6.1
8 |
9 |
10 | gateway-service
11 | com.py
12 | 1.0-SNAPSHOT
13 |
14 |
15 | 17
16 | 2021.0.0
17 |
18 |
19 |
20 |
21 | org.springframework.cloud
22 | spring-cloud-starter-gateway
23 |
24 |
25 | org.springframework.cloud
26 | spring-cloud-starter-netflix-eureka-client
27 |
28 |
29 | org.springframework.cloud
30 | spring-cloud-starter-sleuth
31 |
32 |
33 | org.springdoc
34 | springdoc-openapi-webflux-core
35 | 1.5.13
36 |
37 |
38 | org.springdoc
39 | springdoc-openapi-webflux-ui
40 | 1.5.13
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.springframework.cloud
48 | spring-cloud-dependencies
49 | ${spring-cloud.version}
50 | pom
51 | import
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-maven-plugin
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/gateway-service/src/main/java/com/py/gateway/GatewayApplication.java:
--------------------------------------------------------------------------------
1 | package com.py.gateway;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springdoc.core.GroupedOpenApi;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
10 | import org.springframework.cloud.gateway.route.RouteDefinition;
11 | import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
12 | import org.springframework.context.annotation.Bean;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | @SpringBootApplication
18 | @EnableDiscoveryClient
19 | public class GatewayApplication {
20 |
21 | private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class);
22 |
23 | public static void main(String[] args) {
24 | SpringApplication.run(GatewayApplication.class, args);
25 | }
26 |
27 | @Autowired
28 | RouteDefinitionLocator locator;
29 |
30 | @Bean
31 | public List apis() {
32 | List groups = new ArrayList<>();
33 | List definitions = locator.getRouteDefinitions().collectList().block();
34 | assert definitions != null;
35 | definitions.stream().filter(routeDefinition -> routeDefinition.getId().matches(".*-service")).forEach(routeDefinition -> {
36 | String name = routeDefinition.getId().replaceAll("-service", "");
37 | groups.add(GroupedOpenApi.builder().pathsToMatch("/" + name + "/**").group(name).build());
38 | });
39 | return groups;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/gateway-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8060
3 |
4 | eureka:
5 | client:
6 | serviceUrl:
7 | defaultZone: http://localhost:8061/eureka/
8 |
9 | logging:
10 | pattern:
11 | console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"
12 |
13 | spring:
14 | application:
15 | name: gateway-service
16 | cloud:
17 | gateway:
18 | discovery:
19 | locator:
20 | enabled: true
21 | routes:
22 | - id: employee-service
23 | uri: lb://employee-service
24 | predicates:
25 | - Path=/employee/**
26 | filters:
27 | - RewritePath=/employee/(?.*), /$\{path}
28 | - id: department-service
29 | uri: lb://department-service
30 | predicates:
31 | - Path=/department/**
32 | filters:
33 | - RewritePath=/department/(?.*), /$\{path}
34 | - id: organization-service
35 | uri: lb://organization-service
36 | predicates:
37 | - Path=/organization/**
38 | filters:
39 | - RewritePath=/organization/(?.*), /$\{path}
40 | - id: openapi
41 | uri: http://localhost:${server.port}
42 | predicates:
43 | - Path=/v3/api-docs/**
44 | filters:
45 | - RewritePath=/v3/api-docs/(?.*), /$\{path}/v3/api-docs
46 |
47 | springdoc:
48 | swagger-ui:
49 | urls:
50 | - name: employee
51 | url: /v3/api-docs/employee
52 | - name: department
53 | url: /v3/api-docs/department
54 | - name: organization
55 | url: /v3/api-docs/organization
--------------------------------------------------------------------------------
/organization-service/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.classpath
3 | /.project
4 | /.settings/
5 |
--------------------------------------------------------------------------------
/organization-service/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | process-classes
10 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
11 |
12 |
13 |
14 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
15 |
16 | com.py.organization.OrganizationApplication
17 | java
18 |
19 |
20 |
21 | debug
22 |
23 | jar
24 |
25 |
26 | process-classes
27 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
28 |
29 |
30 | -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}
31 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
32 |
33 | com.py.organization.OrganizationApplication
34 | java
35 | true
36 |
37 |
38 |
39 | profile
40 |
41 | jar
42 |
43 |
44 | process-classes
45 | org.codehaus.mojo:exec-maven-plugin:3.0.0:exec
46 |
47 |
48 |
49 | ${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}
50 | com.py.organization.OrganizationApplication
51 | java
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/organization-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | org.springframework.boot
5 | spring-boot-starter-parent
6 | 2.6.1
7 |
8 |
9 | organization-service
10 | com.py
11 | 1.0-SNAPSHOT
12 |
13 |
14 | 17
15 | 2021.0.0
16 |
17 |
18 |
19 |
20 |
21 | org.springframework.cloud
22 | spring-cloud-dependencies
23 | ${spring-cloud.version}
24 | pom
25 | import
26 |
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.cloud
33 | spring-cloud-starter-netflix-eureka-client
34 |
35 |
36 | org.springframework.cloud
37 | spring-cloud-starter-openfeign
38 |
39 |
40 | org.springframework.cloud
41 | spring-cloud-openfeign-core
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-web
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-starter-actuator
50 |
51 |
52 | org.springframework.cloud
53 | spring-cloud-starter-sleuth
54 |
55 |
56 | org.springdoc
57 | springdoc-openapi-webmvc-core
58 | 1.5.13
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-test
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-maven-plugin
72 |
73 |
74 | org.jacoco
75 | jacoco-maven-plugin
76 | 0.8.7
77 |
78 |
79 |
80 | prepare-agent
81 |
82 |
83 |
84 | report
85 | test
86 |
87 | report
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/OrganizationApplication.java:
--------------------------------------------------------------------------------
1 | package com.py.organization;
2 |
3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4 | import io.swagger.v3.oas.annotations.info.Info;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 | import org.springframework.context.annotation.Bean;
9 | import com.py.organization.model.Organization;
10 | import com.py.organization.repository.OrganizationRepository;
11 |
12 | @SpringBootApplication
13 | @EnableFeignClients
14 | @OpenAPIDefinition(info =
15 | @Info(title = "Organization API", version = "1.0", description = "Documentation Organization API v1.0")
16 | )
17 | public class OrganizationApplication {
18 |
19 | public static void main(String[] args) {
20 | SpringApplication.run(OrganizationApplication.class, args);
21 | }
22 |
23 | @Bean
24 | OrganizationRepository repository() {
25 | OrganizationRepository repository = new OrganizationRepository();
26 | repository.add(new Organization("Microsoft", "Redmond, Washington, USA"));
27 | repository.add(new Organization("Oracle", "Redwood City, California, USA"));
28 | return repository;
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/client/DepartmentClient.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.client;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 |
9 | import com.py.organization.model.Department;
10 |
11 | @FeignClient(name = "department-service")
12 | public interface DepartmentClient {
13 |
14 | @GetMapping("/organization/{organizationId}")
15 | public List findByOrganization(@PathVariable("organizationId") Long organizationId);
16 |
17 | @GetMapping("/organization/{organizationId}/with-employees")
18 | public List findByOrganizationWithEmployees(@PathVariable("organizationId") Long organizationId);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/client/EmployeeClient.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.client;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 |
9 | import com.py.organization.model.Employee;
10 |
11 | @FeignClient(name = "employee-service")
12 | public interface EmployeeClient {
13 |
14 | @GetMapping("/organization/{organizationId}")
15 | List findByOrganization(@PathVariable("organizationId") Long organizationId);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/controller/OrganizationController.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.controller;
2 |
3 | import java.util.List;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | import com.py.organization.client.DepartmentClient;
15 | import com.py.organization.client.EmployeeClient;
16 | import com.py.organization.model.Organization;
17 | import com.py.organization.repository.OrganizationRepository;
18 |
19 | @RestController
20 | public class OrganizationController {
21 |
22 | private static final Logger LOGGER = LoggerFactory.getLogger(OrganizationController.class);
23 |
24 | @Autowired
25 | OrganizationRepository repository;
26 | @Autowired
27 | DepartmentClient departmentClient;
28 | @Autowired
29 | EmployeeClient employeeClient;
30 |
31 | @PostMapping
32 | public Organization add(@RequestBody Organization organization) {
33 | LOGGER.info("Organization add: {}", organization);
34 | return repository.add(organization);
35 | }
36 |
37 | @GetMapping
38 | public List findAll() {
39 | LOGGER.info("Organization find");
40 | return repository.findAll();
41 | }
42 |
43 | @GetMapping("/{id}")
44 | public Organization findById(@PathVariable("id") Long id) {
45 | LOGGER.info("Organization find: id={}", id);
46 | return repository.findById(id);
47 | }
48 |
49 | @GetMapping("/{id}/with-departments")
50 | public Organization findByIdWithDepartments(@PathVariable("id") Long id) {
51 | LOGGER.info("Organization find: id={}", id);
52 | Organization organization = repository.findById(id);
53 | organization.setDepartments(departmentClient.findByOrganization(organization.getId()));
54 | return organization;
55 | }
56 |
57 | @GetMapping("/{id}/with-departments-and-employees")
58 | public Organization findByIdWithDepartmentsAndEmployees(@PathVariable("id") Long id) {
59 | LOGGER.info("Organization find: id={}", id);
60 | Organization organization = repository.findById(id);
61 | organization.setDepartments(departmentClient.findByOrganizationWithEmployees(organization.getId()));
62 | return organization;
63 | }
64 |
65 | @GetMapping("/{id}/with-employees")
66 | public Organization findByIdWithEmployees(@PathVariable("id") Long id) {
67 | LOGGER.info("Organization find: id={}", id);
68 | Organization organization = repository.findById(id);
69 | organization.setEmployees(employeeClient.findByOrganization(organization.getId()));
70 | return organization;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/model/Department.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Department {
7 |
8 | private Long id;
9 | private String name;
10 | private List employees = new ArrayList<>();
11 |
12 | public Department() {
13 |
14 | }
15 |
16 | public Department(String name) {
17 | super();
18 | this.name = name;
19 | }
20 |
21 | public Long getId() {
22 | return id;
23 | }
24 |
25 | public void setId(Long id) {
26 | this.id = id;
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public void setName(String name) {
34 | this.name = name;
35 | }
36 |
37 | public List getEmployees() {
38 | return employees;
39 | }
40 |
41 | public void setEmployees(List employees) {
42 | this.employees = employees;
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "Department [id=" + id + ", name=" + name + "]";
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/model/Employee.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.model;
2 |
3 | public class Employee {
4 |
5 | private Long id;
6 | private String name;
7 | private int age;
8 | private String position;
9 |
10 | public Employee() {
11 |
12 | }
13 |
14 | public Employee(String name, int age, String position) {
15 | this.name = name;
16 | this.age = age;
17 | this.position = position;
18 | }
19 |
20 | public Long getId() {
21 | return id;
22 | }
23 |
24 | public void setId(Long id) {
25 | this.id = id;
26 | }
27 |
28 | public String getName() {
29 | return name;
30 | }
31 |
32 | public void setName(String name) {
33 | this.name = name;
34 | }
35 |
36 | public int getAge() {
37 | return age;
38 | }
39 |
40 | public void setAge(int age) {
41 | this.age = age;
42 | }
43 |
44 | public String getPosition() {
45 | return position;
46 | }
47 |
48 | public void setPosition(String position) {
49 | this.position = position;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "Employee [id=" + id + ", name=" + name + ", position=" + position + "]";
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/model/Organization.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Organization {
7 |
8 | private Long id;
9 | private String name;
10 | private String address;
11 | private List departments = new ArrayList<>();
12 | private List employees = new ArrayList<>();
13 |
14 | public Organization() {
15 |
16 | }
17 |
18 | public Organization(String name, String address) {
19 | this.name = name;
20 | this.address = address;
21 | }
22 |
23 | public Long getId() {
24 | return id;
25 | }
26 |
27 | public void setId(Long id) {
28 | this.id = id;
29 | }
30 |
31 | public String getName() {
32 | return name;
33 | }
34 |
35 | public void setName(String name) {
36 | this.name = name;
37 | }
38 |
39 | public String getAddress() {
40 | return address;
41 | }
42 |
43 | public void setAddress(String address) {
44 | this.address = address;
45 | }
46 |
47 | public List getDepartments() {
48 | return departments;
49 | }
50 |
51 | public void setDepartments(List departments) {
52 | this.departments = departments;
53 | }
54 |
55 | public List getEmployees() {
56 | return employees;
57 | }
58 |
59 | public void setEmployees(List employees) {
60 | this.employees = employees;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return "Organization [id=" + id + ", name=" + name + ", address=" + address + "]";
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/organization-service/src/main/java/com/py/organization/repository/OrganizationRepository.java:
--------------------------------------------------------------------------------
1 | package com.py.organization.repository;
2 |
3 | import com.py.organization.model.Organization;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class OrganizationRepository {
9 |
10 | private List organizations = new ArrayList<>();
11 |
12 | public Organization add(Organization organization) {
13 | organization.setId((long) (organizations.size()+1));
14 | organizations.add(organization);
15 | return organization;
16 | }
17 |
18 | public Organization findById(Long id) {
19 | return organizations.stream()
20 | .filter(a -> a.getId().equals(id))
21 | .findFirst()
22 | .orElseThrow();
23 | }
24 |
25 | public List findAll() {
26 | return organizations;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/organization-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: organization-service
4 |
5 | server:
6 | port: 0
7 |
8 | eureka:
9 | client:
10 | serviceUrl:
11 | defaultZone: http://localhost:8061/eureka/
12 |
13 | logging:
14 | pattern:
15 | console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"
16 |
17 | springdoc:
18 | packagesToScan: com.py.organization
--------------------------------------------------------------------------------
/organization-service/src/test/java/OrganizationRepositoryTest.java:
--------------------------------------------------------------------------------
1 | import org.junit.jupiter.api.MethodOrderer;
2 | import org.junit.jupiter.api.Order;
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.TestMethodOrder;
5 | import org.springframework.util.Assert;
6 | import com.py.organization.model.Organization;
7 | import com.py.organization.repository.OrganizationRepository;
8 |
9 | import java.util.List;
10 |
11 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
12 | public class OrganizationRepositoryTest {
13 |
14 | private static OrganizationRepository repository = new OrganizationRepository();
15 |
16 | @Test
17 | @Order(1)
18 | public void testAddOrganization() {
19 | Organization organization = new Organization("Test", "Test Street");
20 | organization = repository.add(organization);
21 | Assert.notNull(organization, "Organization is null.");
22 | Assert.isTrue(organization.getId() == 1L, "Organization bad id.");
23 | }
24 |
25 | @Test
26 | @Order(2)
27 | public void testFindAll() {
28 | List organizations = repository.findAll();
29 | Assert.isTrue(organizations.size() == 1, "Organizations size is wrong.");
30 | Assert.isTrue(organizations.get(0).getId() == 1L, "Organization bad id.");
31 | }
32 |
33 | @Test
34 | @Order(3)
35 | public void testFindById() {
36 | Organization organization = repository.findById(1L);
37 | Assert.notNull(organization, "Organization not found.");
38 | Assert.isTrue(organization.getId() == 1L, "Organization bad id.");
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.py
5 | sample-spring-microservices
6 | 1.0-SNAPSHOT
7 | pom
8 |
9 |
10 |
11 |
12 |
13 | discovery-service
14 | config-service
15 | employee-service
16 | department-service
17 | organization-service
18 | gateway-service
19 |
20 |
21 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Microservices with Spring Cloud Demo Project
--------------------------------------------------------------------------------