From ad6ed2cb14fd2f44690e92b067825556bec414cc Mon Sep 17 00:00:00 2001 From: Hamid Reza Sharifi Date: Sat, 22 Apr 2023 23:33:54 +0330 Subject: [PATCH] Bael 6361: Introduction to Spring Modulith (#13891) --- .../spring-boot-libraries-2/pom.xml | 21 ++++++++++ .../com/baeldung/modulith/Application.java | 21 ++++++++++ .../notification/NotificationDTO.java | 39 +++++++++++++++++ .../notification/NotificationService.java | 42 +++++++++++++++++++ .../notification/internal/Notification.java | 37 ++++++++++++++++ .../internal/NotificationType.java | 5 +++ .../modulith/product/ProductService.java | 26 ++++++++++++ .../modulith/product/internal/Product.java | 38 +++++++++++++++++ .../ApplicationModularityUnitTest.java | 27 ++++++++++++ 9 files changed, 256 insertions(+) create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/Application.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationDTO.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationService.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/Notification.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/NotificationType.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/ProductService.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/internal/Product.java create mode 100644 spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/modulith/ApplicationModularityUnitTest.java diff --git a/spring-boot-modules/spring-boot-libraries-2/pom.xml b/spring-boot-modules/spring-boot-libraries-2/pom.xml index 4409db0672..6d9401f4bc 100644 --- a/spring-boot-modules/spring-boot-libraries-2/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-2/pom.xml @@ -11,6 +11,18 @@ 1.0.0-SNAPSHOT + + + + org.springframework.experimental + spring-modulith-bom + 0.5.1 + import + pom + + + + org.springframework.boot @@ -87,6 +99,15 @@ 2.34.0 test + + org.springframework.experimental + spring-modulith-api + + + org.springframework.experimental + spring-modulith-starter-test + test + diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/Application.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/Application.java new file mode 100644 index 0000000000..a8c3e48661 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/Application.java @@ -0,0 +1,21 @@ +package com.baeldung.modulith; + +import com.baeldung.modulith.product.ProductService; +import com.baeldung.modulith.product.internal.Product; +import org.jobrunr.autoconfigure.JobRunrAutoConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@EnableAsync +@SpringBootApplication +@EnableAutoConfiguration(exclude = { JobRunrAutoConfiguration.class}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args) + .getBean(ProductService.class) + .create(new Product("baeldung", "course", 10)); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationDTO.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationDTO.java new file mode 100644 index 0000000000..a8fb346daa --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationDTO.java @@ -0,0 +1,39 @@ +package com.baeldung.modulith.notification; + +import java.util.Date; + +public class NotificationDTO { + private Date date; + private String format; + private String productName; + + public NotificationDTO(Date date, String format, String productName) { + this.date = date; + this.format = format; + this.productName = productName; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } +} diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationService.java new file mode 100644 index 0000000000..7789798bbe --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/NotificationService.java @@ -0,0 +1,42 @@ +package com.baeldung.modulith.notification; + +import com.baeldung.modulith.notification.internal.Notification; +import com.baeldung.modulith.notification.internal.NotificationType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.modulith.ApplicationModuleListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +public class NotificationService { + + private static final Logger LOG = LoggerFactory.getLogger(NotificationService.class); + + public void createNotification(NotificationDTO notificationDTO) { + Notification notification = toEntity(notificationDTO); + LOG.info("Received notification by module dependency for product {} in date {} by {}.", notification.getProductName() + , notification.getDate(), notification.getFormat()); + } + + @Async + @ApplicationModuleListener + public void notificationEvent(NotificationDTO event) { + Notification notification = toEntity(event); + LOG.info("Received notification by event for product {} in date {} by {}.", notification.getProductName() + , notification.getDate(), notification.getFormat()); + } + + private Notification toEntity(NotificationDTO notificationDTO) { + Notification notification = new Notification(); + notification.setDate(notificationDTO.getDate()); + if (notificationDTO.getFormat().equals("SMS")) { + notification.setFormat(NotificationType.SMS); + } + if (notificationDTO.getFormat().equals("EMAIL")) { + notification.setFormat(NotificationType.EMAIL); + } + notification.setProductName(notificationDTO.getProductName()); + return notification; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/Notification.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/Notification.java new file mode 100644 index 0000000000..0b1ce85d26 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/Notification.java @@ -0,0 +1,37 @@ +package com.baeldung.modulith.notification.internal; + +import java.util.Date; + +public class Notification { + private Date date; + private NotificationType format; + private String productName; + + public Notification() { + + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public NotificationType getFormat() { + return format; + } + + public void setFormat(NotificationType format) { + this.format = format; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } +} diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/NotificationType.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/NotificationType.java new file mode 100644 index 0000000000..45870e52b9 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/notification/internal/NotificationType.java @@ -0,0 +1,5 @@ +package com.baeldung.modulith.notification.internal; + +public enum NotificationType { + EMAIL, SMS +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/ProductService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/ProductService.java new file mode 100644 index 0000000000..46d87fc539 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/ProductService.java @@ -0,0 +1,26 @@ +package com.baeldung.modulith.product; + +import com.baeldung.modulith.notification.NotificationDTO; +import com.baeldung.modulith.notification.NotificationService; +import com.baeldung.modulith.product.internal.Product; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class ProductService { + + private final ApplicationEventPublisher events; + private final NotificationService notificationService; + + public ProductService(ApplicationEventPublisher events, NotificationService notificationService) { + this.events = events; + this.notificationService = notificationService; + } + + public void create(Product product) { + notificationService.createNotification(new NotificationDTO(new Date(), "SMS", product.getName())); + events.publishEvent(new NotificationDTO(new Date(), "SMS", product.getName())); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/internal/Product.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/internal/Product.java new file mode 100644 index 0000000000..d989906b63 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/modulith/product/internal/Product.java @@ -0,0 +1,38 @@ +package com.baeldung.modulith.product.internal; + +public class Product { + + private String name; + private String description; + private int price; + + public Product(String name, String description, int price) { + this.name = name; + this.description = description; + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/modulith/ApplicationModularityUnitTest.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/modulith/ApplicationModularityUnitTest.java new file mode 100644 index 0000000000..40d644b1e0 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/modulith/ApplicationModularityUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.modulith; + +import org.junit.jupiter.api.Test; +import org.springframework.modulith.core.ApplicationModules; +import org.springframework.modulith.docs.Documenter; + +class ApplicationModularityUnitTest { + + ApplicationModules modules = ApplicationModules.of(Application.class); + + @Test + void verifiesModularStructure() { + modules.verify(); + } + + @Test + void createModuleDocumentation() { + new Documenter(modules) + .writeDocumentation() + .writeIndividualModulesAsPlantUml(); + } + + @Test + void createApplicationModuleModel() { + modules.forEach(System.out::println); + } +} \ No newline at end of file