CQRS Java sample using Helidon and MongoDB
This project demonstrates a CQRS (Command Query Responsibility Segregation) architecture built with:
-
Helidon MicroProfile 3.x — lightweight Java microservices framework
-
MongoDB — document database for persistence
-
Domain-Driven Design (DDD) — aggregates, value objects, domain events, repositories
-
Package-by-feature — each feature is self-contained with its own API, command, query, domain, and infrastructure layers
com.soujava.helidon.cqrs
├── shared/ ← cross-cutting CQRS abstractions
│ ├── command/
│ │ ├── Command.java ← marker interface
│ │ ├── CommandBus.java ← dispatch interface
│ │ ├── CommandHandler.java ← handler interface
│ │ └── SimpleCommandBus.java ← in-process registry-based bus
│ ├── query/
│ │ ├── Query.java
│ │ ├── QueryBus.java
│ │ ├── QueryHandler.java
│ │ └── SimpleQueryBus.java
│ └── domain/
│ ├── AggregateRoot.java ← base class; collects domain events
│ └── DomainEvent.java ← base class for all domain events
│
└── order/ ← "Order" bounded context / feature
├── api/ ← REST resources & DTOs (JAX-RS)
│ ├── OrderResource.java
│ ├── CreateOrderRequest.java
│ └── DomainExceptionMapper.java
├── command/ ← write side
│ ├── CreateOrderCommand.java
│ ├── CreateOrderCommandHandler.java
│ ├── ConfirmOrderCommand.java
│ ├── ConfirmOrderCommandHandler.java
│ ├── CancelOrderCommand.java
│ └── CancelOrderCommandHandler.java
├── query/ ← read side
│ ├── FindOrderByIdQuery.java
│ ├── FindOrderByIdQueryHandler.java
│ ├── FindAllOrdersQuery.java
│ ├── FindAllOrdersQueryHandler.java
│ └── OrderView.java ← read model (separate from domain aggregate)
├── domain/ ← DDD domain model
│ ├── Order.java ← aggregate root
│ ├── OrderId.java ← value object
│ ├── OrderItem.java ← entity
│ ├── OrderStatus.java ← enum value object
│ ├── OrderRepository.java ← repository interface (port)
│ └── event/
│ ├── OrderCreatedEvent.java
│ ├── OrderConfirmedEvent.java
│ └── OrderCancelledEvent.java
├── infrastructure/ ← adapters / persistence
│ ├── MongoClientProducer.java
│ └── MongoOrderRepository.java
└── OrderHandlerRegistrar.java ← wires handlers into buses at startup
| Concept | Where |
|---|---|
Aggregate Root |
|
Value Object |
|
Entity |
|
Domain Event |
|
Repository |
|
Factory method |
|
REST Request
│
▼
OrderResource
│
├─[POST /orders]────────► CommandBus.dispatch(CreateOrderCommand)
│ │
│ ▼
│ CreateOrderCommandHandler
│ │
│ ▼
│ Order.create() → OrderRepository.save()
│
└─[GET /orders/{id}]───► QueryBus.dispatch(FindOrderByIdQuery)
│
▼
FindOrderByIdQueryHandler
│
▼
OrderRepository.findById() → OrderView
| Method | Path | Description |
|---|---|---|
|
|
Place a new order |
|
|
List all orders |
|
|
Get a single order by id |
|
|
Confirm a pending order |
|
|
Cancel an order |
Configuration is provided via src/main/resources/META-INF/microprofile-config.properties:
mongodb.uri=mongodb://localhost:27017
mongodb.database=orders_db
server.port=8080-
Start MongoDB:
docker run -d -p 27017:27017 mongo:7
-
Build and run:
mvn package java -jar target/helidon-mongodb-cqrs-1.0-SNAPSHOT.jar