This project aims to demonstrate how Spring Modulith can be used to create a modular, maintainable architecture by ensuring small, self-contained modules without unnecessary package dependencies. The goal is to improve cohesion and reduce coupling, while leveraging event-driven design patterns and architectural best practices.
- Spring Modulith: Helps maintain modularity by abstracting architectural patterns, such as the Outbox Pattern, to handle event-driven communication efficiently without introducing tight coupling between modules.
- Event Sourcing: Ensures all state changes are captured as immutable events, allowing for a more resilient, traceable, and auditable system.
- Apache Kafka: Acts as the core message broker, enabling reliable and scalable communication between different modules.
- Spring Security: Secures the service by enforcing authentication and authorization for all actions performed within the system.
- Spring MVC: Exposes RESTful endpoints to manage and interact with orders and other core domain functionalities.
- Spring Data JPA: Simplifies data persistence and retrieval, working seamlessly with the event sourcing approach.
- Docker Compose: Provides an easy-to-deploy environment with all necessary services, including Kafka and PostgreSQL, making the project ready for local development and testing.
This project contains a Docker Compose file named compose.yaml. In this file, the following services have been defined:
- PostgreSQL:
postgres:latest - Kafka:
bitnami/kafka:latest - AKHQ (Kafka GUI):
tchiotludo/akhq:latest - Tempo (Distributed tracing backend)
- Tempo (Distributed tracing backend with Zipkin-compatible ingest exposed on
localhost:9412) - Prometheus (Metrics)
- Grafana (Dashboards)
- Loki + Promtail (Centralised log aggregation and forwarding to Grafana)
Note: Please review the tags of the used images and set them to the same versions as those running in production to ensure consistency.
Clone this repository into a new project folder (e.g., base-payments).
git clone https://github.com/DanielMachadoVasconcelos/base-payments.git
cd base-paymentsStart the external resources by running the Docker Compose file.
Note: This step is optional, since the spring boot applications will start the necessary resources automatically
docker-compose up -dTo run the application, you can use the following command:
./gradlew bootRunThis command will start the application on port 8080 by default.
When the Docker Compose observability stack is running, the service automatically forwards structured logs to Loki via the com.github.loki4j:loki-logback-appender. The default push URL is http://localhost:3100/loki/api/v1/push; override it as needed:
LOKI_URL=http://localhost:3100/loki/api/v1/push ./gradlew bootRunWith Grafana, Loki, Tempo running you can:
- Explore metrics via the
HTTP Requests Monitoringdashboard. - Monitor end-to-end service health with the imported
Spring Boot Observabilitydashboard (Grafana ID17175), provisioned automatically underDashboards → Spring Boot Observability. - View correlated logs in Grafana Explore (
Lokidatasource) – log lines embed bothcorrelationIdandtraceId. - Jump from a log line to a trace (derived field on
traceId) or search recent traces via the Tempo datasource (spans are exported to Tempo through its Zipkin-compatible endpoint exposed onlocalhost:9412).
You can test the application by sending HTTP requests to the exposed endpoints. The application provides the following endpoints:
POST /api/orders: Creates a new orderGET /api/orders/{id}: Retrieves an order by its IDGET /api/orders: Retrieves all ordersPUT /api/orders/{id}/cancel: Cancels an order by its IDPUT /api/orders/{id}/complete: Completes an order by its IDPOST /api/orders/{id}/items: Adds an item to an order by its IDDELETE /api/orders/{id}/items/{itemId}: Removes an item from an order by its ID and item IDGET /api/orders/{id}/events: Retrieves all events for an order by its IDGET /api/orders/{id}/events/{eventId}: Retrieves a specific event for an order by its ID and event ID
curl --location --request POST 'localhost:5000/v1/orders' \
--header 'Content-Type: application/json' \
--data-raw '{
"currency": "USD",
"amount": 3500
}'Note: Access the local url (localhost:5050) in your favorite browser to verify the Postgres Database Admin UI.
Use the following credentials:
| username | password |
|---|---|
| admin@admin.com | admin |
Or access the database using the following command:
PGPASSWORD=password psql -U user -h localhost ordersNote: Access the local url (localhost:8080) in your favorite browser to verify the Kafka GUI.
Look for the following topics:
orders-events.v1.topic
For further reference, please consider the following sections:
- Official Gradle Documentation
- Spring Boot Gradle Plugin Reference Guide
- Create an OCI Image
- Docker Compose Support
- Spring Modulith
- Spring for Apache Kafka
- Spring Boot DevTools
- Spring Configuration Processor
- Spring Web
- Spring Data JPA
The following guides illustrate how to use some features concretely: