diff --git a/shadaev_anton_lab_3/README.md b/shadaev_anton_lab_3/README.md new file mode 100644 index 0000000..43e22e2 --- /dev/null +++ b/shadaev_anton_lab_3/README.md @@ -0,0 +1,74 @@ +# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами +Цель: + +Изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API. + +Задачи: + +Создать 2 микросервиса, реализующих CRUD на связанных сущностях. Реализовать механизм синхронного обмена сообщениями между микросервисами. Реализовать шлюз на основе прозрачного прокси-сервера nginx. + +## Запуск: + +Чтобы запустить контейнеры в docker, необходимо выполнить следующую команду: `docker-compose -f \ docker-compose.yml up -d`, где: + + -f - путь до docker-compose.yml файла + -d - фоновый режим запуска + + +## Демонстрация работы программы +### Сервис Aggregator +POST-метод для создания вакансии + +![1.png](screenshots%2F1.png) + +GET-метод для получения вакансии по id + +![2.png](screenshots%2F2.png) + +GET-метод для получения списка вакансий + +![3.png](screenshots%2F3.png) + +PUT-метод для обновления вакансии + +![4.png](screenshots%2F4.png) + +DELETE-метод для удаления вакансии + +![5.png](screenshots%2F5.png) + +### Метод, связывающий оба микросервиса +Демонстрация работы: + +![img_12.png](screenshots%2Fimg_12.png) + +### Сущности +Page -> Jobs (One-to-Many) + +![img.png](screenshots/test/img.png) + +![img_1.png](screenshots/test/img_1.png) + +### Dockerfile (aggregator-api) + +![img_2.png](screenshots/test/img_2.png) + +### Dockerfile (parser-api) + +![img_3.png](screenshots/test/img_3.png) + +### Docker compose + +![img_4.png](screenshots/test/img_4.png) + +![img_5.png](screenshots/test/img_5.png) + +![img_6.png](screenshots/test/img_6.png) + +![img_7.png](screenshots/test/img_7.png) + +### Nginx +![img_8.png](screenshots%2Ftest%2Fimg_8.png) + +## Ссылка на видео: +https://youtu.be/oPLQxyRDlXw \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/Dockerfile b/shadaev_anton_lab_3/aggregator-api/Dockerfile new file mode 100644 index 0000000..3cf37cb --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk-slim + +EXPOSE 8080 + +WORKDIR /app + +COPY aggregator-api-1.0-SNAPSHOT.jar /app + +CMD ["java", "-jar", "/app/aggregator-api-1.0-SNAPSHOT.jar"] \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/aggregator-api-1.0-SNAPSHOT.jar b/shadaev_anton_lab_3/aggregator-api/aggregator-api-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..b1633e2 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/aggregator-api-1.0-SNAPSHOT.jar differ diff --git a/shadaev_anton_lab_3/aggregator-api/pom.xml b/shadaev_anton_lab_3/aggregator-api/pom.xml new file mode 100644 index 0000000..2dc83fe --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.company + shadaev_anton_lab_3 + 1.0-SNAPSHOT + + + aggregator-api + + + 17 + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-devtools + + + org.postgresql + postgresql + 42.3.1 + + + org.projectlombok + lombok + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/AggregatorApiApplication.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/AggregatorApiApplication.java new file mode 100644 index 0000000..b4317dd --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/AggregatorApiApplication.java @@ -0,0 +1,11 @@ +package com.company; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AggregatorApiApplication { + public static void main(String[] args) { + SpringApplication.run(AggregatorApiApplication.class, args); + } +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/controller/JobController.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/controller/JobController.java new file mode 100644 index 0000000..f8b9598 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/controller/JobController.java @@ -0,0 +1,77 @@ +package com.company.controller; + +import com.company.dto.JobDto; +import com.company.exceptions.JobAlreadyExistsException; +import com.company.exceptions.JobNotFoundException; +import com.company.model.Job; +import com.company.service.JobService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/jobs") +public class JobController { + private final JobService jobService; + + @Autowired + public JobController(JobService jobService) { + this.jobService = jobService; + } + + @PostMapping + public ResponseEntity save(@RequestBody JobDto jobDto) { + Job job; + try { + if (jobService.findJobByTitle(jobDto.getTitle()).isPresent()) + throw new JobAlreadyExistsException("Job already exists!"); + job = jobService.save(jobDto); + return ResponseEntity.status(HttpStatus.CREATED).body(job); + } catch (JobAlreadyExistsException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + + @GetMapping + public List findAll() { + return jobService.findAll(); + } + + @GetMapping("/{uuid}") + public ResponseEntity findJobByUUID(@PathVariable UUID uuid) { + return jobService.findJobByUUID(uuid) + .map(app -> ResponseEntity.ok().body(app)) + .orElse(ResponseEntity.notFound().build()); + } + + @PutMapping("/{uuid}") + public ResponseEntity updateJobByUUID(@PathVariable UUID uuid, @RequestBody JobDto jobDto) { + Job job; + try { + if (jobService.findJobByUUID(uuid).isEmpty()) + throw new JobNotFoundException("Job not found!"); + job = jobService.updateJobByUUID(uuid, jobDto); + return ResponseEntity.ok().body(job); + } catch (JobNotFoundException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + + @DeleteMapping("/{uuid}") + public ResponseEntity deleteJobByUUID(@PathVariable UUID uuid) { + UUID statusId; + try { + if (!jobService.findJobByUUID(uuid).isPresent()) + throw new JobNotFoundException("Job not found!"); + statusId = jobService.deleteJobByUUID(uuid); + return ResponseEntity.ok().body(statusId); + } catch (JobNotFoundException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/dto/JobDto.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/dto/JobDto.java new file mode 100644 index 0000000..4840aea --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/dto/JobDto.java @@ -0,0 +1,19 @@ +package com.company.dto; + +import com.company.model.Job; +import lombok.Getter; + +public record JobDto(@Getter String title, @Getter String description) { + + public JobDto(String title, String description) { + this.title = title; + this.description = description; + } + + public static Job toJob(JobDto jobDto) { + return Job.builder() + .title(jobDto.getTitle()) + .description(jobDto.getDescription()) + .build(); + } +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobAlreadyExistsException.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobAlreadyExistsException.java new file mode 100644 index 0000000..6b82337 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobAlreadyExistsException.java @@ -0,0 +1,10 @@ +package com.company.exceptions; + +public class JobAlreadyExistsException extends Exception { + public JobAlreadyExistsException() { + } + + public JobAlreadyExistsException(String message) { + super(message); + } +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobNotFoundException.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobNotFoundException.java new file mode 100644 index 0000000..0bfdf21 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/exceptions/JobNotFoundException.java @@ -0,0 +1,10 @@ +package com.company.exceptions; + +public class JobNotFoundException extends Exception { + public JobNotFoundException() { + } + + public JobNotFoundException(String message) { + super(message); + } +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/model/Job.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/model/Job.java new file mode 100644 index 0000000..0032f7c --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/model/Job.java @@ -0,0 +1,21 @@ +package com.company.model; + +import lombok.*; + +import javax.persistence.*; +import java.util.UUID; + +@Entity +@Table(name = "jobs") +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Builder +public class Job { + @Id + @GeneratedValue + private UUID id; + private String title; + private String description; +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/repo/JobRepository.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/repo/JobRepository.java new file mode 100644 index 0000000..4eba8b1 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/repo/JobRepository.java @@ -0,0 +1,13 @@ +package com.company.repo; + +import com.company.model.Job; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface JobRepository extends JpaRepository { + Optional findJobByTitle(String title); +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/JobService.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/JobService.java new file mode 100644 index 0000000..cfeffeb --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/JobService.java @@ -0,0 +1,17 @@ +package com.company.service; + +import com.company.dto.JobDto; +import com.company.model.Job; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface JobService { + Job save(JobDto job); + List findAll(); + Optional findJobByUUID(UUID uuid); + Optional findJobByTitle(String title); + Job updateJobByUUID(UUID uuid, JobDto jobDto); + UUID deleteJobByUUID(UUID uuid); +} diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/impl/JobService.java b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/impl/JobService.java new file mode 100644 index 0000000..75553a4 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/java/com/company/service/impl/JobService.java @@ -0,0 +1,62 @@ +package com.company.service.impl; + +import com.company.dto.JobDto; +import com.company.model.Job; +import com.company.repo.JobRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Service +public class JobService implements com.company.service.JobService { + private final JobRepository jobRepository; + + @Autowired + public JobService(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + @Override + @Transactional + public Job save(JobDto jobDto) { + return jobRepository.save(JobDto.toJob(jobDto)); + } + + @Override + @Transactional + public List findAll(){ + return jobRepository.findAll(); + } + + @Override + @Transactional + public Optional findJobByUUID(UUID uuid) { + return Optional.ofNullable(jobRepository.findById(uuid).get()); + } + + @Override + @Transactional + public Optional findJobByTitle(String title) { + return Optional.ofNullable(jobRepository.findJobByTitle(title)).get(); + } + + @Override + @Transactional + public Job updateJobByUUID(UUID uuid, JobDto jobDto) { + Job job = jobRepository.findById(uuid).get(); + job.setTitle(jobDto.getTitle()); + job.setDescription(jobDto.getDescription()); + return jobRepository.save(job); + } + + @Override + @Transactional + public UUID deleteJobByUUID(UUID uuid) { + jobRepository.deleteById(uuid); + return uuid; + } +} \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/resources/application.yaml b/shadaev_anton_lab_3/aggregator-api/src/main/resources/application.yaml new file mode 100644 index 0000000..1161207 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/resources/application.yaml @@ -0,0 +1,13 @@ +server: + port: 8080 + +spring: + jpa: + hibernate: + ddl-auto: update + show-sql: true + datasource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:5433/aggregator_db + username: postgres + password: postgres \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/src/main/resources/templates/test.html b/shadaev_anton_lab_3/aggregator-api/src/main/resources/templates/test.html new file mode 100644 index 0000000..5957de6 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/src/main/resources/templates/test.html @@ -0,0 +1,13 @@ + + + + + + + test + + + test... + + \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar b/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..b1633e2 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar.original b/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar.original new file mode 100644 index 0000000..0503279 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/aggregator-api-1.0-SNAPSHOT.jar.original differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/application.yaml b/shadaev_anton_lab_3/aggregator-api/target/classes/application.yaml new file mode 100644 index 0000000..1161207 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/target/classes/application.yaml @@ -0,0 +1,13 @@ +server: + port: 8080 + +spring: + jpa: + hibernate: + ddl-auto: update + show-sql: true + datasource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:5433/aggregator_db + username: postgres + password: postgres \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/AggregatorApiApplication.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/AggregatorApiApplication.class new file mode 100644 index 0000000..9855bdd Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/AggregatorApiApplication.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/controller/JobController.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/controller/JobController.class new file mode 100644 index 0000000..8110034 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/controller/JobController.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/dto/JobDto.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/dto/JobDto.class new file mode 100644 index 0000000..dd565b8 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/dto/JobDto.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobAlreadyExistsException.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobAlreadyExistsException.class new file mode 100644 index 0000000..ce4aa1b Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobAlreadyExistsException.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobNotFoundException.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobNotFoundException.class new file mode 100644 index 0000000..cb98d45 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/exceptions/JobNotFoundException.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/model/Job.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/model/Job.class new file mode 100644 index 0000000..d7ed5b9 Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/model/Job.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/repo/JobRepository.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/repo/JobRepository.class new file mode 100644 index 0000000..9e5847c Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/repo/JobRepository.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/JobService.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/JobService.class new file mode 100644 index 0000000..b3289ca Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/JobService.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/impl/JobService.class b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/impl/JobService.class new file mode 100644 index 0000000..5b3fe0e Binary files /dev/null and b/shadaev_anton_lab_3/aggregator-api/target/classes/com/company/service/impl/JobService.class differ diff --git a/shadaev_anton_lab_3/aggregator-api/target/classes/templates/test.html b/shadaev_anton_lab_3/aggregator-api/target/classes/templates/test.html new file mode 100644 index 0000000..5957de6 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/target/classes/templates/test.html @@ -0,0 +1,13 @@ + + + + + + + test + + + test... + + \ No newline at end of file diff --git a/shadaev_anton_lab_3/aggregator-api/target/maven-archiver/pom.properties b/shadaev_anton_lab_3/aggregator-api/target/maven-archiver/pom.properties new file mode 100644 index 0000000..097b875 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/target/maven-archiver/pom.properties @@ -0,0 +1,3 @@ +artifactId=aggregator-api +groupId=com.company +version=1.0-SNAPSHOT diff --git a/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..f87c14a --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,10 @@ +com/company/controller/JobController.class +com/company/service/JobService.class +com/company/model/Job$JobBuilder.class +com/company/exceptions/JobAlreadyExistsException.class +com/company/exceptions/JobNotFoundException.class +com/company/repo/JobRepository.class +com/company/dto/JobDto.class +com/company/service/impl/JobService.class +com/company/model/Job.class +com/company/AggregatorApiApplication.class diff --git a/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..26bdb32 --- /dev/null +++ b/shadaev_anton_lab_3/aggregator-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,9 @@ +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/dto/JobDto.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/model/Job.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/service/JobService.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/exceptions/JobNotFoundException.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/exceptions/JobAlreadyExistsException.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/repo/JobRepository.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/service/impl/JobService.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/AggregatorApiApplication.java +/Users/a-shdv/IdeaProjects/aggregator/aggregator-api/src/main/java/com/company/controller/JobController.java diff --git a/shadaev_anton_lab_3/docker-compose.yaml b/shadaev_anton_lab_3/docker-compose.yaml new file mode 100644 index 0000000..d82d8ef --- /dev/null +++ b/shadaev_anton_lab_3/docker-compose.yaml @@ -0,0 +1,74 @@ +version: '3.8' +services: + aggregator-api-service: +# image: kybernetique/aggregator-api:latest + build: + context: ./aggregator-api + dockerfile: Dockerfile + ports: + - "8081:8080" + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-service/aggregator_db + - SPRING_DATASOURCE_USERNAME=postgres + - SPRING_DATASOURCE_PASSWORD=postgres + - SPRING_JPA_HIBERNATE_DDL_AUTO=create-drop + depends_on: + - postgres-service + networks: + backend: + aliases: + - "aggregator" + + + parser-api-service: +# image: kybernetique/parser-api:latest + build: + context: ./parser-api + dockerfile: Dockerfile + ports: + - "8082:8081" + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-service/aggregator_db + - SPRING_DATASOURCE_USERNAME=postgres + - SPRING_DATASOURCE_PASSWORD=postgres + - SPRING_JPA_HIBERNATE_DDL_AUTO=create-drop + depends_on: + - postgres-service + networks: + backend: + aliases: + - "parser" + + postgres-service: + image: postgres:14.1 + container_name: postgres-db + restart: always + ports: + - "5433:5432" + environment: + POSTGRES_DB: "aggregator_db" + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "postgres" + networks: + backend: + aliases: + - "postgres" + + nginx-service: + image: nginx:latest + ports: + - "81:80" + networks: + backend: + aliases: + - "nginx" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - aggregator-api-service + - parser-api-service + - postgres-service + +networks: + backend: + driver: bridge \ No newline at end of file diff --git a/shadaev_anton_lab_3/nginx.conf b/shadaev_anton_lab_3/nginx.conf new file mode 100644 index 0000000..3d9dfdb --- /dev/null +++ b/shadaev_anton_lab_3/nginx.conf @@ -0,0 +1,19 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 80; + listen [::]:80; + server_name localhost; + + location /aggregator-api/ { + proxy_pass http://aggregator-api-service:8080/; + } + + location /parser-api/ { + proxy_pass http://parser-api-service:8081/; + } + } +} diff --git a/shadaev_anton_lab_3/parser-api/Dockerfile b/shadaev_anton_lab_3/parser-api/Dockerfile new file mode 100644 index 0000000..c58ab26 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk-slim + +EXPOSE 8080 + +WORKDIR /app + +COPY parser-api-1.0-SNAPSHOT.jar /app + +CMD ["java", "-jar", "/app/parser-api-1.0-SNAPSHOT.jar"] \ No newline at end of file diff --git a/shadaev_anton_lab_3/parser-api/parser-api-1.0-SNAPSHOT.jar b/shadaev_anton_lab_3/parser-api/parser-api-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..483ff13 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/parser-api-1.0-SNAPSHOT.jar differ diff --git a/shadaev_anton_lab_3/parser-api/pom.xml b/shadaev_anton_lab_3/parser-api/pom.xml new file mode 100644 index 0000000..2a2905f --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.company + shadaev_anton_lab_3 + 1.0-SNAPSHOT + + + parser-api + + + 17 + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-devtools + + + org.postgresql + postgresql + 42.3.1 + + + org.projectlombok + lombok + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/ParserApiApplication.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/ParserApiApplication.java new file mode 100644 index 0000000..c23febc --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/ParserApiApplication.java @@ -0,0 +1,18 @@ +package com.company; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +public class ParserApiApplication { + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + public static void main(String[] args) { + SpringApplication.run(ParserApiApplication.class, args); + } +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/controller/PageController.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/controller/PageController.java new file mode 100644 index 0000000..f0a5631 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/controller/PageController.java @@ -0,0 +1,75 @@ +package com.company.controller; + +import com.company.dto.PageDto; +import com.company.exception.PageNotFoundException; +import com.company.model.Page; +import com.company.service.PageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/pages") +public class PageController { + private final PageService pageService; + + @Autowired + public PageController(PageService pageService) { + this.pageService = pageService; + } + + @PostMapping + public ResponseEntity save(@RequestBody PageDto pageDto) { + Page page; + page = pageService.save(pageDto); + return ResponseEntity.status(HttpStatus.CREATED).body(page); + } + + @GetMapping + public List findAll() { + return pageService.findAll(); + } + + @GetMapping("/{uuid}") + public ResponseEntity findPageByUUID(@PathVariable UUID uuid) { + return pageService.findPageByUUID(uuid) + .map(app -> ResponseEntity.ok().body(app)) + .orElse(ResponseEntity.notFound().build()); + } + + @PutMapping("/{uuid}") + public ResponseEntity updatePageByUUID(@PathVariable UUID uuid, @RequestBody PageDto pageDto) { + Page page; + try { + if (pageService.findPageByUUID(uuid).isEmpty()) + throw new PageNotFoundException("Page not found!"); + page = pageService.updatePageByUUID(uuid, pageDto); + return ResponseEntity.ok().body(page); + } catch (PageNotFoundException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + + @DeleteMapping("/{uuid}") + public ResponseEntity deletePageByUUID(@PathVariable UUID uuid) { + UUID statusId; + try { + if (!pageService.findPageByUUID(uuid).isPresent()) + throw new PageNotFoundException("Page not found!"); + statusId = pageService.deletePageByUUID(uuid); + return ResponseEntity.ok().body(statusId); + } catch (PageNotFoundException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + + @GetMapping("/find-job-info/{uuid}") + public ResponseEntity findJobInfo(@PathVariable UUID uuid) { + return ResponseEntity.ok().body(pageService.findJobInfo(uuid)); + } + +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/JobInfoDto.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/JobInfoDto.java new file mode 100644 index 0000000..f2e46f8 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/JobInfoDto.java @@ -0,0 +1,10 @@ +package com.company.dto; + +import lombok.Getter; + +public record JobInfoDto(@Getter String title, @Getter String description) { + public JobInfoDto(String title, String description) { + this.title = title; + this.description = description; + } +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/PageDto.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/PageDto.java new file mode 100644 index 0000000..e680945 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/dto/PageDto.java @@ -0,0 +1,16 @@ +package com.company.dto; + +import com.company.model.Page; +import lombok.Getter; + +public record PageDto(@Getter String jobUrl) { + public PageDto(String jobUrl) { + this.jobUrl = jobUrl; + } + + public static Page toPage(PageDto pageDto) { + return Page.builder() + .jobUrl(pageDto.getJobUrl()) + .build(); + } +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/exception/PageNotFoundException.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/exception/PageNotFoundException.java new file mode 100644 index 0000000..c433aae --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/exception/PageNotFoundException.java @@ -0,0 +1,10 @@ +package com.company.exception; + +public class PageNotFoundException extends Exception { + public PageNotFoundException() { + } + + public PageNotFoundException(String message) { + super(message); + } +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/model/Page.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/model/Page.java new file mode 100644 index 0000000..df1d19f --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/model/Page.java @@ -0,0 +1,23 @@ +package com.company.model; + +import lombok.*; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name = "pages") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Page { + @Id + @GeneratedValue + private UUID id; + private String jobUrl; +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/repo/PageRepository.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/repo/PageRepository.java new file mode 100644 index 0000000..6f1293c --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/repo/PageRepository.java @@ -0,0 +1,9 @@ +package com.company.repo; + +import com.company.model.Page; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface PageRepository extends JpaRepository { +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/PageService.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/PageService.java new file mode 100644 index 0000000..49db48c --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/PageService.java @@ -0,0 +1,18 @@ +package com.company.service; + +import com.company.dto.JobInfoDto; +import com.company.dto.PageDto; +import com.company.model.Page; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface PageService { + Page save(PageDto pageDto); + List findAll(); + Optional findPageByUUID(UUID uuid); + JobInfoDto findJobInfo(UUID jobUUID); + Page updatePageByUUID(UUID uuid, PageDto pageDto); + UUID deletePageByUUID(UUID uuid); +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/impl/PageService.java b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/impl/PageService.java new file mode 100644 index 0000000..7b4ff25 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/java/com/company/service/impl/PageService.java @@ -0,0 +1,66 @@ +package com.company.service.impl; + +import com.company.dto.JobInfoDto; +import com.company.dto.PageDto; +import com.company.model.Page; +import com.company.repo.PageRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Service +public class PageService implements com.company.service.PageService { + private final PageRepository pageRepository; + private final RestTemplate restTemplate; + + @Autowired + public PageService(PageRepository pageRepository, RestTemplate restTemplate) { + this.pageRepository = pageRepository; + this.restTemplate = restTemplate; + } + + @Override + @Transactional + public Page save(PageDto pageDto) { + return pageRepository.save(PageDto.toPage(pageDto)); + } + + @Override + @Transactional + public List findAll() { + return pageRepository.findAll(); + } + + @Override + @Transactional + public Optional findPageByUUID(UUID uuid) { + return Optional.ofNullable(pageRepository.findById(uuid).get()); + } + + @Override + @Transactional + public Page updatePageByUUID(UUID uuid, PageDto pageDto) { + Page page = pageRepository.findById(uuid).get(); + page.setJobUrl(pageDto.getJobUrl()); + return pageRepository.save(page); + } + + @Override + @Transactional + public UUID deletePageByUUID(UUID uuid) { + pageRepository.deleteById(uuid); + return uuid; + } + + @Override + @Transactional + public JobInfoDto findJobInfo(UUID jobUUID) { + String jobInfoUrl = "http://nginx/aggregator-api/jobs/" + jobUUID; + return restTemplate.getForObject(jobInfoUrl, JobInfoDto.class); + } +} diff --git a/shadaev_anton_lab_3/parser-api/src/main/resources/application.yaml b/shadaev_anton_lab_3/parser-api/src/main/resources/application.yaml new file mode 100644 index 0000000..de7fe9f --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/src/main/resources/application.yaml @@ -0,0 +1,13 @@ +server: + port: 8081 + +spring: + jpa: + hibernate: + ddl-auto: update + show-sql: true + datasource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:5433/aggregator_db + username: postgres + password: postgres \ No newline at end of file diff --git a/shadaev_anton_lab_3/parser-api/target/classes/application.yaml b/shadaev_anton_lab_3/parser-api/target/classes/application.yaml new file mode 100644 index 0000000..de7fe9f --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/target/classes/application.yaml @@ -0,0 +1,13 @@ +server: + port: 8081 + +spring: + jpa: + hibernate: + ddl-auto: update + show-sql: true + datasource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:5433/aggregator_db + username: postgres + password: postgres \ No newline at end of file diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/ParserApiApplication.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/ParserApiApplication.class new file mode 100644 index 0000000..dd56447 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/ParserApiApplication.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/controller/PageController.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/controller/PageController.class new file mode 100644 index 0000000..a26ed0e Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/controller/PageController.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/JobInfoDto.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/JobInfoDto.class new file mode 100644 index 0000000..d1a5921 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/JobInfoDto.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/PageDto.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/PageDto.class new file mode 100644 index 0000000..bfaeb26 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/dto/PageDto.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/exception/PageNotFoundException.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/exception/PageNotFoundException.class new file mode 100644 index 0000000..5587f87 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/exception/PageNotFoundException.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/model/Page.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/model/Page.class new file mode 100644 index 0000000..765f591 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/model/Page.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/repo/PageRepository.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/repo/PageRepository.class new file mode 100644 index 0000000..99179c5 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/repo/PageRepository.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/PageService.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/PageService.class new file mode 100644 index 0000000..056dc0e Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/PageService.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/impl/PageService.class b/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/impl/PageService.class new file mode 100644 index 0000000..2c71734 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/classes/com/company/service/impl/PageService.class differ diff --git a/shadaev_anton_lab_3/parser-api/target/maven-archiver/pom.properties b/shadaev_anton_lab_3/parser-api/target/maven-archiver/pom.properties new file mode 100644 index 0000000..068d8b5 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/target/maven-archiver/pom.properties @@ -0,0 +1,3 @@ +artifactId=parser-api +groupId=com.company +version=1.0-SNAPSHOT diff --git a/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..d4d1849 --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,10 @@ +com/company/service/impl/PageService.class +com/company/dto/PageDto.class +com/company/model/Page.class +com/company/service/PageService.class +com/company/repo/PageRepository.class +com/company/model/Page$PageBuilder.class +com/company/dto/JobInfoDto.class +com/company/controller/PageController.class +com/company/ParserApiApplication.class +com/company/exception/PageNotFoundException.class diff --git a/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..8b3205e --- /dev/null +++ b/shadaev_anton_lab_3/parser-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,9 @@ +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/ParserApiApplication.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/controller/PageController.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/model/Page.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/service/PageService.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/exception/PageNotFoundException.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/service/impl/PageService.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/dto/PageDto.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/dto/JobInfoDto.java +/Users/a-shdv/IdeaProjects/aggregator/parser-api/src/main/java/com/company/repo/PageRepository.java diff --git a/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar b/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..483ff13 Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar differ diff --git a/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar.original b/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar.original new file mode 100644 index 0000000..3091ccb Binary files /dev/null and b/shadaev_anton_lab_3/parser-api/target/parser-api-1.0-SNAPSHOT.jar.original differ diff --git a/shadaev_anton_lab_3/pom.xml b/shadaev_anton_lab_3/pom.xml new file mode 100644 index 0000000..2e01764 --- /dev/null +++ b/shadaev_anton_lab_3/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.5 + + + + com.company + shadaev_anton_lab_3 + 1.0-SNAPSHOT + pom + + aggregator-api + parser-api + + + + 17 + 17 + UTF-8 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/shadaev_anton_lab_3/screenshots/1.png b/shadaev_anton_lab_3/screenshots/1.png new file mode 100644 index 0000000..c5db99d Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/1.png differ diff --git a/shadaev_anton_lab_3/screenshots/2.png b/shadaev_anton_lab_3/screenshots/2.png new file mode 100644 index 0000000..4d0b68c Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/2.png differ diff --git a/shadaev_anton_lab_3/screenshots/3.png b/shadaev_anton_lab_3/screenshots/3.png new file mode 100644 index 0000000..b845a81 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/3.png differ diff --git a/shadaev_anton_lab_3/screenshots/4.png b/shadaev_anton_lab_3/screenshots/4.png new file mode 100644 index 0000000..aedec70 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/4.png differ diff --git a/shadaev_anton_lab_3/screenshots/5.png b/shadaev_anton_lab_3/screenshots/5.png new file mode 100644 index 0000000..ae2fdd2 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/5.png differ diff --git a/shadaev_anton_lab_3/screenshots/img.png b/shadaev_anton_lab_3/screenshots/img.png new file mode 100644 index 0000000..3cbbc5c Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_1.png b/shadaev_anton_lab_3/screenshots/img_1.png new file mode 100644 index 0000000..5a84663 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_1.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_10.png b/shadaev_anton_lab_3/screenshots/img_10.png new file mode 100644 index 0000000..868a35e Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_10.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_11.png b/shadaev_anton_lab_3/screenshots/img_11.png new file mode 100644 index 0000000..9f833b3 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_11.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_12.png b/shadaev_anton_lab_3/screenshots/img_12.png new file mode 100644 index 0000000..d209250 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_12.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_2.png b/shadaev_anton_lab_3/screenshots/img_2.png new file mode 100644 index 0000000..7426573 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_2.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_3.png b/shadaev_anton_lab_3/screenshots/img_3.png new file mode 100644 index 0000000..7a697f9 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_3.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_4.png b/shadaev_anton_lab_3/screenshots/img_4.png new file mode 100644 index 0000000..931d394 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_4.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_5.png b/shadaev_anton_lab_3/screenshots/img_5.png new file mode 100644 index 0000000..05a8d52 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_5.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_6.png b/shadaev_anton_lab_3/screenshots/img_6.png new file mode 100644 index 0000000..ebd7e85 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_6.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_7.png b/shadaev_anton_lab_3/screenshots/img_7.png new file mode 100644 index 0000000..cb94e23 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_7.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_8.png b/shadaev_anton_lab_3/screenshots/img_8.png new file mode 100644 index 0000000..b3c1cd0 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_8.png differ diff --git a/shadaev_anton_lab_3/screenshots/img_9.png b/shadaev_anton_lab_3/screenshots/img_9.png new file mode 100644 index 0000000..868a35e Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/img_9.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img.png b/shadaev_anton_lab_3/screenshots/test/img.png new file mode 100644 index 0000000..3cbbc5c Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_1.png b/shadaev_anton_lab_3/screenshots/test/img_1.png new file mode 100644 index 0000000..5a84663 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_1.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_2.png b/shadaev_anton_lab_3/screenshots/test/img_2.png new file mode 100644 index 0000000..7426573 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_2.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_3.png b/shadaev_anton_lab_3/screenshots/test/img_3.png new file mode 100644 index 0000000..7a697f9 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_3.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_4.png b/shadaev_anton_lab_3/screenshots/test/img_4.png new file mode 100644 index 0000000..931d394 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_4.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_5.png b/shadaev_anton_lab_3/screenshots/test/img_5.png new file mode 100644 index 0000000..05a8d52 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_5.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_6.png b/shadaev_anton_lab_3/screenshots/test/img_6.png new file mode 100644 index 0000000..ebd7e85 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_6.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_7.png b/shadaev_anton_lab_3/screenshots/test/img_7.png new file mode 100644 index 0000000..cb94e23 Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_7.png differ diff --git a/shadaev_anton_lab_3/screenshots/test/img_8.png b/shadaev_anton_lab_3/screenshots/test/img_8.png new file mode 100644 index 0000000..07eea7e Binary files /dev/null and b/shadaev_anton_lab_3/screenshots/test/img_8.png differ