Spring Modulith
===============
https://github.com/spring-boot-tutorials/spring-modulith
In this article we will configure Spring Modulith.
Create Initial Code Base
------------------------
- Go to https://start.spring.io/
- Add the following dependencies:
- spring-modulith-starter-core
- spring-boot-starter-web
- lombok
- Click `Generate`
Dependencies
------------
Dependencies used in ``pom.xml``
.. code-block:: xml
org.springframework.boot
spring-boot-starter-web
org.springframework.modulith
spring-modulith-starter-core
org.projectlombok
lombok
true
Modulith #1 - POJO
------------------
Let's create a new POJO ``src/main/java/com/example/spring_modulith/module_notification/NotificationDTO.java``
.. code-block:: java
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class NotificationDTO {
private String productName;
private String format;
private Date date;
}
Modulith #1 - Service
---------------------
Create a new file ``src/main/java/com/example/spring_modulith/module_notification/NotificationService.java``:
.. code-block:: java
@Service
public class NotificationService {
private static final Logger LOG = LoggerFactory.getLogger(NotificationService.class);
public void createNotification(NotificationDTO notification) {
LOG.info("Received notification by module DEPENDENCY for product {} in date {} by {}.",
notification.getProductName(),
notification.getDate(),
notification.getFormat());
}
// TODO doesn't work
@ApplicationModuleListener
public void notificationEvent(NotificationDTO event) {
LOG.info("Received notification by EVENT for product {} in date {} by {}.",
event.getProductName(),
event.getDate(),
event.getFormat());
}
}
Modulith #1 - Internal - POJO
-----------------------------
Create a new POJO class ``src/main/java/com/example/spring_modulith/module_notification/internal/Notification.java``:
.. code-block:: java
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class Notification {
private String productName;
private NotificationType format;
private Date date;
}
And another POJO class ``src/main/java/com/example/spring_modulith/module_notification/internal/NotificationType.java``:
.. code-block:: java
public enum NotificationType {
SMS
}
Modulith #2 - Service
---------------------
Create new file ``src/main/java/com/example/spring_modulith/module_product/ProductService.java``:
.. code-block:: java
@Service
@RequiredArgsConstructor
public class ProductService {
private final ApplicationEventPublisher events;
private final NotificationService notificationService;
public void create(Product product) {
notificationService.createNotification(new NotificationDTO(product.getName(), "SMS", new Date()));
events.publishEvent(new NotificationDTO(product.getName(), "SMS", new Date()));
}
}
Modulith #2 - Internal - POJO
-----------------------------
Create new POJO class ``src/main/java/com/example/spring_modulith/module_product/internal/Product.java``:
.. code-block:: java
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class Product {
private String name;
private String description;
private int price;
}
Main
----
Modify ``MainApplication.java``:
.. code-block:: java
@EnableAsync
@SpringBootApplication
public class SpringModulithApplication {
public static void main(String[] args) {
SpringApplication.run(SpringModulithApplication.class, args)
.getBean(ProductService.class)
.create(new Product("marcus", "description", 100));
}
}
Create Tests
------------
Create new file ``src/test/java/com/example/spring_modulith/SpringModulithApplicationTests.java``:
.. code-block:: java
@SpringBootTest
class SpringModulithApplicationTests {
@Test
void createApplicationModuleModel() {
ApplicationModules modules = ApplicationModules.of(SpringModulithApplication.class);
modules.forEach(System.out::println);
}
@Test
void verifiesModularStructure() {
ApplicationModules modules = ApplicationModules.of(SpringModulithApplication.class);
modules.verify();
}
@Test
void createModuleDocumentation() {
ApplicationModules modules = ApplicationModules.of(SpringModulithApplication.class);
new Documenter(modules)
.writeDocumentation()
.writeIndividualModulesAsPlantUml();
}
}
Run & Verify Tests
------------------
Open terminal at project root and execute the following:
.. code-block:: sh
mvn clean package