DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Java, Spring Boot, and MongoDB: Performance Analysis and Improvements
  • Spring Boot Secured By Let's Encrypt
  • How To Build Web Service Using Spring Boot 2.x

Trending

  • Docker Model Runner: Streamlining AI Deployment for Developers
  • A Guide to Developing Large Language Models Part 1: Pretraining
  • It’s Not About Control — It’s About Collaboration Between Architecture and Security
  • Mastering Fluent Bit: Installing and Configuring Fluent Bit on Kubernetes (Part 3)
  1. DZone
  2. Software Design and Architecture
  3. Microservices
  4. A Practical Guide to Creating a Spring Modulith Project

A Practical Guide to Creating a Spring Modulith Project

Spring Modulith simplifies modular app development in Spring Boot and enables well-structured, domain-driven design with seamless Spring ecosystem integration.

By 
RENJITH RAMACHANDRAN user avatar
RENJITH RAMACHANDRAN
·
Jan. 22, 25 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
6.5K Views

Join the DZone community and get the full member experience.

Join For Free

Spring Modulith empowers developers to define logical application modules in their code, facilitating the creation of well-structured, domain-aligned Spring Boot applications.

This approach introduces modular design principles to the Spring Framework, providing a more organized way to develop applications. The General Availability (GA) version was released in August 2023, and the current stable version at the time of writing this article is 1.3.1.

Advantages of the Spring Modulith Framework

  • Provides tooling and architecture support to build a Modulith application
  • Encourages bounded context where each module encapsulates specific business functionality
  • Helps to define clear module boundaries
  • Supports direct and event-driven (sync and async) communication between modules
  • Integrates seamlessly with other Spring tools and components like Spring Data, Spring Actuator, Spring Security, etc. 
  • Helps to avoid cyclic dependencies and supports explicit dependencies 
  • Supports testing modules independently or along with other modules

Setting Up the Spring Modulith Project

Prerequisites 

  • Knowledge of Spring Boot
  • Familiarity with Java programming
  • Installed tools: Java SDK, Maven/Gradle, and an IDE (e.g., IntelliJ or Eclipse)

Overview of the Application

The demo application is a Spring Modulith Application that provides User Authentication functionalities like User Registration and Login. It has four modules: Login, UserRegistration, Common, and Notification modules. The application will use H2 DB for persistence.

Module Name
Functionality

Login
The Login module handles user login functionality, comprising a LoginController for APIs, LoginService for login operations, LoginEntity representing the DB table, and LoginRepository as the JPA repository.
UserRegistration
The UserRegistration module handles UserRegistration functionality comprising a UserRegistrationController for APIs,  UserRegistrationService for user registration operations, UserEntity and UserRegistrationRepository for JPA functionalities. 
Notification
Notification module is used to receive the notification event from other modules and send the notification.  
Common
Common module exposes functionalities that are common across different modules. 


Step-by-Step Guide

Step 1

Initializing the project using Spring Initializer.

Use Spring Initializer to set up the project https://start.spring.io/ as shown below. 

Use Spring Initializer to set up the project

Figure 1

The following dependencies are added:

Dependency
Description
Spring Modulith
Contains packages to build modular monolith Application
H2 Database
Demo will be using H2 Db for persistence
Spring Data JPA
Package for Java Persistence API
Lombok
Package helps with boilerplate code, especially generating getters and setters
Spring Web
Package to build Rest APIs


Download the file and open it in the IDE of your choice. 

Step 2

Create the packages for the modules defined. The packages should be defined at the same level as the SpringBoot application. 

The structure of the code

Figure 2

Figure 2 above shows the structure of the code. Modules common, login, notification, and userregistration are created at the same level as the main class, which loads the Spring Boot application. Spring Modulith identifies them as modules through the package structure.

Step 3

Create the ModularityTest class, which will have test cases to test whether the Modulith application is built in accordance with the Modulith standards. Spring Modulith provides ApplicationModules class that provides verify() method to ascertain whether the application is built in accordance with Spring Modulith constraints.  It also provides utilities to create documentation. Thus, Spring Modulith provides a toolkit to check compliance with the Modulith structure and create documentation for the modules.

Java
 
package com.dzone.demo.userauthentication;


import org.junit.jupiter.api.Test;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.docs.Documenter;

public class ModularityTest {

    @Test
    public void applicationModules() {
       ApplicationModules modules = ApplicationModules.of(UserauthenticationApplication.class);
        modules.forEach(System.out::println);
        modules.verify();

    }

    @Test
    void createDocumentation(){
        ApplicationModules modules = ApplicationModules.of(UserauthenticationApplication.class);
        new Documenter(modules).writeDocumentation();
    }
}


Step 4

