diff --git a/api-gateway/Dockerfile b/api-gateway/Dockerfile
new file mode 100644
index 0000000..3b78cf0
--- /dev/null
+++ b/api-gateway/Dockerfile
@@ -0,0 +1,6 @@
+FROM eclipse-temurin:21-jdk-alpine
+LABEL authors="iakovlysenko"
+VOLUME /tmp
+ARG JAR_FILE=target/api-gateway-1.0-SNAPSHOT.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml
new file mode 100644
index 0000000..ef025ff
--- /dev/null
+++ b/api-gateway/pom.xml
@@ -0,0 +1,79 @@
+
+
+ 4.0.0
+
+ ru.project.iakov
+ api-gateway
+ 1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+
+ 21
+ 2023.0.1
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.2.5
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+ org.projectlombok
+ lombok
+ 1.18.38
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
\ No newline at end of file
diff --git a/api-gateway/src/main/java/ru/project/iakov/apigateway/ApiGatewayApplication.java b/api-gateway/src/main/java/ru/project/iakov/apigateway/ApiGatewayApplication.java
new file mode 100644
index 0000000..29f365a
--- /dev/null
+++ b/api-gateway/src/main/java/ru/project/iakov/apigateway/ApiGatewayApplication.java
@@ -0,0 +1,11 @@
+package ru.project.iakov.apigateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ApiGatewayApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ApiGatewayApplication.class, args);
+ }
+}
diff --git a/api-gateway/src/main/resources/application-docker.yml b/api-gateway/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..f038d5a
--- /dev/null
+++ b/api-gateway/src/main/resources/application-docker.yml
@@ -0,0 +1,23 @@
+server:
+ port: 8080
+
+spring:
+ application:
+ name: api-gateway
+ cloud:
+ gateway:
+ routes:
+ - id: user-service
+ uri: lb://user-service
+ predicates:
+ - Path=/users/**
+ - id: notification-service
+ uri: lb://notification-service
+ predicates:
+ - Path=/api/v1/email/**
+ config:
+ import: optional:configserver:http://config-server:8888
+eureka:
+ client:
+ service-url:
+ defaultZone: http://discovery-server:8761/eureka
\ No newline at end of file
diff --git a/api-gateway/src/main/resources/application.yml b/api-gateway/src/main/resources/application.yml
new file mode 100644
index 0000000..bb2fe75
--- /dev/null
+++ b/api-gateway/src/main/resources/application.yml
@@ -0,0 +1,23 @@
+server:
+ port: 8082
+spring:
+ application:
+ name: api-gateway
+ cloud:
+ gateway:
+ routes:
+ - id: user-service
+ uri: lb://user-service
+ predicates:
+ - Path=/users/**
+ - id: notification-service
+ uri: lb://notification-service
+ predicates:
+ - Path=/api/v1/email/**
+ config:
+ import: optional:configserver:http://localhost:8888
+
+eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/api-gateway/target/classes/application.yml b/api-gateway/target/classes/application.yml
new file mode 100644
index 0000000..bb2fe75
--- /dev/null
+++ b/api-gateway/target/classes/application.yml
@@ -0,0 +1,23 @@
+server:
+ port: 8082
+spring:
+ application:
+ name: api-gateway
+ cloud:
+ gateway:
+ routes:
+ - id: user-service
+ uri: lb://user-service
+ predicates:
+ - Path=/users/**
+ - id: notification-service
+ uri: lb://notification-service
+ predicates:
+ - Path=/api/v1/email/**
+ config:
+ import: optional:configserver:http://localhost:8888
+
+eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/api-gateway/target/classes/ru/project/iakov/apigateway/ApiGatewayApplication.class b/api-gateway/target/classes/ru/project/iakov/apigateway/ApiGatewayApplication.class
new file mode 100644
index 0000000..64e4729
Binary files /dev/null and b/api-gateway/target/classes/ru/project/iakov/apigateway/ApiGatewayApplication.class differ
diff --git a/config-repo/application.yml b/config-repo/application.yml
new file mode 100644
index 0000000..8756ed0
--- /dev/null
+++ b/config-repo/application.yml
@@ -0,0 +1,10 @@
+eureka:
+ client:
+ register-with-eureka: true
+ fetch-registry: true
+ service-url:
+ defaultZone: http://discovery-server:8761/eureka/
+
+spring:
+ application:
+ name: default
\ No newline at end of file
diff --git a/config-repo/config-server.yml b/config-repo/config-server.yml
new file mode 100644
index 0000000..1bba46d
--- /dev/null
+++ b/config-repo/config-server.yml
@@ -0,0 +1,6 @@
+server:
+ port: 8888
+
+spring:
+ application:
+ name: config-server
\ No newline at end of file
diff --git a/config-repo/notification-service.yml b/config-repo/notification-service.yml
new file mode 100644
index 0000000..faf13b1
--- /dev/null
+++ b/config-repo/notification-service.yml
@@ -0,0 +1,20 @@
+server:
+ port: 8082
+
+spring:
+ application:
+ name: notification-service
+ mail:
+ host: smtp.mail.ru
+ port: 465
+ username: ${EMAIL_USERNAME}
+ password: ${EMAIL_PASSWORD}
+ properties:
+ mail:
+ smtp:
+ auth: true
+ starttls:
+ enable: true
+
+kafka:
+ topic: user-events
\ No newline at end of file
diff --git a/config-repo/user-service.yml b/config-repo/user-service.yml
new file mode 100644
index 0000000..ca8ba01
--- /dev/null
+++ b/config-repo/user-service.yml
@@ -0,0 +1,17 @@
+server:
+ port: 8081
+
+spring:
+ application:
+ name: user-service
+ datasource:
+ url: jdbc:postgresql://postgres:5432/postgres
+ username: postgres
+ password: postgres
+ jpa:
+ hibernate:
+ ddl-auto: update
+ show-sql: true
+ properties:
+ hibernate:
+ format_sql: true
\ No newline at end of file
diff --git a/config-server/Dockerfile b/config-server/Dockerfile
new file mode 100644
index 0000000..a2e8c68
--- /dev/null
+++ b/config-server/Dockerfile
@@ -0,0 +1,6 @@
+FROM eclipse-temurin:21-jdk-alpine
+LABEL authors="iakovlysenko"
+VOLUME /tmp
+ARG JAR_FILE=target/config-server-1.0-SNAPSHOT.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/config-server/pom.xml b/config-server/pom.xml
new file mode 100644
index 0000000..d777305
--- /dev/null
+++ b/config-server/pom.xml
@@ -0,0 +1,79 @@
+
+
+ 4.0.0
+
+ ru.project.iakov
+ config-server
+ 1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+
+ 21
+ 2023.0.1
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.2.5
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+ org.projectlombok
+ lombok
+ 1.18.38
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
\ No newline at end of file
diff --git a/config-server/src/main/java/ru/project/iakov/configserver/ConfigServerApplication.java b/config-server/src/main/java/ru/project/iakov/configserver/ConfigServerApplication.java
new file mode 100644
index 0000000..e93fcc0
--- /dev/null
+++ b/config-server/src/main/java/ru/project/iakov/configserver/ConfigServerApplication.java
@@ -0,0 +1,13 @@
+package ru.project.iakov.configserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+@SpringBootApplication
+@EnableConfigServer
+public class ConfigServerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ConfigServerApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/config-server/src/main/resources/application-docker.yml b/config-server/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..d7768f3
--- /dev/null
+++ b/config-server/src/main/resources/application-docker.yml
@@ -0,0 +1,15 @@
+server:
+ port: 8888
+
+spring:
+ cloud:
+ config:
+ server:
+ native:
+ search-locations: file:/config
+
+
+eureka:
+ client:
+ service-url:
+ defaultZone: http://discovery-server:8761/eureka/
\ No newline at end of file
diff --git a/config-server/src/main/resources/application.yml b/config-server/src/main/resources/application.yml
new file mode 100644
index 0000000..6020c3a
--- /dev/null
+++ b/config-server/src/main/resources/application.yml
@@ -0,0 +1,14 @@
+server:
+ port: 8888
+spring:
+ application:
+ name: config-server
+ cloud:
+ config:
+ server:
+ git:
+ uri: file:/config
+eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/config-server/target/classes/application.yml b/config-server/target/classes/application.yml
new file mode 100644
index 0000000..6020c3a
--- /dev/null
+++ b/config-server/target/classes/application.yml
@@ -0,0 +1,14 @@
+server:
+ port: 8888
+spring:
+ application:
+ name: config-server
+ cloud:
+ config:
+ server:
+ git:
+ uri: file:/config
+eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/config-server/target/classes/ru/project/iakov/configserver/ConfigServerApplication.class b/config-server/target/classes/ru/project/iakov/configserver/ConfigServerApplication.class
new file mode 100644
index 0000000..8ab5ee1
Binary files /dev/null and b/config-server/target/classes/ru/project/iakov/configserver/ConfigServerApplication.class differ
diff --git a/discovery-server/Dockerfile b/discovery-server/Dockerfile
new file mode 100644
index 0000000..3d01bf0
--- /dev/null
+++ b/discovery-server/Dockerfile
@@ -0,0 +1,6 @@
+FROM eclipse-temurin:21-jdk-alpine
+LABEL authors="iakovlysenko"
+VOLUME /tmp
+ARG JAR_FILE=target/discovery-server-1.0-SNAPSHOT.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/discovery-server/pom.xml b/discovery-server/pom.xml
new file mode 100644
index 0000000..e6f040c
--- /dev/null
+++ b/discovery-server/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+ ru.project.iakov
+ discovery-server
+ 1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+
+ 21
+ 2023.0.1
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.2.5
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+ org.projectlombok
+ lombok
+ 1.18.38
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-server
+
+
+
\ No newline at end of file
diff --git a/discovery-server/src/main/java/ru/project/iakov/discoveryserver/DiscoveryServerApplication.java b/discovery-server/src/main/java/ru/project/iakov/discoveryserver/DiscoveryServerApplication.java
new file mode 100644
index 0000000..dd7c274
--- /dev/null
+++ b/discovery-server/src/main/java/ru/project/iakov/discoveryserver/DiscoveryServerApplication.java
@@ -0,0 +1,13 @@
+package ru.project.iakov.discoveryserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+@SpringBootApplication
+@EnableEurekaServer
+public class DiscoveryServerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DiscoveryServerApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/discovery-server/src/main/resources/application-docker.yml b/discovery-server/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..40de21b
--- /dev/null
+++ b/discovery-server/src/main/resources/application-docker.yml
@@ -0,0 +1,11 @@
+server:
+ port: 8761
+
+spring:
+ application:
+ name: discovery-server
+
+eureka:
+ client:
+ register-with-eureka: false
+ fetch-registry: false
\ No newline at end of file
diff --git a/discovery-server/src/main/resources/application.yml b/discovery-server/src/main/resources/application.yml
new file mode 100644
index 0000000..9652c74
--- /dev/null
+++ b/discovery-server/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+server:
+ port: 8761
+spring:
+ application:
+ name: discovery-server
+eureka:
+ client:
+ register-with-eureka: false
+ fetch-registry: false
\ No newline at end of file
diff --git a/discovery-server/target/classes/application.yml b/discovery-server/target/classes/application.yml
new file mode 100644
index 0000000..9652c74
--- /dev/null
+++ b/discovery-server/target/classes/application.yml
@@ -0,0 +1,9 @@
+server:
+ port: 8761
+spring:
+ application:
+ name: discovery-server
+eureka:
+ client:
+ register-with-eureka: false
+ fetch-registry: false
\ No newline at end of file
diff --git a/discovery-server/target/classes/ru/project/iakov/discoveryserver/DiscoveryServerApplication.class b/discovery-server/target/classes/ru/project/iakov/discoveryserver/DiscoveryServerApplication.class
new file mode 100644
index 0000000..4b2b6cc
Binary files /dev/null and b/discovery-server/target/classes/ru/project/iakov/discoveryserver/DiscoveryServerApplication.class differ
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..4a330a5
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,115 @@
+services:
+
+ postgres:
+ image: postgres:15
+ container_name: postgres
+ restart: unless-stopped
+ user: postgres
+ environment:
+ POSTGRES_DB: postgres
+ PGUSER: postgres
+ POSTGRES_PASSWORD: postgres
+ env_file:
+ - .env
+ ports:
+ - "5432:5432"
+ volumes:
+ - pgdata:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER $$POSTGRES_DB"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ zookeeper:
+ image: confluentinc/cp-zookeeper:7.4.0
+ container_name: zookeeper
+ environment:
+ ZOOKEEPER_CLIENT_PORT: 2181
+ ports:
+ - "2181:2181"
+
+ kafka:
+ image: confluentinc/cp-kafka:7.4.0
+ container_name: kafka
+ depends_on:
+ - zookeeper
+ ports:
+ - "9092:9092"
+ environment:
+ KAFKA_BROKER_ID: 1
+ KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
+
+ discovery-server:
+ container_name: discovery-server
+ image: discovery-server:latest
+ build:
+ context: ./discovery-server
+ ports:
+ - "8761:8761"
+
+ config-server:
+ image: config-server:latest
+ build:
+ context: ./config-server
+ ports:
+ - "8888:8888"
+ volumes:
+ - ./config-repo:/config
+ depends_on:
+ - discovery-server
+ environment:
+ - SPRING_PROFILES_ACTIVE=docker
+
+ user-service:
+ image: user-service:latest
+ build:
+ context: ./user-service
+ ports:
+ - "8082:8082"
+ depends_on:
+ - discovery-server
+ - kafka
+ - postgres
+ - config-server
+ environment:
+ - SPRING_PROFILES_ACTIVE=docker
+ - EMAIL_USERNAME=${EMAIL_USERNAME}
+ - EMAIL_PASSWORD=${EMAIL_PASSWORD}
+ - DB_USERNAME=${DB_USERNAME}
+ - DB_PASSWORD=${DB_PASSWORD}
+ env_file:
+ - .env
+
+ notification-service:
+ image: notification-service:latest
+ build:
+ context: ./notification-service
+ ports:
+ - "8081:8081"
+ depends_on:
+ - kafka
+ - config-server
+ environment:
+ - SPRING_PROFILES_ACTIVE=docker
+ - EMAIL_USERNAME=${EMAIL_USERNAME}
+ - EMAIL_PASSWORD=${EMAIL_PASSWORD}
+ env_file:
+ - .env
+
+ api-gateway:
+ image: api-gateway:latest
+ build:
+ context: ./api-gateway
+ ports:
+ - "8080:8080"
+ depends_on:
+ - discovery-server
+ - config-server
+ environment:
+ - SPRING_PROFILES_ACTIVE=docker
+volumes:
+ pgdata:
+
diff --git a/notification-service/Dockerfile b/notification-service/Dockerfile
new file mode 100644
index 0000000..85e14b1
--- /dev/null
+++ b/notification-service/Dockerfile
@@ -0,0 +1,6 @@
+FROM eclipse-temurin:21-jdk-alpine
+LABEL authors="iakovlysenko"
+VOLUME /tmp
+ARG JAR_FILE=target/notification-service-1.0-SNAPSHOT.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/notification-service/pom.xml b/notification-service/pom.xml
index 3ee33e8..0580104 100644
--- a/notification-service/pom.xml
+++ b/notification-service/pom.xml
@@ -4,52 +4,111 @@
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
+ notification-service
1.0-SNAPSHOT
- 24
- 24
+ 21
+ 21
UTF-8
+ 2023.0.1
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.2.5
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+ org.projectlombok
+ lombok
+ 1.18.38
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
org.projectlombok
lombok
1.18.38
provided
+
+
org.springframework.boot
spring-boot-starter-web
- 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
+
+
- ru.project.iakov
- user-service
- 1.0-SNAPSHOT
- compile
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
- ru.project.iakov
- user-service
- 1.0-SNAPSHOT
- compile
+ org.springframework.cloud
+ spring-cloud-starter-config
\ No newline at end of file
diff --git a/notification-service/src/main/resources/application-docker.yml b/notification-service/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..8bef37d
--- /dev/null
+++ b/notification-service/src/main/resources/application-docker.yml
@@ -0,0 +1,24 @@
+server:
+ port: 8081
+
+spring:
+ application:
+ name: notification-service
+
+ kafka:
+ bootstrap-servers: kafka:9092
+
+ mail:
+ host: smtp.mail.ru
+ port: 465
+ username: ${EMAIL_USERNAME}
+ password: ${EMAIL_PASSWORD}
+ protocol: smtps
+ properties:
+ mail.smtp.auth: true
+ mail.smtp.starttls.enable: true
+
+eureka:
+ client:
+ service-url:
+ defaultZone: http://discovery-server:8761/eureka
\ No newline at end of file
diff --git a/notification-service/src/main/resources/application.yml b/notification-service/src/main/resources/application.yml
index be161d0..c457813 100644
--- a/notification-service/src/main/resources/application.yml
+++ b/notification-service/src/main/resources/application.yml
@@ -1,4 +1,8 @@
spring:
+ application:
+ name: notification-service
+ config:
+ import: optional:configserver:http://localhost:8888
kafka:
bootstrap-servers: localhost:9092
consumer:
@@ -21,4 +25,8 @@ logging:
root: INFO
server:
- port: 8081
\ No newline at end of file
+ port: 8081
+eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/user-service/Dockerfile b/user-service/Dockerfile
new file mode 100644
index 0000000..740935f
--- /dev/null
+++ b/user-service/Dockerfile
@@ -0,0 +1,6 @@
+FROM eclipse-temurin:21-jdk-alpine
+LABEL authors="iakovlysenko"
+VOLUME /tmp
+ARG JAR_FILE=target/user-service-1.0-SNAPSHOT.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/user-service/pom.xml b/user-service/pom.xml
index 45a14a8..dd877c1 100644
--- a/user-service/pom.xml
+++ b/user-service/pom.xml
@@ -4,16 +4,15 @@
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
+ ru.project.iakov.homework2
user-service
1.0-SNAPSHOT
-
21
21
UTF-8
+ 2023.0.1
-
org.springframework.boot
spring-boot-starter-parent
@@ -21,13 +20,61 @@
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.2.5
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+ org.projectlombok
+ lombok
+ 1.18.38
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
org.postgresql
postgresql
42.7.5
+
org.projectlombok
lombok
@@ -35,41 +82,62 @@
provided
+
org.springframework.boot
spring-boot-starter-web
-
org.springframework.boot
spring-boot-starter-data-jpa
+
org.springframework.boot
spring-boot-starter-test
test
+
org.springframework.kafka
spring-kafka
+
org.springframework.boot
spring-boot-starter-mail
+
org.springdoc
springdoc-openapi-starter-webmvc-ui
2.5.0
+
org.springframework.boot
spring-boot-starter-hateoas
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-circuitbreaker-resilience4j
+
-
+
\ No newline at end of file
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/dto/UserDto.java b/user-service/src/main/java/ru/project/iakov/homework2/dto/UserDto.java
index 7660dce..00156a2 100644
--- a/user-service/src/main/java/ru/project/iakov/homework2/dto/UserDto.java
+++ b/user-service/src/main/java/ru/project/iakov/homework2/dto/UserDto.java
@@ -1,6 +1,6 @@
package ru.project.iakov.homework2.dto;
-import lombok.*;
+import lombok.*;
import java.time.LocalDateTime;
@Data
diff --git a/user-service/src/main/java/ru/project/iakov/homework2/service/KafkaProducerService.java b/user-service/src/main/java/ru/project/iakov/homework2/service/KafkaProducerService.java
index 8671267..1ec5172 100644
--- a/user-service/src/main/java/ru/project/iakov/homework2/service/KafkaProducerService.java
+++ b/user-service/src/main/java/ru/project/iakov/homework2/service/KafkaProducerService.java
@@ -3,6 +3,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
+import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
@Service
@@ -13,8 +14,13 @@ public class KafkaProducerService {
private final KafkaTemplate kafkaTemplate;
private static final String TOPIC = "user-events";
+ @CircuitBreaker(name = "kafkaProducer", fallbackMethod = "sendUserEventFallback")
public void sendUserEvent(String message) {
log.info("Отправка сообщения в Kafka: {}", message);
kafkaTemplate.send(TOPIC, message);
}
+
+ public void sendUserEventFallback(String message, Throwable throwable) {
+ log.error("Ошибка отправки в Kafka: {}", throwable.getMessage());
+ }
}
\ No newline at end of file
diff --git a/user-service/src/main/resources/application-docker.yml b/user-service/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..e957962
--- /dev/null
+++ b/user-service/src/main/resources/application-docker.yml
@@ -0,0 +1,22 @@
+server:
+ port: 8082
+
+spring:
+ application:
+ name: user-service
+ datasource:
+ url: jdbc:postgresql://postgres:5432/postgres
+ username: ${DB_USERNAME}
+ password: ${DB_PASSWORD}
+ jpa:
+ hibernate:
+ ddl-auto: update
+ show-sql: true
+
+ kafka:
+ bootstrap-servers: kafka:9092
+
+eureka:
+ client:
+ service-url:
+ defaultZone: http://discovery-server:8761/eureka
\ No newline at end of file
diff --git a/user-service/src/main/resources/application.yml b/user-service/src/main/resources/application.yml
index 39d62b0..e93f89c 100644
--- a/user-service/src/main/resources/application.yml
+++ b/user-service/src/main/resources/application.yml
@@ -1,8 +1,12 @@
spring:
+ application:
+ name: user-service
+ config:
+ import: optional:configserver:http://configserver:8888
datasource:
- url: jdbc:postgresql://localhost:5432/postgres
- username: postgres
- password: postgres
+ url: jdbc:postgresql://postgres:5432/postgres
+ username: ${DB_USERNAME}
+ password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: update
@@ -34,4 +38,8 @@ spring:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
server:
- port: 8080
\ No newline at end of file
+ port: 8080
+ eureka:
+ client:
+ service-url:
+ defaultZone: http://localhost:8761/eureka
\ No newline at end of file
diff --git a/user-service/src/main/resources/hibernate.cfg.xml b/user-service/src/main/resources/hibernate.cfg.xml
deleted file mode 100644
index 1515a41..0000000
--- a/user-service/src/main/resources/hibernate.cfg.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
\ No newline at end of file
diff --git a/user-service/src/main/resources/log4j.properties b/user-service/src/main/resources/log4j.properties
deleted file mode 100644
index 7aabc61..0000000
--- a/user-service/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-log4j.rootLogger=INFO, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.Target=System.out
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss} %-5p [%c] - %m%n
-log4j.logger.org.hibernate.SQL=DEBUG
-log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
\ 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
deleted file mode 100644
index 5fea5ee..0000000
--- a/user-service/src/test/java/ru/project/iakov/homework2/controller/UserControllerTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package ru.project.iakov.homework2.controller;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.DisplayName;
-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.web.servlet.MockMvc;
-import ru.project.iakov.homework2.dto.UserDto;
-import ru.project.iakov.homework2.service.UserService;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-@WebMvcTest(UserController.class)
-class UserControllerTest {
-
- @Autowired
- private MockMvc mockMvc;
-
- @MockBean
- private UserService userService;
-
- @Autowired
- private ObjectMapper objectMapper;
-
- @DisplayName("Пользователь найден по ID")
- @Test
- void getUserById_whenUserExist() throws Exception {
- UserDto userDto = new UserDto(1L, "Ivan", "ivan@mail.ru", 30, LocalDateTime.now());
- given(userService.findById(1L)).willReturn(userDto);
-
- mockMvc.perform(get("/users/1"))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.name").value("Ivan"))
- .andExpect(jsonPath("$.email").value("ivan@mail.ru"));
- }
-
- @DisplayName("Такого пользователя нет")
- @Test
- void getUserById_whenUserNotExist() throws Exception {
- given(userService.findById(999L)).willThrow(new IllegalArgumentException());
-
- mockMvc.perform(get("/users/999"))
- .andExpect(result -> assertTrue(result.getResolvedException() instanceof IllegalArgumentException));
- }
-
- @DisplayName("Список пользователей")
- @Test
- void getAllUsers() throws Exception {
- List users = List.of(
- new UserDto(1L, "Ivan", "ivan@mail.ru", 30, LocalDateTime.now()),
- new UserDto(2L, "Petr", "petr@mail.ru", 28, LocalDateTime.now())
- );
- given(userService.findAll()).willReturn(users);
-
- mockMvc.perform(get("/users"))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.length()").value(2));
- }
-
- @DisplayName("Создание пользователя")
- @Test
- void createUser() throws Exception {
- UserDto toCreate = new UserDto(null, "Ivan", "ivan@mail.ru", 30, LocalDateTime.now());
- UserDto created = new UserDto(10L, "Petr", "petr@mail.ru", 28, LocalDateTime.now());
-
- given(userService.createUser(any(UserDto.class))).willReturn(created);
-
- mockMvc.perform(post("/users")
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(toCreate)))
- .andExpect(status().isCreated())
- .andExpect(jsonPath("$.id").value(10));
- }
-
- @DisplayName("Обновление пользователя")
- @Test
- void updateUser_whenUserExist() throws Exception {
- UserDto update = new UserDto(null, "Ivan", "ivan@mail.ru", 30, LocalDateTime.now());
- UserDto updated = new UserDto(1L, "Petr", "petr@mail.ru", 28, LocalDateTime.now());
-
- given(userService.updateUser(eq(1L), any(UserDto.class))).willReturn(updated);
-
- mockMvc.perform(put("/users/1")
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(update)))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.name").value("Petr"));
- }
-
- @DisplayName("При обновлении пользователь не найден")
- @Test
- void updateUser_whenUserIsNotExist() throws Exception {
- given(userService.updateUser(eq(999L), any(UserDto.class)))
- .willThrow(new IllegalArgumentException());
-
- mockMvc.perform(put("/users/999")
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(new UserDto(1L, "Ivan", "ivan@mail.ru", 30, LocalDateTime.now()))))
- .andExpect(result -> assertTrue(result.getResolvedException() instanceof IllegalArgumentException));
- }
-
- @DisplayName("Успешное удаление пользователя")
- @Test
- void deleteUserSuccess_whenUserExist() throws Exception {
- doNothing().when(userService).deleteUser(1L);
-
- mockMvc.perform(delete("/users/1"))
- .andExpect(status().isNoContent());
- }
-
- @DisplayName("При удалении пользователь не найден")
- @Test
- void deleteUser_whenUserIsNotExist() throws Exception {
- doThrow(new IllegalArgumentException()).when(userService).deleteUser(999L);
-
- mockMvc.perform(delete("/users/999"))
- .andExpect(result -> assertTrue(result.getResolvedException() instanceof IllegalArgumentException));
- }
-}
\ No newline at end of file