diff --git a/notification-service/pom.xml b/notification-service/pom.xml
index b9d3ef4..3ee33e8 100644
--- a/notification-service/pom.xml
+++ b/notification-service/pom.xml
@@ -39,5 +39,17 @@
spring-boot-starter-mail
3.4.6
+
+ ru.project.iakov
+ user-service
+ 1.0-SNAPSHOT
+ compile
+
+
+ ru.project.iakov
+ user-service
+ 1.0-SNAPSHOT
+ compile
+
\ No newline at end of file
diff --git a/notification-service/src/main/java/ru/project/iakov/notificationservice/NotificationServiceApplication.java b/notification-service/src/main/java/ru/project/iakov/notificationservice/NotificationServiceApplication.java
index c8f0a56..585e2e0 100644
--- a/notification-service/src/main/java/ru/project/iakov/notificationservice/NotificationServiceApplication.java
+++ b/notification-service/src/main/java/ru/project/iakov/notificationservice/NotificationServiceApplication.java
@@ -2,8 +2,9 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-@SpringBootApplication
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class NotificationServiceApplication {
public static void main(String[] args) {
diff --git a/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/EmailController.java b/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/EmailController.java
index adb42d0..09c3793 100644
--- a/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/EmailController.java
+++ b/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/EmailController.java
@@ -3,6 +3,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.project.iakov.notificationservice.dto.EmailRequest;
import ru.project.iakov.notificationservice.model.EventType;
@@ -12,6 +13,7 @@
@RestController
@RequestMapping("/api/v1/email")
@RequiredArgsConstructor
+@Validated
public class EmailController {
private final EmailService emailService;
diff --git a/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/NotificationController.java b/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/NotificationController.java
new file mode 100644
index 0000000..08bda19
--- /dev/null
+++ b/notification-service/src/main/java/ru/project/iakov/notificationservice/controller/NotificationController.java
@@ -0,0 +1,34 @@
+package ru.project.iakov.notificationservice.controller;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import ru.project.iakov.notificationservice.dto.EmailRequest;
+import ru.project.iakov.notificationservice.service.EmailService;
+
+
+@Slf4j
+@RestController
+@RequestMapping("/api/v1/kafka")
+@RequiredArgsConstructor
+public class NotificationController {
+
+ private final EmailService emailService;
+
+ @PostMapping("/send")
+ public ResponseEntity sendEmail(@RequestBody EmailRequest request) {
+ try {
+ String body = switch (request.getEventType()) {
+ case CREATED -> "Здравствуйте! Ваш аккаунт был создан.";
+ case DELETED -> "Здравствуйте! Ваш аккаунт был удалён.";
+ };
+
+ emailService.sendEmail(request.getEmail(), request.getSubject(), body);
+ return ResponseEntity.ok("Письмо отправлено");
+ } catch (Exception e) {
+ return ResponseEntity.internalServerError()
+ .body("Ошибка: " + e.getMessage());
+ }
+ }
+}
diff --git a/notification-service/src/main/java/ru/project/iakov/notificationservice/dto/UserEvent.java b/notification-service/src/main/java/ru/project/iakov/notificationservice/dto/UserEvent.java
index 232df3b..19cd9fc 100644
--- a/notification-service/src/main/java/ru/project/iakov/notificationservice/dto/UserEvent.java
+++ b/notification-service/src/main/java/ru/project/iakov/notificationservice/dto/UserEvent.java
@@ -11,5 +11,6 @@
@Builder
public class UserEvent {
private String email;
+ private String subject;
private EventType eventType;
}
\ No newline at end of file
diff --git a/notification-service/src/main/java/ru/project/iakov/notificationservice/service/KafkaConsumerService.java b/notification-service/src/main/java/ru/project/iakov/notificationservice/service/KafkaConsumerService.java
index 08de591..119dc17 100644
--- a/notification-service/src/main/java/ru/project/iakov/notificationservice/service/KafkaConsumerService.java
+++ b/notification-service/src/main/java/ru/project/iakov/notificationservice/service/KafkaConsumerService.java
@@ -18,8 +18,7 @@ public class KafkaConsumerService {
private final ObjectMapper objectMapper;
@KafkaListener(topics = "user-events", groupId = "notification-group")
- public void listen(ConsumerRecord record) {
- String message = record.value();
+ public void listen(String message) {
log.info("Kafka message: {}", message);
try {
UserEvent event = objectMapper.readValue(message, UserEvent.class);
diff --git a/user-service/pom.xml b/user-service/pom.xml
index 045cabe..45a14a8 100644
--- a/user-service/pom.xml
+++ b/user-service/pom.xml
@@ -3,51 +3,73 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
+
ru.project.iakov
user-service
1.0-SNAPSHOT
+
- 24
- 24
+ 21
+ 21
UTF-8
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
org.postgresql
postgresql
42.7.5
+
org.projectlombok
lombok
1.18.38
provided
+
org.springframework.boot
spring-boot-starter-web
- 3.5.0
+
org.springframework.boot
spring-boot-starter-data-jpa
- 3.5.0
+
org.springframework.boot
spring-boot-starter-test
- 3.5.0
test
+
org.springframework.kafka
spring-kafka
- 3.3.6
+
org.springframework.boot
spring-boot-starter-mail
- 3.4.6
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.5.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
-
\ No newline at end of file
+
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/controller/NotificationController.java b/user-service/src/main/java/ru/project/iakov/homework2/controller/NotificationController.java
deleted file mode 100644
index fe58216..0000000
--- a/user-service/src/main/java/ru/project/iakov/homework2/controller/NotificationController.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package ru.project.iakov.homework2.controller;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import ru.project.iakov.homework2.dto.UserEvent;
-import ru.project.iakov.homework2.service.KafkaProducerService;
-
-@Slf4j
-@RestController
-@RequestMapping("/api/v1/kafka")
-@RequiredArgsConstructor
-@Validated
-public class NotificationController {
-
- private final KafkaProducerService kafkaProducer;
- private final ObjectMapper objectMapper;
-
- @PostMapping("/publish")
- public ResponseEntity send(@RequestBody UserEvent request) {
- log.info("Получен запрос на публикацию события: {}", request);
- try {
- String message = objectMapper.writeValueAsString(request);
- kafkaProducer.sendUserEvent(message);
- return ResponseEntity.ok().build();
- } catch (JsonProcessingException e) {
- log.error("Ошибка сериализации события: {}", e.getMessage(), e);
- return ResponseEntity.internalServerError().build();
- }
- }
-}
\ No newline at end of file
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/controller/UserController.java b/user-service/src/main/java/ru/project/iakov/homework2/controller/UserController.java
index 6f3833d..ecefac8 100644
--- a/user-service/src/main/java/ru/project/iakov/homework2/controller/UserController.java
+++ b/user-service/src/main/java/ru/project/iakov/homework2/controller/UserController.java
@@ -1,49 +1,70 @@
package ru.project.iakov.homework2.controller;
+import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.hateoas.CollectionModel;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.project.iakov.homework2.dto.UserDto;
+import ru.project.iakov.homework2.model.UserModel;
+import ru.project.iakov.homework2.model.UserModelAssembler;
import ru.project.iakov.homework2.service.UserService;
import java.util.List;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
+
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
+ private final UserModelAssembler userModelAssembler;
@Autowired
- public UserController(UserService userService) {
+ public UserController(UserService userService, UserModelAssembler userModelAssembler) {
this.userService = userService;
+ this.userModelAssembler = userModelAssembler;
}
+ @Operation(summary = "Получить пользователя по ID")
@GetMapping("/{id}")
- public ResponseEntity getUserById(@PathVariable("id") Long id) {
- UserDto userDto = userService.findById(id);
- return ResponseEntity.ok(userDto);
+ public ResponseEntity getUserById(@PathVariable("id") Long id) {
+ UserDto dto = userService.findById(id);
+ return ResponseEntity.ok(userModelAssembler.toModel(dto));
}
+ @Operation(summary = "Получить всех пользователей")
@GetMapping
- public ResponseEntity> getAllUsers() {
+ public ResponseEntity> getAllUsers() {
List users = userService.findAll();
- return ResponseEntity.ok(users);
+ List models = users.stream()
+ .map(userModelAssembler::toModel)
+ .toList();
+
+ CollectionModel collectionModel = CollectionModel.of(models);
+ collectionModel.add(linkTo(methodOn(UserController.class).getAllUsers()).withSelfRel());
+
+ return ResponseEntity.ok(collectionModel);
}
+ @Operation(summary = "Создать пользователя")
@PostMapping
public ResponseEntity createUser(@RequestBody UserDto userDto) {
UserDto createdUser = userService.createUser(userDto);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
+ @Operation(summary = "Обновить данные пользователя")
@PutMapping("/{id}")
public ResponseEntity updateUser(@PathVariable("id") Long id, @RequestBody UserDto userDto) {
UserDto updatedUser = userService.updateUser(id, userDto);
return ResponseEntity.ok(updatedUser);
}
+ @Operation(summary = "Удалить пользователя по ID")
@DeleteMapping("/{id}")
public ResponseEntity deleteUser(@PathVariable("id") Long id) {
userService.deleteUser(id);
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/model/UserModel.java b/user-service/src/main/java/ru/project/iakov/homework2/model/UserModel.java
new file mode 100644
index 0000000..a85abc9
--- /dev/null
+++ b/user-service/src/main/java/ru/project/iakov/homework2/model/UserModel.java
@@ -0,0 +1,16 @@
+package ru.project.iakov.homework2.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.hateoas.RepresentationModel;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class UserModel extends RepresentationModel {
+ private Long id;
+ private String name;
+ private String email;
+ private int age;
+}
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/model/UserModelAssembler.java b/user-service/src/main/java/ru/project/iakov/homework2/model/UserModelAssembler.java
new file mode 100644
index 0000000..7a97841
--- /dev/null
+++ b/user-service/src/main/java/ru/project/iakov/homework2/model/UserModelAssembler.java
@@ -0,0 +1,28 @@
+package ru.project.iakov.homework2.model;
+
+import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
+import org.springframework.stereotype.Component;
+import ru.project.iakov.homework2.controller.UserController;
+import ru.project.iakov.homework2.dto.UserDto;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
+
+@Component
+public class UserModelAssembler extends RepresentationModelAssemblerSupport {
+
+ public UserModelAssembler() {
+ super(UserController.class, UserModel.class);
+ }
+
+ @Override
+ public UserModel toModel(UserDto dto) {
+ UserModel model = new UserModel(dto.getId(), dto.getName(), dto.getEmail(), dto.getAge());
+
+ model.add(linkTo(methodOn(UserController.class).getUserById(dto.getId())).withSelfRel());
+ model.add(linkTo(methodOn(UserController.class).getAllUsers()).withRel("all-users"));
+ model.add(linkTo(methodOn(UserController.class).deleteUser(dto.getId())).withRel("delete"));
+
+ return model;
+ }
+}
\ No newline at end of file
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/service/UserService.java b/user-service/src/main/java/ru/project/iakov/homework2/service/UserService.java
index 3de3493..c6293b3 100644
--- a/user-service/src/main/java/ru/project/iakov/homework2/service/UserService.java
+++ b/user-service/src/main/java/ru/project/iakov/homework2/service/UserService.java
@@ -12,7 +12,6 @@
import ru.project.iakov.homework2.model.EventType;
import ru.project.iakov.homework2.repository.UserRepository;
-import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
diff --git a/user-service/src/test/java/ru/project/iakov/homework2/controller/EmailControllerTest.java b/user-service/src/test/java/ru/project/iakov/homework2/controller/EmailControllerTest.java
deleted file mode 100644
index ae09553..0000000
--- a/user-service/src/test/java/ru/project/iakov/homework2/controller/EmailControllerTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package ru.project.iakov.homework2.controller;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.http.MediaType;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
-import org.springframework.test.web.servlet.MockMvc;
-import ru.project.iakov.homework2.dto.EmailRequest;
-import ru.project.iakov.homework2.service.EmailService;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@AutoConfigureMockMvc
-public class EmailControllerTest {
- @Autowired
- private MockMvc mockMvc;
-
- @MockitoBean
- private EmailService emailService;
-
- @Test
- public void testSendEmail_success() throws Exception {
- EmailRequest request = new EmailRequest("lysenko_iakov@yahoo.com", "Тест", "Тест");
-
- mockMvc.perform(post("/api/v1/email/send")
- .contentType(MediaType.APPLICATION_JSON)
- .content(new ObjectMapper().writeValueAsString(request)))
- .andExpect(status().isOk());
-
- verify(emailService, times(1)).sendEmail("lysenko_iakov@yahoo.com", "Тест", "Тест");
- }
-}
\ No newline at end of file
diff --git a/user-service/src/test/java/ru/project/iakov/homework2/controller/UserControllerTest.java b/user-service/src/test/java/ru/project/iakov/homework2/controller/UserControllerTest.java
index 4873e5d..5fea5ee 100644
--- a/user-service/src/test/java/ru/project/iakov/homework2/controller/UserControllerTest.java
+++ b/user-service/src/test/java/ru/project/iakov/homework2/controller/UserControllerTest.java
@@ -5,8 +5,8 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import ru.project.iakov.homework2.dto.UserDto;
import ru.project.iakov.homework2.service.UserService;
@@ -29,7 +29,7 @@ class UserControllerTest {
@Autowired
private MockMvc mockMvc;
- @MockitoBean
+ @MockBean
private UserService userService;
@Autowired
diff --git a/user-service/src/test/java/ru/project/iakov/homework2/kafka/KafkaConsumerTest.java b/user-service/src/test/java/ru/project/iakov/homework2/kafka/KafkaConsumerTest.java
deleted file mode 100644
index e2854d5..0000000
--- a/user-service/src/test/java/ru/project/iakov/homework2/kafka/KafkaConsumerTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package ru.project.iakov.homework2.kafka;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
-import ru.project.iakov.homework2.dto.UserEvent;
-import ru.project.iakov.homework2.service.EmailService;
-
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-@AutoConfigureMockMvc
-@SpringBootTest
-public class KafkaConsumerTest {
-
- @Autowired
- private KafkaConsumerService kafkaConsumer;
-
- @MockitoBean
- private EmailService emailService;
-
- @Test
- public void testKafkaConsumer_sendsEmailOnCreatedEvent() {
- UserEvent event = UserEvent.builder()
- .email("lysenko_iakov@yahoo.com")
- .subject("Тест: создание")
- .eventType("CREATED")
- .build();
-
- kafkaConsumer.listen(event);
-
- verify(emailService, times(1)).sendEmail(eq("lysenko_iakov@yahoo.com"), anyString(), contains("создан"));
- }
-
- @Test
- public void testKafkaConsumer_sendsEmailOnDeletedEvent() {
- UserEvent event = UserEvent.builder()
- .email("lysenko_iakov@yahoo.com")
- .subject("Тест: удаление")
- .eventType("DELETED")
- .build();
-
- kafkaConsumer.listen(event);
-
- verify(emailService, times(1)).sendEmail(eq("lysenko_iakov@yahoo.com"), anyString(), contains("удалён"));
- }
-}
\ No newline at end of file