Example Java DDD/CQRS/Event Sourcing microservices with Quarkus, Spring Boot and the EventStore from Greg Young. The code uses the lightweight ddd-4-java and cqrs-4-java libaries. No special framework is used except the well known JEE/Spring standards.
This application shows how to implement DDD, CQRS and Event Sourcing without a DDD/CQRS framework. It uses just a few small libraries in addition to standard web application frameworks like Quarkus and Spring Boot.
If you are new to the DDD/CQRS topic, you can use these mindmaps to find out more:
Here is an overview of how such an application looks like:
- Shared - Common code for all demo applications (commands, events, value objects and utilities).
- Aggregates - DDD related code for all demo applications (aggregates, entities and business exceptions).
- Quarkus - Two microservices (Command & Query) based on Quarkus.
- Spring Boot - Two microservices (Command & Query) based on Spring Boot.
The following instructions are tested on Linux (Ubuntu 22)
CAUTION: Building and running on Windows will require some (small) changes.
Make sure you have the following tools installed/configured:
- git (VCS)
- Docker CE
- Docker Compose
- OPTIONAL GraalVM
- Hostname should be set in /etc/hosts (See Find and Change Your Hostname in Ubuntu for more information)
- Clone the git repository
git clone https://github.com/fuinorg/ddd-cqrs-4-java-example.git
- Change into the project's directory and run a Maven build
Be patient - This may take a while (~5 minutes) as all dependencies and some Docker images must be downloaded and also some integration tests will be executed.
cd ddd-cqrs-4-java-example ./mvnw install
Change into the project's directory and run Docker Compose
cd ddd-cqrs-4-java-example
docker-compose up
Start one query service and then one command service. You can mix Quarkus & Spring Boot if you want to!
- Start the Quarkus query service:
cd ddd-cqrs-4-java-example/quarkus/query ./mvnw quarkus:dev
- Opening http://localhost:8080/ should show the query welcome page
For more details see quarkus/query.
- Start the Quarkus command service:
cd ddd-cqrs-4-java-example/quarkus/command ./mvnw quarkus:dev
- Opening http://localhost:8081/ should show the command welcome page
For more details see quarkus/command.
- Start the Spring Boot query service:
cd ddd-cqrs-4-java-example/spring-boot/query ./mvnw spring-boot:run
- Opening http://localhost:8080/ should show the query welcome page
For more details see spring-boot/query.
- Start the Spring Boot command service:
cd ddd-cqrs-4-java-example/spring-boot/command ./mvnw spring-boot:run
- Opening http://localhost:8081/ should show the command welcome page
For more details see spring-boot/command.
- Open http://localhost:2113/ to access the event store UI (User: admin / Password: changeit) You should see a projection named "qry-person-stream" when you click on "Projections" in the top menu.
- Opening http://localhost:8080/persons should show an empty JSON array
Change into the demo directory and execute the command using cURL (See shell script and JSON files with commands in demo)
cd ddd-cqrs-4-java-example/demo
./create-persons.sh
Command service (Console window 3) should show something like
Update aggregate: id=PERSON 954177c4-aeb7-4d1e-b6d7-3e02fe9432cb, version=-1, nextVersion=0
Update aggregate: id=PERSON 568df38c-fdc3-4f60-81aa-d3cce9ebfd7b, version=-1, nextVersion=0
Update aggregate: id=PERSON 84565d62-115e-4502-b7c9-38ad69c64b05, version=-1, nextVersion=0
Query service (Console window 2) should show something like
Handle PersonCreatedEvent: Person 'Harry Osborn' (954177c4-aeb7-4d1e-b6d7-3e02fe9432cb) was created
Handle PersonCreatedEvent: Person 'Mary Jane Watson' (568df38c-fdc3-4f60-81aa-d3cce9ebfd7b) was created
Handle PersonCreatedEvent: Person 'Peter Parker' (84565d62-115e-4502-b7c9-38ad69c64b05) was created
- Refreshing http://localhost:8080/persons should show
[ { "id": "568df38c-fdc3-4f60-81aa-d3cce9ebfd7b", "name": "Mary Jane Watson" }, { "id": "84565d62-115e-4502-b7c9-38ad69c64b05", "name": "Peter Parker" }, { "id": "954177c4-aeb7-4d1e-b6d7-3e02fe9432cb", "name": "Harry Osborn" } ]
- Opening http://localhost:8080/persons/84565d62-115e-4502-b7c9-38ad69c64b05 should show
{"id":"84565d62-115e-4502-b7c9-38ad69c64b05","name":"Peter Parker"}
- The event sourced data of the person aggregate could be found in a stream named PERSON-84565d62-115e-4502-b7c9-38ad69c64b05
Change into the demo directory and execute the command using cURL (See shell script and JSON files with commands in demo)
cd ddd-cqrs-4-java-example/demo
./delete-harry-osborn.sh
- Refreshing http://localhost:8080/persons should show
"Harry Osborn" should no longer be present in the list.
[ { "id": "568df38c-fdc3-4f60-81aa-d3cce9ebfd7b", "name": "Mary Jane Watson" }, { "id": "84565d62-115e-4502-b7c9-38ad69c64b05", "name": "Peter Parker" } ]
- Stop Docker Compose (Ubuntu shortcut = ctrl c)
- Remove Docker Compose container
docker-compose rm