diff --git a/kamyshov_danila_lab_3/README.md b/kamyshov_danila_lab_3/README.md new file mode 100644 index 0000000..ab22ba9 --- /dev/null +++ b/kamyshov_danila_lab_3/README.md @@ -0,0 +1,154 @@ +# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами + +Цель: изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API. + +Задачи: + +Создать 2 микросервиса, реализующих CRUD на связанных сущностях. +Реализовать механизм синхронного обмена сообщениями между микросервисами. +Реализовать шлюз на основе прозрачного прокси-сервера nginx. + +# Создание микросервисов +Первый микросервис - messaging-application для сущности "Приложение для обмена сообщениями" +Второй микросервис - user-device-application для сущности "Устройство пользователя" + +Сущность: Устройство пользователя (User Device): +UUID (Уникальный идентификатор): Уникальный номер или код, идентифицирующий конкретное устройство пользователя. +Модель (Model): Название и модель устройства пользователя. +Тип интерфейса (Interface Type): Тип интерфейса для подключения к веб-приложению (Web, Mobile, Desktop и т.д.). +UUID приложения для обмена сообщениями (messagingAppUuid): Уникальный идентификатор приложения для обмена сообщениями, с которым данное устройство пользователя связано. Это поле устанавливает связь "1-ко-многим" между устройством и приложением. + +Сущность: Приложение для обмена сообщениями (Messaging Application): +UUID (Уникальный идентификатор): Уникальный номер или код, идентифицирующий конкретное приложение для обмена сообщениями. +Название (Name): Название приложения для обмена сообщениями. +Поддерживаемые платформы (Supported Platforms): Операционные системы и устройства, на которых работает приложение (Web, Mobile, Desktop и др.). +Максимальное количество участников (Maximum Participants): Максимальное количество пользователей, которое может использовать приложение для обмена сообщениями одновременно. + +Связь "1-ко-многим" между этими сущностями реализуется через поле "UUID приложения" в сущности "Устройство пользователя". Каждое устройство пользователя связано с конкретным приложением для обмена сообщениями через UUID этого приложения, что позволяет одному приложению быть связанным с несколькими устройствами. + +Вот примеры моделей для запросов: +Пример модели "Приложение для обмена сообщениями" для списка: +{ + "uuid": "8f036445-a5bd-401c-926e-840f9de795cd", + "Name": "Messenger", + "Supported Platforms": "Web, iOS, Android", + "Maximum Participants": 100 +} +Пример модели "Приложение для обмена сообщениями" для создания или изменения: +{ + "uuid": "8f036445-a5bd-401c-926e-840f9de795cd", + "Name": "Messenger", + "Supported Platforms": "Web, iOS, Android", + "Maximum Participants": 100 +} +Пример модели "Устройство пользователя" для списка: +{ + "uuid": "8740d660-b251-4272-8535-be7ec3748d4b", + "Model": "iPhone X", + "type": "Mobile", + "Interface Type": "ios", + "messagingAppUuid": "8f036445-a5bd-401c-926e-840f9de795cd" +} + +Пример модели "Устройство пользователя" для создания или изменения: +{ + "Model": "iPhone X", + "type": "Mobile", + "Interface Type": "ios", + "messagingAppUuid": "8f036445-a5bd-401c-926e-840f9de795cd" +} +Пример модели "Устройство пользователя" для подробностей: +{ + "uuid": "8740d660-b251-4272-8535-be7ec3748d4b", + "Model": "iPhone X", + "type": "Mobile", + "Interface Type": "ios", + "messagingAppUuid": "8f036445-a5bd-401c-926e-840f9de795cd", + "messagingAppInfo": { + "Name": "Messenger", + "Supported Platforms": "Web, iOS, Android", + "Maximum Participants": 100 + } +} + +

+

Структура 1-го микросервиса
+ +

+

+

Структура 2-го микросервиса
+ +

+- контроллеры для обработка запросов, дтошки для выбора что изображать в сваггере при запросах, модели для сущностей, репозитории для отправки данных, сервисы для бизнес-логики + +# Докер файлы, докер компоус, nginx + +

+

Докер файл для 1-го микросервиса
+ +