Once the project structure has been created, create the controller, repository, or entities specific to the module. Usually,  classes in Spring Boot are defined with a public access modifier. In a Modulith architecture, a module exposes only limited classes that other modules can consume.

In Figure 3 below, only the LoginService class is public. All other classes have a default access modifier so that only classes within the module can access it. This prevents classes from other modules to Autowire it. In the example below, LoginDTO is a class that is not defined at the root level of the module(login) but needs to be accessed by the UserRegistrationModule. In that case, use @NamedInterface annotation to expose the class for other modules to consume. The access modifier should be public.

Only the LoginService class is public

Figure 3


Java
 
@NamedInterface("LoginDTO")
public class LoginDTO {


Step 5

Run a modularity test after all the modules have been defined. It produces a result as shown below.

Java
 
# Common
> Logical name: common
> Base package: com.dzone.demo.userauthentication.common
> Named interfaces:
  + NamedInterface: name=<<UNNAMED>>, types=[]
  + NamedInterface: name=common-events, types=[ c.d.d.u.c.e.UserRegisteredEvent ]
  + NamedInterface: name=common-validator, types=[ c.d.d.u.c.v.EmailValidator ]
> Spring beans:
  o ….util.TimeUtil
  + ….validator.EmailValidator

# Login
> Logical name: login
> Base package: com.dzone.demo.userauthentication.login
> Named interfaces:
  + NamedInterface: name=<<UNNAMED>>, types=[ c.d.d.u.l.LoginEntity, c.d.d.u.l.LoginService ]
  + NamedInterface: name=LoginDTO, types=[ c.d.d.u.l.c.LoginDTO ]
> Spring beans:
  o ….LoginRepository
  + ….LoginService
  o ….controller.LoginController

# Userregistration
> Logical name: userregistration
> Base package: com.dzone.demo.userauthentication.userregistration
> Spring beans:
  o ….controller.UserAuthenticationController
  o ….domain.UserRegistrationRepository
  o ….domain.UserRegistrationService

# Notification
> Logical name: notification
> Base package: com.dzone.demo.userauthentication.notification
> Named interfaces:
  + NamedInterface: name=<<UNNAMED>>, types=[]
  + NamedInterface: name=NotificationService, types=[ c.d.d.u.n.d.NotificationService ]
> Spring beans:
  + ….domain.NotificationService

Elements
Explanation
Logical name
Name of the module
Base Package
The base package of the module
Named interfaces
It lists all the Named Interfaces as explained above
Spring beans
It lists all the Spring Beans. All classes having @Controller , @Service , @Repository, @Component will be listed in Spring beans section


Step 6

Instead of using @NamedInterface at each class level, package-info.java can be used to expose classes in a package. As shown in Figure 4 below, classes inside the validator package are exposed using package-info.java.

Java
 
@org.springframework.modulith.NamedInterface("common-validator")
package com.dzone.demo.userauthentication.common.validator;


package-info.java can be used to confine access to a module. It can also be used to make a module accessible to all. 

The following code snippet at the module level will allow the module to have dependencies with only a set of modules or named interfaces, as shown. 

Java
 
allowedDependencies = {"login::LoginService","login::LoginDTO","common::common-validator","notification::NotificationService","common::common-events"}


The following code snippet would make the module and its classes accessible for all other modules. 

Java
 
@org.springframework.modulith.ApplicationModule(
        type = ApplicationModule.Type.OPEN
)


UserRegistrationService in the UserRegistration module can access the functions exposed by LoginService in the Login module by auto-wiring the service. The same is applicable to EmailValidator class in the commons module. Only classes exposed explicitly are accessible by the UserRegistration module. 

Java
 
    private LoginService loginService;
    private UserRegistrationRepository userRegistrationRepository;
    private EmailValidator emailValidator;

    UserRegistrationService(@Autowired LoginService loginService, @Autowired EmailValidator emailValidator, @Autowired UserRegistrationRepository userRegistrationRepository) {  
        this.userRegistrationRepository = userRegistrationRepository;
        this.emailValidator = emailValidator;
        this.loginService = loginService;
    }


Thus, the above examples show how to set up, package, and test a Spring Modulith application. The code for the application can be found in the following link.

Conclusion

Spring Modulith is a valuable addition to the Spring ecosystem, providing utilities to build a Modulith application following domain-driven design principles. Being part of the Spring ecosystem enables seamless integration with other Spring modules. A Modulith application serves as an excellent middle ground between Monolith and Microservices architectures, and Spring Modulith offers the necessary toolkit to build a robust and efficient solution.

Spring Framework application Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Java, Spring Boot, and MongoDB: Performance Analysis and Improvements
  • Spring Boot Secured By Let's Encrypt
  • How To Build Web Service Using Spring Boot 2.x

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: