From 304bcb24d30dd261b7a4890c083f956f81415b55 Mon Sep 17 00:00:00 2001 From: stvort Date: Fri, 11 Oct 2019 22:19:47 +0400 Subject: [PATCH] spring-mail-integration-demo example gas been added --- examples/README.md | 1 + .../spring-mail-integration-demo/.gitignore | 31 +++++++ .../spring-mail-integration-demo/README.md | 17 ++++ examples/spring-mail-integration-demo/pom.xml | 78 ++++++++++++++++ .../SpringMailIntegrationDemoApplication.java | 15 +++ .../actuator/ActivityStatEndpoint.java | 23 +++++ .../config/AppProps.java | 13 +++ .../integration/ActivityStatGateway.java | 12 +++ .../integration/IntegrationConfig.java | 92 +++++++++++++++++++ .../integration/UserActivityGateway.java | 14 +++ .../models/ActivityStatElem.java | 38 ++++++++ .../models/ActivityType.java | 22 +++++ .../models/AppUser.java | 25 +++++ .../models/UserActivity.java | 38 ++++++++ .../repositories/ActivityRepository.java | 9 ++ .../repositories/ActivityStatRepository.java | 20 ++++ .../repositories/ActivityTypeRepository.java | 7 ++ .../repositories/AppUserRepository.java | 9 ++ ...ActivityStatCalculationEmitterSerivce.java | 23 +++++ .../services/UserActivityEmitterService.java | 32 +++++++ .../UserActivityToEmailTransformer.java | 8 ++ .../UserActivityToEmailTransformerImpl.java | 25 +++++ .../src/main/resources/application.yml | 34 +++++++ .../src/main/resources/data.sql | 16 ++++ .../src/main/resources/schema.sql | 8 ++ 25 files changed, 610 insertions(+) create mode 100644 examples/spring-mail-integration-demo/.gitignore create mode 100644 examples/spring-mail-integration-demo/README.md create mode 100644 examples/spring-mail-integration-demo/pom.xml create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/SpringMailIntegrationDemoApplication.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/actuator/ActivityStatEndpoint.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/config/AppProps.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/ActivityStatGateway.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/UserActivityGateway.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityStatElem.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityType.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/AppUser.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/UserActivity.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityRepository.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityStatRepository.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityTypeRepository.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/AppUserRepository.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityEmitterService.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformer.java create mode 100644 examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformerImpl.java create mode 100644 examples/spring-mail-integration-demo/src/main/resources/application.yml create mode 100644 examples/spring-mail-integration-demo/src/main/resources/data.sql create mode 100644 examples/spring-mail-integration-demo/src/main/resources/schema.sql diff --git a/examples/README.md b/examples/README.md index 2aa1a26c..1c4f887c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,3 +8,4 @@ * *mongo-db-demo* - MongoDB, MongoEventListener, Mongock * *docker-test-containers* - TestContainers * *spring-cloud-demo-stvort* - Config server, Eureka, Zuul, Feign client +* *spring-mail-integration-demo* - SpringMail SpringIntegration \ No newline at end of file diff --git a/examples/spring-mail-integration-demo/.gitignore b/examples/spring-mail-integration-demo/.gitignore new file mode 100644 index 00000000..a2a3040a --- /dev/null +++ b/examples/spring-mail-integration-demo/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/examples/spring-mail-integration-demo/README.md b/examples/spring-mail-integration-demo/README.md new file mode 100644 index 00000000..daa7b044 --- /dev/null +++ b/examples/spring-mail-integration-demo/README.md @@ -0,0 +1,17 @@ +## Пример работы с SpringMail через SpringIntegration + +В примере демонстрируется: +* *использование `@Scheduled` таймера для имитации пользовтельской активности* +* *обработка доменных сущностей средствами SpringIntegration (`@MessagingGateway`, `IntegrationFlow`) с использованием `route` и `subFlowMapping`* +* *создание и отправка email сообщений средствами SpringMail* +* *аггрегация данных с помощью SpringData/JPQL* +* *создание кастомного endpoint-а actuator-а для вывода статистики* + +Описание примера: +* *по таймеру `UserActivityEmitterService` достает из БД случайный тип активности и пользователя* +* *после чего формирует из них объект активности (`UserActivity`) и отправляет в поток обработки с помощью `UserActivityGateway`. Активности,* +* *активности, у которых в названии типа есть вхождение "Вредн" помечаются, как важные соответствующим заголовком отправляемого сообщения* +* *в потоке обработки (`appUserActivityFlow`) объект активности сохраняется в БД, а важные сообщения преобразуются в письма и отправляются на почту администратору* +* *по таймеру `ActivityStatCalculationEmitterSerivce` инициирует подсчет статистики с помощью отправки сообщения в `activityStatFlow` через `ActivityStatGateway`* +* *в данном потоке происходит удаление старых статистических данных, а так же подсчет и сохранение в БД новых* +* *за вывод статистических данных отвечает кастомный endpoint actuator-а `ActivityStatEndpoint`* diff --git a/examples/spring-mail-integration-demo/pom.xml b/examples/spring-mail-integration-demo/pom.xml new file mode 100644 index 00000000..150c451b --- /dev/null +++ b/examples/spring-mail-integration-demo/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.9.RELEASE + + + ru.otus.example + spring-mail-integration-demo + 0.0.1-SNAPSHOT + spring-integration-mail-demo + Spring mail integration demo project + + + 11 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-integration + + + org.springframework.boot + spring-boot-starter-mail + + + + com.h2database + h2 + runtime + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.integration + spring-integration-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/SpringMailIntegrationDemoApplication.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/SpringMailIntegrationDemoApplication.java new file mode 100644 index 00000000..0b289559 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/SpringMailIntegrationDemoApplication.java @@ -0,0 +1,15 @@ +package ru.otus.example.springmail_integration_demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableScheduling +@SpringBootApplication +public class SpringMailIntegrationDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringMailIntegrationDemoApplication.class, args); + } + +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/actuator/ActivityStatEndpoint.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/actuator/ActivityStatEndpoint.java new file mode 100644 index 00000000..74ec271d --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/actuator/ActivityStatEndpoint.java @@ -0,0 +1,23 @@ +package ru.otus.example.springmail_integration_demo.actuator; + +import lombok.RequiredArgsConstructor; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.stereotype.Component; +import ru.otus.example.springmail_integration_demo.models.ActivityStatElem; +import ru.otus.example.springmail_integration_demo.repositories.ActivityStatRepository; + +import java.util.List; + +@RequiredArgsConstructor +@Component +@Endpoint(id = "activity-stat") +public class ActivityStatEndpoint { + + private final ActivityStatRepository activityStatRepository; + + @ReadOperation + public List getAppUsersActivityStat() { + return activityStatRepository.findAll(); + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/config/AppProps.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/config/AppProps.java new file mode 100644 index 00000000..7e17ae81 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/config/AppProps.java @@ -0,0 +1,13 @@ +package ru.otus.example.springmail_integration_demo.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties("app") +public class AppProps { + private String serverEmail; + private String adminEmail; +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/ActivityStatGateway.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/ActivityStatGateway.java new file mode 100644 index 00000000..fc2d87cc --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/ActivityStatGateway.java @@ -0,0 +1,12 @@ +package ru.otus.example.springmail_integration_demo.integration; + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.messaging.handler.annotation.Payload; + +@MessagingGateway +public interface ActivityStatGateway { + + @Gateway(requestChannel = "activityStatInChanel") + void calcActivityStat(@Payload String extInfo); +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java new file mode 100644 index 00000000..9219fe1d --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java @@ -0,0 +1,92 @@ +package ru.otus.example.springmail_integration_demo.integration; + +import lombok.val; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.IntegrationComponentScan; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlowDefinition; +import org.springframework.integration.dsl.MessageChannels; +import org.springframework.integration.dsl.Pollers; +import org.springframework.integration.scheduling.PollerMetadata; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import ru.otus.example.springmail_integration_demo.repositories.ActivityRepository; +import ru.otus.example.springmail_integration_demo.repositories.ActivityStatRepository; +import ru.otus.example.springmail_integration_demo.services.UserActivityToEmailTransformer; + + +@Configuration +@IntegrationComponentScan +public class IntegrationConfig { + private static final int DEFAULT_QUEUE_CAPACITY = 100; + private static final int DEFAULT_POLLER_PERIOD = 1000; + + private static final String IS_IMPORTANT_MESSAGE = "isImportant"; + private static final String SAVE_METHOD_NAME = "save"; + private static final String TRANSFORM_METHOD_NAME = "transform"; + private static final String CALC_ACTIVITY_STAT_METHOD_NAME = "calcActivityStat"; + private static final String SAVE_ALL_METHOD_NAME = "saveAll"; + private static final String DELETE_ALL_METHOD_NAME = "deleteAll"; + + @Autowired + private ActivityRepository activityRepository; + + @Autowired + private ActivityStatRepository activityStatRepository; + + @Autowired + private UserActivityToEmailTransformer messageTransformer; + + @Autowired + private JavaMailSender mailSender; + + @Bean + public PollableChannel appUserActivityInChanel() { + return MessageChannels.queue("appUserActivityInChanel", DEFAULT_QUEUE_CAPACITY).get(); + } + + @Bean + public PollableChannel activityStatInChanel() { + return MessageChannels.queue("activityStatInChanel", DEFAULT_QUEUE_CAPACITY).get(); + } + + @Bean(name = PollerMetadata.DEFAULT_POLLER) + public PollerMetadata poller() { + return Pollers.fixedRate(DEFAULT_POLLER_PERIOD).get(); + } + + @Bean + public IntegrationFlow appUserActivityFlow() { + return f -> f.channel(appUserActivityInChanel()) + .handle(activityRepository, SAVE_METHOD_NAME) + .route(Message.class, m -> m.getHeaders().get(IS_IMPORTANT_MESSAGE, Boolean.class) + , mapping -> mapping.subFlowMapping(true, sub -> sub + .transform(messageTransformer, TRANSFORM_METHOD_NAME) + .handle(m -> { + val isImportant = m.getHeaders().get(IS_IMPORTANT_MESSAGE, Boolean.class); + if (isImportant != null && isImportant) { + mailSender.send((SimpleMailMessage) m.getPayload()); + } + }) + ) + .subFlowMapping(false, IntegrationFlowDefinition::nullChannel) + ); + } + + @Bean + public IntegrationFlow activityStatFlow() { + return f -> f.channel(activityStatInChanel()) + .handle((m, h) -> { + activityStatRepository.deleteAll(); + return true; + }) + .handle(activityStatRepository, CALC_ACTIVITY_STAT_METHOD_NAME) + .handle(activityStatRepository, SAVE_ALL_METHOD_NAME) + .log(); + + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/UserActivityGateway.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/UserActivityGateway.java new file mode 100644 index 00000000..2acdd320 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/UserActivityGateway.java @@ -0,0 +1,14 @@ +package ru.otus.example.springmail_integration_demo.integration; + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.messaging.handler.annotation.Payload; +import ru.otus.example.springmail_integration_demo.models.UserActivity; + +@MessagingGateway +public interface UserActivityGateway { + + @Gateway(requestChannel = "appUserActivityInChanel") + void processActivity(@Payload UserActivity activity, @Header(name = "isImportant") boolean isImportant); +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityStatElem.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityStatElem.java new file mode 100644 index 00000000..f4f8f317 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityStatElem.java @@ -0,0 +1,38 @@ +package ru.otus.example.springmail_integration_demo.models; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Data +@NoArgsConstructor +@Entity +@Table(name = "activity_stat") +public class ActivityStatElem { + + @JsonIgnore + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @JsonProperty("Имя пользователя") + @Column(name = "app_user_name") + private String appUserName; + + @JsonProperty("Тип активности") + @Column(name = "activity_type") + private String activityType; + + @JsonProperty("Количество") + @Column(name = "activities_count") + private long activitiesCount; + + public ActivityStatElem(String appUserName, String activityType, long activitiesCount) { + this.appUserName = appUserName; + this.activityType = activityType; + this.activitiesCount = activitiesCount; + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityType.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityType.java new file mode 100644 index 00000000..c1538928 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/ActivityType.java @@ -0,0 +1,22 @@ +package ru.otus.example.springmail_integration_demo.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "activity_types") +public class ActivityType { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "name") + private String name; +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/AppUser.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/AppUser.java new file mode 100644 index 00000000..53347a91 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/AppUser.java @@ -0,0 +1,25 @@ +package ru.otus.example.springmail_integration_demo.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "app_users") +public class AppUser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "email") + private String email; + + @Column(name = "name") + private String name; +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/UserActivity.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/UserActivity.java new file mode 100644 index 00000000..7bb6ac10 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/models/UserActivity.java @@ -0,0 +1,38 @@ +package ru.otus.example.springmail_integration_demo.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "app_users_activity") +public class UserActivity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "activity_time") + private LocalDateTime activityTime; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "activity_type_id") + private ActivityType type; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "app_user_id") + private AppUser appUser; + + public UserActivity(ActivityType type, AppUser appUser) { + this.id = id; + this.type = type; + this.appUser = appUser; + this.activityTime = LocalDateTime.now(); + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityRepository.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityRepository.java new file mode 100644 index 00000000..0f74455c --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityRepository.java @@ -0,0 +1,9 @@ +package ru.otus.example.springmail_integration_demo.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.example.springmail_integration_demo.models.UserActivity; + +@Transactional +public interface ActivityRepository extends JpaRepository { +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityStatRepository.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityStatRepository.java new file mode 100644 index 00000000..43230a76 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityStatRepository.java @@ -0,0 +1,20 @@ +package ru.otus.example.springmail_integration_demo.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.example.springmail_integration_demo.models.ActivityStatElem; + +import java.util.List; + +@Transactional +public interface ActivityStatRepository extends JpaRepository { + + @Transactional(readOnly = true) + @Query("select new ru.otus.example.springmail_integration_demo.models.ActivityStatElem(u.name, t.name, count(a)) " + + "from UserActivity a left join a.appUser u left join a.type t " + + "group by u.name, t.name " + + "order by count(a) desc, u.name, t.name") + List calcActivityStat(); + +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityTypeRepository.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityTypeRepository.java new file mode 100644 index 00000000..92347ab6 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/ActivityTypeRepository.java @@ -0,0 +1,7 @@ +package ru.otus.example.springmail_integration_demo.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.otus.example.springmail_integration_demo.models.ActivityType; + +public interface ActivityTypeRepository extends JpaRepository { +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/AppUserRepository.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/AppUserRepository.java new file mode 100644 index 00000000..72ff4542 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/repositories/AppUserRepository.java @@ -0,0 +1,9 @@ +package ru.otus.example.springmail_integration_demo.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.example.springmail_integration_demo.models.AppUser; + +@Transactional +public interface AppUserRepository extends JpaRepository { +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java new file mode 100644 index 00000000..a14d2ca8 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java @@ -0,0 +1,23 @@ +package ru.otus.example.springmail_integration_demo.services; + +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import ru.otus.example.springmail_integration_demo.integration.ActivityStatGateway; +import ru.otus.example.springmail_integration_demo.repositories.ActivityTypeRepository; +import ru.otus.example.springmail_integration_demo.repositories.AppUserRepository; + +@RequiredArgsConstructor +@Service +public class ActivityStatCalculationEmitterSerivce { + private static final String EMPTY_EXT_INFO = "none"; + + private final ActivityTypeRepository activityTypeRepository; + private final AppUserRepository appUserRepository; + private final ActivityStatGateway activityStatGateway; + + @Scheduled(initialDelay = 3000, fixedRate = 10000) + public void emitAppUserActivityStatCalculation(){ + activityStatGateway.calcActivityStat(EMPTY_EXT_INFO); + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityEmitterService.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityEmitterService.java new file mode 100644 index 00000000..9b7d067a --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityEmitterService.java @@ -0,0 +1,32 @@ +package ru.otus.example.springmail_integration_demo.services; + +import lombok.RequiredArgsConstructor; +import lombok.val; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import ru.otus.example.springmail_integration_demo.integration.UserActivityGateway; +import ru.otus.example.springmail_integration_demo.models.UserActivity; +import ru.otus.example.springmail_integration_demo.repositories.ActivityTypeRepository; +import ru.otus.example.springmail_integration_demo.repositories.AppUserRepository; + +import java.util.Random; + +@RequiredArgsConstructor +@Service +public class UserActivityEmitterService { + private final ActivityTypeRepository activityTypeRepository; + private final AppUserRepository appUserRepository; + private final UserActivityGateway userActivityGateway; + + @Scheduled(initialDelay = 2000, fixedRate = 3000) + public void emitAppUserActivity(){ + val random = new Random(); + val activityTypes = activityTypeRepository.findAll(); + val appUsers = appUserRepository.findAll(); + + val activityType = activityTypes.get(random.nextInt(activityTypes.size())); + val appUser = appUsers.get(random.nextInt(appUsers.size())); + val appUserActivity = new UserActivity(activityType, appUser); + userActivityGateway.processActivity(appUserActivity, activityType.getName().contains("Вредн")); + } +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformer.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformer.java new file mode 100644 index 00000000..4cd676b5 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformer.java @@ -0,0 +1,8 @@ +package ru.otus.example.springmail_integration_demo.services; + +import org.springframework.mail.SimpleMailMessage; +import ru.otus.example.springmail_integration_demo.models.UserActivity; + +public interface UserActivityToEmailTransformer { + SimpleMailMessage transform(UserActivity activity); +} diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformerImpl.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformerImpl.java new file mode 100644 index 00000000..1576776e --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/UserActivityToEmailTransformerImpl.java @@ -0,0 +1,25 @@ +package ru.otus.example.springmail_integration_demo.services; + +import lombok.RequiredArgsConstructor; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.stereotype.Service; +import ru.otus.example.springmail_integration_demo.config.AppProps; +import ru.otus.example.springmail_integration_demo.models.UserActivity; + +@RequiredArgsConstructor +@Service +public class UserActivityToEmailTransformerImpl implements UserActivityToEmailTransformer { + + private final AppProps appProps; + + @Override + public SimpleMailMessage transform(UserActivity activity) { + SimpleMailMessage mailMessage = new SimpleMailMessage(); + mailMessage.setTo(appProps.getAdminEmail()); + mailMessage.setFrom(appProps.getServerEmail()); + mailMessage.setSubject("Обнаружена вредная активность"); + mailMessage.setText(String.format("Внимание!!! Обнаружена вредная активность! Время: %s, пользователь: %s, тип активности: %s", + activity.getActivityTime(), activity.getAppUser().getName(), activity.getType().getName())); + return mailMessage; + } +} diff --git a/examples/spring-mail-integration-demo/src/main/resources/application.yml b/examples/spring-mail-integration-demo/src/main/resources/application.yml new file mode 100644 index 00000000..8f2e0d52 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/resources/application.yml @@ -0,0 +1,34 @@ +app: + admin-email: ${admin.email} + server-email: ${admin.email} + +spring: + datasource: + initialization-mode: always + + jpa: + generate-ddl: false + hibernate: + ddl-auto: none + show-sql: true + + mail: + host: smtp.mail.ru + port: 465 + username: ${email.server.user} + password: ${email.server.password} + protocol: smtps + properties: + mail: + smtp: + auth: true + starttls.enable: true + +management: + endpoints: + web: + exposure: + include: health, info, activity-stat + endpoint: + health: + show-details: always \ No newline at end of file diff --git a/examples/spring-mail-integration-demo/src/main/resources/data.sql b/examples/spring-mail-integration-demo/src/main/resources/data.sql new file mode 100644 index 00000000..6ab9b209 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/resources/data.sql @@ -0,0 +1,16 @@ +insert into app_users(name, email) values ('Рафаель Губерманович Тыгыдым', 'test@mail.ru') +insert into app_users(name, email) values ('Артем Демосфенович Шмяк', 'test@mail.ru') +insert into app_users(name, email) values ('Ифигения Бореславовна Фуфелшмерц', 'test@mail.ru') + +insert into activity_types(name) values ('Очень полезное дело №4') +insert into activity_types(name) values ('Очень полезное дело №13') +insert into activity_types(name) values ('Очень полезное дело №34') +insert into activity_types(name) values ('Очень полезное дело №48') +insert into activity_types(name) values ('Очень полезное дело №53') +insert into activity_types(name) values ('Вредное дело №11') +insert into activity_types(name) values ('Вредное дело №12') +insert into activity_types(name) values ('Вредное дело №13') +insert into activity_types(name) values ('Вредное дело №14') +insert into activity_types(name) values ('Вредное дело №15') +insert into activity_types(name) values ('Вредное дело №16') + diff --git a/examples/spring-mail-integration-demo/src/main/resources/schema.sql b/examples/spring-mail-integration-demo/src/main/resources/schema.sql new file mode 100644 index 00000000..c0f9ebe8 --- /dev/null +++ b/examples/spring-mail-integration-demo/src/main/resources/schema.sql @@ -0,0 +1,8 @@ +create table activity_types (id bigint auto_increment, name varchar(255), primary key (id)) +create table app_users (id bigint auto_increment, email varchar(255), name varchar(255), primary key (id)) + +create table app_users_activity (id bigint auto_increment, activity_time timestamp, app_user_id bigint, activity_type_id bigint, primary key (id)) +alter table app_users_activity add constraint app_users_activity_user_id_fk foreign key (app_user_id) references app_users +alter table app_users_activity add constraint app_users_activity_activity_type_id_fk foreign key (activity_type_id) references activity_types + +create table activity_stat (id bigint auto_increment, app_user_name varchar(255), activity_type varchar(255), activities_count bigint, primary key (id))