A comprehensive reference implementation of Command Query Responsibility Segregation (CQRS) and Event Sourcing patterns using Spring Boot 3 and Java 21.
This project demonstrates how to implement CQRS and Event Sourcing in a modern Spring Boot application. It includes:
- Domain-Driven Design with aggregates and domain events
- Event Sourcing for persisting state changes as events
- CQRS with separate command and query models
- Event-driven architecture with event handlers for projections
- REST API for commands and queries
- Complete order management example domain
-
Domain Layer
AggregateRoot
: Base class for aggregates with event sourcing capabilitiesDomainEvent
: Base class for all domain eventsOrder
: Example aggregate implementing business logic
-
Command Side (Write Model)
- Commands:
CreateOrderCommand
,AddOrderItemCommand
, etc. - Command Handlers: Process commands and interact with aggregates
- Event Store: Persists domain events
- Commands:
-
Query Side (Read Model)
- Projections: Denormalized views optimized for queries
- Event Handlers: Update projections when events occur
- Query Services: Provide read access to projections
-
Infrastructure
EventStore
: Interface for event persistenceJpaEventStore
: JPA implementation of event storeAggregateRepository
: Repository for loading/saving aggregates
- Java 21
- Maven 3.8+
mvn spring-boot:run
The application will start on http://localhost:8080
Access the H2 console at http://localhost:8080/h2-console
- JDBC URL:
jdbc:h2:mem:eventstore
- Username:
sa
- Password: (empty)
POST /api/orders
Content-Type: application/json
{
"customerName": "John Doe"
}
POST /api/orders/{orderId}/items
Content-Type: application/json
{
"productName": "Laptop",
"quantity": 2,
"unitPrice": 999.99
}
POST /api/orders/{orderId}/confirm
POST /api/orders/{orderId}/cancel
GET /api/orders/{orderId}
GET /api/orders
GET /api/orders?customerName=John&status=CONFIRMED
- Create an order:
curl -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"customerName": "John Doe"}'
- Add items to the order:
curl -X POST http://localhost:8080/api/orders/{orderId}/items \
-H "Content-Type: application/json" \
-d '{"productName": "Laptop", "quantity": 1, "unitPrice": 1200.00}'
- Confirm the order:
curl -X POST http://localhost:8080/api/orders/{orderId}/confirm
- Query the order:
curl http://localhost:8080/api/orders/{orderId}
Run the tests with:
mvn test
The project includes:
- Unit tests for domain logic
- Integration tests for the complete flow
- API tests for REST endpoints
- All state changes are stored as immutable events
- Aggregates can be reconstructed from their event history
- Complete audit trail of all changes
- Temporal queries and debugging capabilities
- Separate models for commands (writes) and queries (reads)
- Optimized read models for different query patterns
- Independent scaling of read and write sides
- Event-driven synchronization between models
- Rich domain models with business logic
- Aggregates enforce consistency boundaries
- Domain events capture business-significant occurrences
- Clear separation of concerns
src/main/java/com/example/cqrs/
├── api/ # REST controllers and DTOs
├── command/ # Command side (write model)
│ └── order/ # Order commands and handlers
├── domain/ # Domain layer
│ └── order/ # Order aggregate and events
├── infrastructure/ # Infrastructure concerns
├── query/ # Query side (read model)
│ └── order/ # Order projections and queries
└── CqrsEventSourcingApplication.java
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.