+

+

Докер файл для 2-го микросервиса
+ +

+-Использования базового образа, установка рабочий директории, копирования джар файла, экспорт порта, запуск приложения при запуске контейнера +

+

Докер компоус
+ +

+-создания общей сети для всех сервисов, запуск образов сервисов, проброска портов, копирования конфигурационного файла nginx и запуск этого сервиса после запуска других сервисов +

+

nginx
+ +

+установка количества одновремменных подключений, прослушка запросов по 80 порту, серверное имя локалхост, адрес для переадресации запросов по нему, url переадрусации +

+

Скрин созданых образов
+ +

+

+

Скрин созданых контейнеров
+ +

+

+

Swagger 1-го микросервиса
+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+

Swagger 2-го микросервиса
+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+ +# Видео + +Видео с разбором лабораторной работы - https://drive.google.com/file/d/1hOHcZAP8aECQXtKm1CcHNDtKli1TdJLO/view?usp=sharing diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/Dockerfile b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/Dockerfile new file mode 100644 index 0000000..1fdbff9 --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/Dockerfile @@ -0,0 +1,14 @@ +# Используем базовый образ с Java и средой выполнения Spring Boot +FROM openjdk:17-jdk-slim + +# Устанавливаем рабочий каталог внутри контейнера +WORKDIR /app + +# Копируем JAR-файл приложения в контейнер (предполагается, что JAR-файл находится в каталоге target/) +COPY target/messaging-application-0.0.1-SNAPSHOT.jar messaging-application.jar + +# Экспонируем порт, на котором будет работать приложение +EXPOSE 8099 + +# Запускаем приложение при запуске контейнера +CMD ["java", "-jar", "messaging-application.jar"] diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/MessagingApplication.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/MessagingApplication.java new file mode 100644 index 0000000..8be583a --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/MessagingApplication.java @@ -0,0 +1,11 @@ +package com.example.messagingapplication; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MessagingApplication { + public static void main(String[] args) { + SpringApplication.run(MessagingApplication.class, args); + } +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/controller/MessagingApplicationController.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/controller/MessagingApplicationController.java new file mode 100644 index 0000000..22b3dac --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/controller/MessagingApplicationController.java @@ -0,0 +1,56 @@ +package com.example.messagingapplication.controller; + +import com.example.messagingapplication.model.MessagingApplication; +import com.example.messagingapplication.dto.MessagingApplicationDTO; +import com.example.messagingapplication.service.MessagingApplicationService; +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; + +@RestController +@RequestMapping("/messaging-application") +public class MessagingApplicationController { + private final MessagingApplicationService applicationService; + + @Autowired + public MessagingApplicationController(MessagingApplicationService applicationService) { + this.applicationService = applicationService; + } + + @GetMapping("/") + public List getAllApplications() { + return applicationService.getAllApplications(); + } + + @GetMapping("/{uuid}") + public ResponseEntity getApplicationByUuid(@PathVariable String uuid) { + return applicationService.getApplicationByUuid(uuid) + .map(app -> ResponseEntity.ok().body(app)) + .orElse(ResponseEntity.notFound().build()); + } + + @PostMapping("/") + public ResponseEntity createApplication(@RequestBody MessagingApplicationDTO applicationDTO) { + MessagingApplication createdApplication = applicationService.createApplication(applicationDTO); + return ResponseEntity.status(HttpStatus.CREATED).body(createdApplication); + } + + @PutMapping("/{uuid}") + public ResponseEntity updateApplication(@PathVariable String uuid, @RequestBody MessagingApplicationDTO applicationDTO) { + MessagingApplication updatedApplication = applicationService.updateApplication(uuid, applicationDTO); + if (updatedApplication != null) { + return ResponseEntity.ok().body(updatedApplication); + } else { + return ResponseEntity.notFound().build(); + } + } + + @DeleteMapping("/{uuid}") + public ResponseEntity deleteApplication(@PathVariable String uuid) { + boolean deleted = applicationService.deleteApplication(uuid); + return deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); + } +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/dto/MessagingApplicationDTO.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/dto/MessagingApplicationDTO.java new file mode 100644 index 0000000..0a539e9 --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/dto/MessagingApplicationDTO.java @@ -0,0 +1,14 @@ +package com.example.messagingapplication.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MessagingApplicationDTO { + private String name; + private String supportedPlatforms; + private int maximumParticipants; +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/model/MessagingApplication.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/model/MessagingApplication.java new file mode 100644 index 0000000..787ca2e --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/model/MessagingApplication.java @@ -0,0 +1,22 @@ +package com.example.messagingapplication.model; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "messaging_application") +@Data +public class MessagingApplication { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String uuid; + private String name; + private String supportedPlatforms; + private int maximumParticipants; +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/repository/MessagingApplicationRepository.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/repository/MessagingApplicationRepository.java new file mode 100644 index 0000000..6b769a5 --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/repository/MessagingApplicationRepository.java @@ -0,0 +1,12 @@ +package com.example.messagingapplication.repository; + +import com.example.messagingapplication.model.MessagingApplication; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MessagingApplicationRepository extends JpaRepository { + Optional findByUuid(String uuid); +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/service/MessagingApplicationService.java b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/service/MessagingApplicationService.java new file mode 100644 index 0000000..1f374a8 --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/java/com/example/messagingapplication/service/MessagingApplicationService.java @@ -0,0 +1,70 @@ +package com.example.messagingapplication.service; + +import com.example.messagingapplication.model.MessagingApplication; +import com.example.messagingapplication.dto.MessagingApplicationDTO; +import com.example.messagingapplication.repository.MessagingApplicationRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.Random; + +@Service +@RequiredArgsConstructor +public class MessagingApplicationService { + private final MessagingApplicationRepository applicationRepository; + + @Transactional + public List getAllApplications() { + return applicationRepository.findAll(); + } + + @Transactional + public Optional getApplicationByUuid(String uuid) { + return applicationRepository.findByUuid(uuid); + } + + @Transactional + public MessagingApplication createApplication(MessagingApplicationDTO applicationDTO) { + MessagingApplication application = new MessagingApplication(); + application.setUuid(createUUID()); + application.setName(applicationDTO.getName()); + application.setSupportedPlatforms(applicationDTO.getSupportedPlatforms()); + application.setMaximumParticipants(applicationDTO.getMaximumParticipants()); + return applicationRepository.save(application); + } + + @Transactional + public MessagingApplication updateApplication(String uuid, MessagingApplicationDTO applicationDTO) { + Optional existingApplication = applicationRepository.findByUuid(uuid); + if (existingApplication.isPresent()) { + MessagingApplication application = existingApplication.get(); + application.setName(applicationDTO.getName()); + application.setSupportedPlatforms(applicationDTO.getSupportedPlatforms()); + application.setMaximumParticipants(applicationDTO.getMaximumParticipants()); + return applicationRepository.save(application); + } + return null; + } + + @Transactional + public boolean deleteApplication(String uuid) { + Optional existingApplication = applicationRepository.findByUuid(uuid); + if (existingApplication.isPresent()) { + applicationRepository.delete(existingApplication.get()); + return true; + } + return false; + } + + private String createUUID() { + Random random = new Random(); + long mostSigBits = random.nextLong(); + long leastSigBits = random.nextLong(); + return String.format("%08x-%04x-%04x-%04x-%012x", + mostSigBits >>> 32, (mostSigBits >>> 16) & 0xFFFF, mostSigBits & 0xFFFF, + (leastSigBits >>> 16) & 0xFFFF, leastSigBits & 0xFFFF); + } +} diff --git a/kamyshov_danila_lab_3/messaging-application/src/main/resources/application.properties b/kamyshov_danila_lab_3/messaging-application/src/main/resources/application.properties new file mode 100644 index 0000000..e51fdaa --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.hibernate.ddl-auto=update +spring.h2.console.enabled=true + +server.port=8099 diff --git a/kamyshov_danila_lab_3/messaging-application/src/test/java/com/example/messagingapplication/MessagingApplicationApplicationTests.java b/kamyshov_danila_lab_3/messaging-application/src/test/java/com/example/messagingapplication/MessagingApplicationApplicationTests.java new file mode 100644 index 0000000..a079ec4 --- /dev/null +++ b/kamyshov_danila_lab_3/messaging-application/src/test/java/com/example/messagingapplication/MessagingApplicationApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.messagingapplication; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class MessagingApplicationApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/kamyshov_danila_lab_3/screens/img1.png b/kamyshov_danila_lab_3/screens/img1.png new file mode 100644 index 0000000..e5ddede Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img1.png differ diff --git a/kamyshov_danila_lab_3/screens/img10.png b/kamyshov_danila_lab_3/screens/img10.png new file mode 100644 index 0000000..48082b2 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img10.png differ diff --git a/kamyshov_danila_lab_3/screens/img11.png b/kamyshov_danila_lab_3/screens/img11.png new file mode 100644 index 0000000..15e83fb Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img11.png differ diff --git a/kamyshov_danila_lab_3/screens/img12.png b/kamyshov_danila_lab_3/screens/img12.png new file mode 100644 index 0000000..fcf2fc6 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img12.png differ diff --git a/kamyshov_danila_lab_3/screens/img13.png b/kamyshov_danila_lab_3/screens/img13.png new file mode 100644 index 0000000..665da82 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img13.png differ diff --git a/kamyshov_danila_lab_3/screens/img14.png b/kamyshov_danila_lab_3/screens/img14.png new file mode 100644 index 0000000..dff11c7 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img14.png differ diff --git a/kamyshov_danila_lab_3/screens/img15.png b/kamyshov_danila_lab_3/screens/img15.png new file mode 100644 index 0000000..acd624f Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img15.png differ diff --git a/kamyshov_danila_lab_3/screens/img16.png b/kamyshov_danila_lab_3/screens/img16.png new file mode 100644 index 0000000..4f5fe11 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img16.png differ diff --git a/kamyshov_danila_lab_3/screens/img17.png b/kamyshov_danila_lab_3/screens/img17.png new file mode 100644 index 0000000..186ace0 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img17.png differ diff --git a/kamyshov_danila_lab_3/screens/img18.png b/kamyshov_danila_lab_3/screens/img18.png new file mode 100644 index 0000000..83739db Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img18.png differ diff --git a/kamyshov_danila_lab_3/screens/img19.png b/kamyshov_danila_lab_3/screens/img19.png new file mode 100644 index 0000000..6c8270c Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img19.png differ diff --git a/kamyshov_danila_lab_3/screens/img2.png b/kamyshov_danila_lab_3/screens/img2.png new file mode 100644 index 0000000..118b972 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img2.png differ diff --git a/kamyshov_danila_lab_3/screens/img20.png b/kamyshov_danila_lab_3/screens/img20.png new file mode 100644 index 0000000..69c42bb Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img20.png differ diff --git a/kamyshov_danila_lab_3/screens/img3.png b/kamyshov_danila_lab_3/screens/img3.png new file mode 100644 index 0000000..ec10ad3 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img3.png differ diff --git a/kamyshov_danila_lab_3/screens/img4.png b/kamyshov_danila_lab_3/screens/img4.png new file mode 100644 index 0000000..c5b52f6 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img4.png differ diff --git a/kamyshov_danila_lab_3/screens/img5.png b/kamyshov_danila_lab_3/screens/img5.png new file mode 100644 index 0000000..b8298a3 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img5.png differ diff --git a/kamyshov_danila_lab_3/screens/img6.png b/kamyshov_danila_lab_3/screens/img6.png new file mode 100644 index 0000000..ec9bac9 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img6.png differ diff --git a/kamyshov_danila_lab_3/screens/img7.png b/kamyshov_danila_lab_3/screens/img7.png new file mode 100644 index 0000000..ab186aa Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img7.png differ diff --git a/kamyshov_danila_lab_3/screens/img8.png b/kamyshov_danila_lab_3/screens/img8.png new file mode 100644 index 0000000..6c150f8 Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img8.png differ diff --git a/kamyshov_danila_lab_3/screens/img9.png b/kamyshov_danila_lab_3/screens/img9.png new file mode 100644 index 0000000..0f2db9a Binary files /dev/null and b/kamyshov_danila_lab_3/screens/img9.png differ diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/Dockerfile b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/Dockerfile new file mode 100644 index 0000000..40a2e46 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/Dockerfile @@ -0,0 +1,14 @@ +# Используем базовый образ с Java и средой выполнения Spring Boot +FROM openjdk:17-jdk-slim + +# Устанавливаем рабочий каталог внутри контейнера +WORKDIR /app + +# Копируем JAR-файл приложения в контейнер (предполагается, что JAR-файл находится в каталоге target/) +COPY target/user-device-application-0.0.1-SNAPSHOT.jar user-device-application.jar + +# Экспонируем порт, на котором будет работать приложение +EXPOSE 8090 + +# Запускаем приложение при запуске контейнера +CMD ["java", "-jar", "user-device-application.jar"] diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/UserDeviceApplication.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/UserDeviceApplication.java new file mode 100644 index 0000000..42f96b2 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/UserDeviceApplication.java @@ -0,0 +1,18 @@ +package com.example.userdeviceapplication; + +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 UserDeviceApplication { + public static void main(String[] args) { + SpringApplication.run(UserDeviceApplication.class, args); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/controller/UserDeviceController.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/controller/UserDeviceController.java new file mode 100644 index 0000000..2c131c1 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/controller/UserDeviceController.java @@ -0,0 +1,61 @@ +package com.example.userdeviceapplication.controller; + +import com.example.userdeviceapplication.dto.UserDeviceCreateUpdateDTO; +import com.example.userdeviceapplication.dto.UserDeviceDTO; +import com.example.userdeviceapplication.dto.UserDeviceDetailDTO; +import com.example.userdeviceapplication.service.UserDeviceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/user-device-application") +public class UserDeviceController { + private final UserDeviceService userDeviceService; + + @Autowired + public UserDeviceController(UserDeviceService userDeviceService) { + this.userDeviceService = userDeviceService; + } + + @GetMapping("/") + public ResponseEntity> getUserDevices() { + List userDevices = userDeviceService.getAllUserDevices(); + return ResponseEntity.ok(userDevices); + } + + @GetMapping("/{uuid}") + public ResponseEntity getUserDevice(@PathVariable String uuid) { + UserDeviceDetailDTO userDevice = userDeviceService.getUserDeviceByUuid(uuid); + if (userDevice != null) { + return ResponseEntity.ok(userDevice); + } + return ResponseEntity.notFound().build(); + } + + @PostMapping("/") + public ResponseEntity createUserDevice(@RequestBody UserDeviceCreateUpdateDTO createDTO) { + UserDeviceDetailDTO userDevice = userDeviceService.createUserDevice(createDTO); + return ResponseEntity.ok(userDevice); + } + + @PutMapping("/{uuid}") + public ResponseEntity updateUserDevice(@PathVariable String uuid, @RequestBody UserDeviceCreateUpdateDTO updateDTO) { + UserDeviceDetailDTO userDevice = userDeviceService.updateUserDevice(uuid, updateDTO); + if (userDevice != null) { + return ResponseEntity.ok(userDevice); + } + return ResponseEntity.notFound().build(); + } + + @DeleteMapping("/{uuid}") + public ResponseEntity deleteUserDevice(@PathVariable String uuid) { + boolean deleted = userDeviceService.deleteUserDevice(uuid); + if (deleted) { + return ResponseEntity.ok().build(); + } + return ResponseEntity.notFound().build(); + } +} diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/docker-compose.yml b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/docker-compose.yml new file mode 100644 index 0000000..4b2ac6e --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3' +services: + messaging-application: + image: messagingapplication_microservice_1:1.0 + ports: + - "8099:8099" + networks: + - network + + user-device-application: + image: userdeviceapplication_microservice_2:1.0 + ports: + - "8090:8090" + networks: + - network + + nginx: + image: nginx:latest + ports: + - "80:80" + networks: + - network + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - messaging-application + - user-device-application + +networks: + network: + driver: bridge \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceCreateUpdateDTO.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceCreateUpdateDTO.java new file mode 100644 index 0000000..d232f28 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceCreateUpdateDTO.java @@ -0,0 +1,11 @@ +package com.example.userdeviceapplication.dto; + +import lombok.Data; + +@Data +public class UserDeviceCreateUpdateDTO { + private String model; + private String type; + private String interfaceType; + private String messagingAppUuid; +} \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDTO.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDTO.java new file mode 100644 index 0000000..aeca910 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDTO.java @@ -0,0 +1,12 @@ +package com.example.userdeviceapplication.dto; + +import lombok.Data; + +@Data +public class UserDeviceDTO { + private String uuid; + private String model; + private String type; + private String interfaceType; + private String messagingAppUuid; +} \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailDTO.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailDTO.java new file mode 100644 index 0000000..d014e77 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailDTO.java @@ -0,0 +1,13 @@ +package com.example.userdeviceapplication.dto; + +import lombok.Data; + +@Data +public class UserDeviceDetailDTO { + private String uuid; + private String model; + private String type; + private String interfaceType; + private String messagingAppUuid; + private UserDeviceDetailInfoDTO messagingAppInfo; +} \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailInfoDTO.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailInfoDTO.java new file mode 100644 index 0000000..030f9bb --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/dto/UserDeviceDetailInfoDTO.java @@ -0,0 +1,10 @@ +package com.example.userdeviceapplication.dto; + +import lombok.Data; + +@Data +public class UserDeviceDetailInfoDTO { + private String name; + private String supportedPlatforms; + private int maximumParticipants; +} \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/model/UserDevice.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/model/UserDevice.java new file mode 100644 index 0000000..3c1b632 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/model/UserDevice.java @@ -0,0 +1,21 @@ +package com.example.userdeviceapplication.model; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; + +@Entity +@Data +public class UserDevice { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String uuid; + private String model; + private String type; + private String interfaceType; + private String messagingAppUuid; +} diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/nginx.conf b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/nginx.conf new file mode 100644 index 0000000..6b04374 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/nginx.conf @@ -0,0 +1,19 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 80; + listen [::]:80; + server_name localhost; + + location /messaging-application/ { + proxy_pass http://messaging-application:8099; + } + + location /user-device-application/ { + proxy_pass http://user-device-application:8090; + } + } +} \ No newline at end of file diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/repository/UserDeviceRepository.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/repository/UserDeviceRepository.java new file mode 100644 index 0000000..6e32c4d --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/repository/UserDeviceRepository.java @@ -0,0 +1,10 @@ +package com.example.userdeviceapplication.repository; + +import com.example.userdeviceapplication.model.UserDevice; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserDeviceRepository extends JpaRepository { + UserDevice findByUuid(String uuid); +} diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/service/UserDeviceService.java b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/service/UserDeviceService.java new file mode 100644 index 0000000..c601825 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/java/com/example/userdeviceapplication/service/UserDeviceService.java @@ -0,0 +1,114 @@ +package com.example.userdeviceapplication.service; + +import com.example.userdeviceapplication.dto.UserDeviceCreateUpdateDTO; +import com.example.userdeviceapplication.dto.UserDeviceDTO; +import com.example.userdeviceapplication.dto.UserDeviceDetailDTO; +import com.example.userdeviceapplication.dto.UserDeviceDetailInfoDTO; +import com.example.userdeviceapplication.model.UserDevice; +import com.example.userdeviceapplication.repository.UserDeviceRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +@Service +public class UserDeviceService { + private final UserDeviceRepository userDeviceRepository; + private final RestTemplate restTemplate; + + @Autowired + public UserDeviceService(UserDeviceRepository userDeviceRepository, RestTemplate restTemplate) { + this.userDeviceRepository = userDeviceRepository; + this.restTemplate = restTemplate; + } + + public List getAllUserDevices() { + List userDevices = userDeviceRepository.findAll(); + return userDevices.stream() + .map(this::convertToUserDeviceDTO) + .collect(Collectors.toList()); + } + + public UserDeviceDetailDTO getUserDeviceByUuid(String uuid) { + UserDevice userDevice = userDeviceRepository.findByUuid(uuid); + if (userDevice != null) { + return convertToUserDeviceDetailDTO(userDevice); + } + return null; + } + + public UserDeviceDetailDTO createUserDevice(UserDeviceCreateUpdateDTO createDTO) { + UserDevice userDevice = new UserDevice(); + userDevice.setUuid(createUUID()); + updateUserDeviceFromDTO(userDevice, createDTO); + userDevice = userDeviceRepository.save(userDevice); + return convertToUserDeviceDetailDTO(userDevice); + } + + public UserDeviceDetailDTO updateUserDevice(String uuid, UserDeviceCreateUpdateDTO updateDTO) { + UserDevice userDevice = userDeviceRepository.findByUuid(uuid); + if (userDevice != null) { + updateUserDeviceFromDTO(userDevice, updateDTO); + userDevice = userDeviceRepository.save(userDevice); + return convertToUserDeviceDetailDTO(userDevice); + } + return null; + } + + public boolean deleteUserDevice(String uuid) { + UserDevice userDevice = userDeviceRepository.findByUuid(uuid); + if (userDevice != null) { + userDeviceRepository.delete(userDevice); + return true; + } + return false; + } + + private UserDeviceDTO convertToUserDeviceDTO(UserDevice userDevice) { + UserDeviceDTO dto = new UserDeviceDTO(); + dto.setUuid(userDevice.getUuid()); + dto.setModel(userDevice.getModel()); + dto.setType(userDevice.getType()); + dto.setInterfaceType(userDevice.getInterfaceType()); + dto.setMessagingAppUuid(userDevice.getMessagingAppUuid()); + return dto; + } + + private UserDeviceDetailDTO convertToUserDeviceDetailDTO(UserDevice userDevice) { + UserDeviceDetailDTO detailDTO = new UserDeviceDetailDTO(); + detailDTO.setUuid(userDevice.getUuid()); + detailDTO.setModel(userDevice.getModel()); + detailDTO.setType(userDevice.getType()); + detailDTO.setInterfaceType(userDevice.getInterfaceType()); + detailDTO.setMessagingAppUuid(userDevice.getMessagingAppUuid()); + + UserDeviceDetailInfoDTO subscriptionInfo = getmessagingAppInfo(userDevice.getMessagingAppUuid()); + detailDTO.setMessagingAppInfo(subscriptionInfo); + + return detailDTO; + } + + private void updateUserDeviceFromDTO(UserDevice userDevice, UserDeviceCreateUpdateDTO dto) { + userDevice.setModel(dto.getModel()); + userDevice.setType(dto.getType()); + userDevice.setInterfaceType(dto.getInterfaceType()); + userDevice.setMessagingAppUuid(dto.getMessagingAppUuid()); + } + + private String createUUID() { + Random random = new Random(); + long mostSigBits = random.nextLong(); + long leastSigBits = random.nextLong(); + return String.format("%08x-%04x-%04x-%04x-%012x", + mostSigBits >>> 32, (mostSigBits >>> 16) & 0xFFFF, mostSigBits & 0xFFFF, + (leastSigBits >>> 16) & 0xFFFF, leastSigBits & 0xFFFF); + } + + private UserDeviceDetailInfoDTO getmessagingAppInfo(String messagingAppUuid) { + String messagingAppInfoUrl = "http://nginx/messaging-application/" + messagingAppUuid; + return restTemplate.getForObject(messagingAppInfoUrl, UserDeviceDetailInfoDTO.class); + } +} diff --git a/kamyshov_danila_lab_3/user-device-application/src/main/resources/application.properties b/kamyshov_danila_lab_3/user-device-application/src/main/resources/application.properties new file mode 100644 index 0000000..b00d2a6 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.hibernate.ddl-auto=update +spring.h2.console.enabled=true + +server.port=8090 + diff --git a/kamyshov_danila_lab_3/user-device-application/src/test/java/com/example/userdeviceapplication/UserDeviceApplicationTests.java b/kamyshov_danila_lab_3/user-device-application/src/test/java/com/example/userdeviceapplication/UserDeviceApplicationTests.java new file mode 100644 index 0000000..46aa8c9 --- /dev/null +++ b/kamyshov_danila_lab_3/user-device-application/src/test/java/com/example/userdeviceapplication/UserDeviceApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.userdeviceapplication; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class UserDeviceApplicationTests { + + @Test + void contextLoads() { + } + +}