diff --git a/tepechin_kirill_lab_3/README.md b/tepechin_kirill_lab_3/README.md new file mode 100644 index 0000000..8ddebaa --- /dev/null +++ b/tepechin_kirill_lab_3/README.md @@ -0,0 +1,97 @@ +## Лабораторная работа №3, ПИбд-42 Тепечин Кирилл + +### Сервисы +* `opop-service` +* `document-service` + +### Синхронный обмен между микросервисами +Синхронное взаимодействие осуществляется через `RestTemplate` + +Пример взаимодействия: + +````java +restTemplate.getForObject(URL+ opopDto.getDocumentId(), DocumentInfo.class) +```` + +### Докерфайлы + +````dockerfile +FROM eclipse-temurin:17-jdk-alpine +VOLUME /tmp +ARG JAR_FILE +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java","-jar","/app.jar"] +```` +### docker-compose файл +````yaml +version: '3' +services: + opop-service: + build: + context: /opop-service + dockerfile: Dockerfile + args: + JAR_FILE: build/libs/*.jar + ports: + - "8080:8080" + networks: + - my-network + environment: + server.forward-headers-strategy: framework + + document-service: + build: + context: /document-service + dockerfile: Dockerfile + args: + JAR_FILE: build/libs/*.jar + ports: + - "8081:8081" + networks: + - my-network + environment: + server.forward-headers-strategy: framework + + nginx: + image: nginx + ports: + - "80:80" + networks: + - my-network + volumes: + - ./nginx-conf:/etc/nginx/conf.d + depends_on: + - opop-service + - document-service + +networks: + my-network: + driver: bridge +```` + +### nginx.conf +```` +server { + listen 80; + + location /opop-service/ { + proxy_pass_request_headers on; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Prefix '/opop-service'; + proxy_pass http://opop-service:8080/; + } + + location /document-service/ { + proxy_pass_request_headers on; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Prefix '/document-service'; + proxy_pass http://document-service:8081/; + + } +} +```` + +### Ссылка на видео +https://vk.com/video170089763_456239482?list=ln-0DBU1KuruzjrZvKRLE + + diff --git a/tepechin_kirill_lab_3/docker-compose.yml b/tepechin_kirill_lab_3/docker-compose.yml new file mode 100644 index 0000000..3cb4c91 --- /dev/null +++ b/tepechin_kirill_lab_3/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3' +services: + opop-service: + build: + context: /opop-service + dockerfile: Dockerfile + args: + JAR_FILE: build/libs/*.jar + ports: + - "8080:8080" + networks: + - my-network + environment: + server.forward-headers-strategy: framework + + document-service: + build: + context: /document-service + dockerfile: Dockerfile + args: + JAR_FILE: build/libs/*.jar + ports: + - "8081:8081" + networks: + - my-network + environment: + server.forward-headers-strategy: framework + + nginx: + image: nginx + ports: + - "80:80" + networks: + - my-network + volumes: + - ./nginx-conf:/etc/nginx/conf.d + depends_on: + - opop-service + - document-service + +networks: + my-network: + driver: bridge \ No newline at end of file diff --git a/tepechin_kirill_lab_3/document-service/Dockerfile b/tepechin_kirill_lab_3/document-service/Dockerfile new file mode 100644 index 0000000..66c9734 --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:17-jdk-alpine +VOLUME /tmp +ARG JAR_FILE +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/tepechin_kirill_lab_3/document-service/build.gradle b/tepechin_kirill_lab_3/document-service/build.gradle new file mode 100644 index 0000000..04c2f61 --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.0.0' + id 'io.spring.dependency-management' version '1.1.0' +} + +group = 'org.example' +version = '1.0-SNAPSHOT' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' +// implementation 'org.mapstruct:mapstruct:1.5.3.Final' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.3' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' + + + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Document.java b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Document.java new file mode 100644 index 0000000..9fa65c7 --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Document.java @@ -0,0 +1,17 @@ +package org.example; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Document { + @JsonView(Views.Private.class) + private long id; + @JsonView(Views.Public.class) + private String text; +} diff --git a/tepechin_kirill_lab_3/document-service/src/main/java/org/example/DocumentApplication.java b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/DocumentApplication.java new file mode 100644 index 0000000..9643d4a --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/DocumentApplication.java @@ -0,0 +1,11 @@ +package org.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DocumentApplication { + public static void main(String[] args) { + SpringApplication.run(DocumentApplication.class, args); + } +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Views.java b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Views.java new file mode 100644 index 0000000..1fd9488 --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/src/main/java/org/example/Views.java @@ -0,0 +1,6 @@ +package org.example; + +public class Views { + public interface Public {} + public interface Private extends Public {} +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/document-service/src/main/resources/application.yml b/tepechin_kirill_lab_3/document-service/src/main/resources/application.yml new file mode 100644 index 0000000..b12d076 --- /dev/null +++ b/tepechin_kirill_lab_3/document-service/src/main/resources/application.yml @@ -0,0 +1,3 @@ +server: + port: 8081 + forward-headers-strategy=framework: \ No newline at end of file diff --git a/tepechin_kirill_lab_3/nginx-conf/nginx.conf b/tepechin_kirill_lab_3/nginx-conf/nginx.conf new file mode 100644 index 0000000..75964c1 --- /dev/null +++ b/tepechin_kirill_lab_3/nginx-conf/nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + + location /opop-service/ { + proxy_pass_request_headers on; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Prefix '/opop-service'; + proxy_pass http://opop-service:8080/; + } + + location /document-service/ { + proxy_pass_request_headers on; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Prefix '/document-service'; + proxy_pass http://document-service:8081/; + + } +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/opop-service/Dockerfile b/tepechin_kirill_lab_3/opop-service/Dockerfile new file mode 100644 index 0000000..8e8de35 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:17-jdk-alpine +VOLUME /tmp +ARG JAR_FILE +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/tepechin_kirill_lab_3/opop-service/build.gradle b/tepechin_kirill_lab_3/opop-service/build.gradle new file mode 100644 index 0000000..59e5a6c --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.0.0' + id 'io.spring.dependency-management' version '1.1.0' +} + +group = 'org.example' +version = '1.0-SNAPSHOT' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.mapstruct:mapstruct:1.5.3.Final' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.3' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' + + + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/Opop.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/Opop.java new file mode 100644 index 0000000..bd97ad5 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/Opop.java @@ -0,0 +1,17 @@ +package org.example; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.example.dto.DocumentInfo; + +import java.util.List; +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Opop { + private long id; + private String code; + private int studyDuration; + private DocumentInfo documentInfo; +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopApplication.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopApplication.java new file mode 100644 index 0000000..01fae73 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopApplication.java @@ -0,0 +1,11 @@ +package org.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class OpopApplication { + public static void main(String[] args) { + SpringApplication.run(OpopApplication.class, args); + } +} \ No newline at end of file diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopController.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopController.java new file mode 100644 index 0000000..0e3c2a9 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopController.java @@ -0,0 +1,49 @@ +package org.example; + +import org.example.dto.OpopDtoCreate; +import org.example.dto.OpopDtoDetails; +import org.example.dto.OpopDtoList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/opop") +public class OpopController { + + @Autowired + private OpopStorage opopStorage; + + @GetMapping + public List getAllOpops(){ + return opopStorage.getAllOpops(); + } + @GetMapping("/{id}") + public OpopDtoDetails getOpopDetails(@PathVariable long id){ + return opopStorage.getOpopDetails(id); + } + + @PostMapping + public OpopDtoDetails addOpop(@RequestBody OpopDtoCreate opopDtoCreate){ + return opopStorage.addOpop(opopDtoCreate); + } + + @PutMapping + public void editOpop(@RequestBody OpopDtoList opopDtoList){ + opopStorage.editOpop(opopDtoList); + } + + @DeleteMapping("/{id}") + public void deleteOpop(@PathVariable long id){ + opopStorage.deleteOpop(id); + } + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(Exception.class) + public String handleNotFound(Exception e) { + return e.getMessage(); + } + +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopMapper.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopMapper.java new file mode 100644 index 0000000..c8bbca7 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopMapper.java @@ -0,0 +1,17 @@ +package org.example; + +import org.example.dto.OpopDtoCreate; +import org.example.dto.OpopDtoDetails; +import org.example.dto.OpopDtoList; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.ReportingPolicy; + +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface OpopMapper { + @Mapping(target = "documentId", source = "documentInfo.id") + OpopDtoList toListDto(Opop opop); + OpopDtoDetails toDetailsDto(Opop opop); + @Mapping(source = "documentId", target = "documentInfo.id") + Opop fromCreateDto(OpopDtoCreate opopDtoCreate); +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopStorage.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopStorage.java new file mode 100644 index 0000000..bbdbfe2 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/OpopStorage.java @@ -0,0 +1,65 @@ +package org.example; + +import org.example.dto.DocumentInfo; +import org.example.dto.OpopDtoCreate; +import org.example.dto.OpopDtoDetails; +import org.example.dto.OpopDtoList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class OpopStorage { + @Autowired + private OpopMapper opopMapper; + private long currentId = 1; + private final RestTemplate restTemplate = new RestTemplate(); + private static final List opopList = new ArrayList<>(); + private final String URL = "http://document-service:8081/document/"; + + public List getAllOpops(){ + return opopList.stream().map(opop -> opopMapper.toListDto(opop)).toList(); + } + + public OpopDtoDetails getOpopDetails(long id){ + return opopMapper.toDetailsDto(opopList.stream() + .filter(opop -> opop.getId() == id).toList().get(0)); + } + + public OpopDtoDetails addOpop(OpopDtoCreate opopDtoCreate){ + long id = currentId++; + Opop opop = opopMapper.fromCreateDto(opopDtoCreate); + opop.setId(id); + opop.setDocumentInfo(restTemplate.getForObject(URL+ opopDtoCreate.getDocumentId(), DocumentInfo.class)); + + opopList.add(opop); + return opopMapper.toDetailsDto(opop); + } + + public void deleteOpop(long id){ + opopList.remove(opopList.stream().filter(opop -> opop.getId() == id).toList().get(0)); + } + + public void editOpop(OpopDtoList opopDto){ + int index = findIndexById(opopDto.getId()); + Opop opop = opopList.get(index); + opop.setCode(opopDto.getCode()); + opop.setStudyDuration(opopDto.getStudyDuration()); + opop.setDocumentInfo(restTemplate.getForObject(URL+ opopDto.getDocumentId(), DocumentInfo.class)); + + opopList.set(index, opop); + } + + private int findIndexById(long idToFind) { + for (int i = 0; i < opopList.size(); i++) { + Opop obj = opopList.get(i); + if (obj.getId() == idToFind) { + return i; + } + } + return -1; + } +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoCreate.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoCreate.java new file mode 100644 index 0000000..b598bf5 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoCreate.java @@ -0,0 +1,14 @@ +package org.example.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OpopDtoCreate { + private String code; + private int studyDuration; + private int documentId; +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoDetails.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoDetails.java new file mode 100644 index 0000000..ae5b342 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoDetails.java @@ -0,0 +1,15 @@ +package org.example.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OpopDtoDetails { + private long id; + private String code; + private int studyDuration; + private DocumentInfo documentInfo; +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoList.java b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoList.java new file mode 100644 index 0000000..ce1c69d --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/java/org/example/dto/OpopDtoList.java @@ -0,0 +1,15 @@ +package org.example.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OpopDtoList { + private long id; + private String code; + private int studyDuration; + private int documentId; +} diff --git a/tepechin_kirill_lab_3/opop-service/src/main/resources/application.yml b/tepechin_kirill_lab_3/opop-service/src/main/resources/application.yml new file mode 100644 index 0000000..3d1ccb0 --- /dev/null +++ b/tepechin_kirill_lab_3/opop-service/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + forward-headers-strategy=framework: \ No newline at end of file