A learning-focused project demonstrating a modern Spring Boot backend using Domain-Driven Design (DDD) principles, Spring Modulith, and Hypermedia-driven (HATEOAS) API design.
The goal of this repository is to explore how to build evolution-ready systems by focusing on deep domain modeling and strict architectural boundaries.
- Java 25: Leveraging the latest language features.
- Spring Boot 4.0: Core framework.
- Spring Modulith: For building and verifying modular monolith structures.
- jMolecules: To express DDD concepts (Aggregates, Value Objects) in code.
- Spring Data REST & HATEOAS: For a true Level 3 REST maturity API.
- Flyway: Database migrations.
- PostgreSQL: Primary persistence.
- Project Moneta: Proper handling of
MonetaryAmountand currencies.
The application is organized into logical modules verified by Spring Modulith:
core: Shared infrastructure, Jackson serializers for money, and JPA converters.ingredients: Catalog management of smoothie components.smoothies: Recipe management and pricing logic.orders: Order lifecycle from placement to fulfillment.payment: Payment processing and receipt generation.engine: Background processing simulation (preparing orders).
The API follows HATEOAS principles to guide clients dynamically:
- Affordances: The API exposes valid actions (e.g.,
cancel,pay) based on the current state of the resource. - HAL-FORMS: Provides metadata so clients can discover and render forms without prior knowledge of the fields.
- Curies: Custom documentation links (e.g.,
smoothies:payment) are embedded directly in the JSON responses.
Using jMolecules, the code explicitly defines tactical DDD patterns:
- Aggregates:
Order,Smoothie, andIngredientdefine strict consistency boundaries. - Associations: Aggregates reference each other by ID rather than direct object references, ensuring module isolation.
- Value Objects: Encapsulation of logic in types like
CreditCardNumber.
Strict decoupling is maintained via Spring Modulith Events. When an Order is paid, the payment module publishes an event. The engine module listens to this to start preparation, ensuring the two modules remain unaware of each other's internal logic.
- JDK 25
- Docker (for running PostgreSQL via
docker-compose.yaml)
- Start the database:
docker-compose up -d
- Run the application:
./mvnw spring-boot:run
- Explore the API:
Access the HAL Explorer at
http://localhost:8080/api.
- Check
requests.httpfile - for a full walkthrough of a customer journey (Ordering → Paying → Taking Receipt).