Skip to content

Event Sourcing + CQRS + Spring Boot + EventStoreDB + MongoDB + Kotlin

Notifications You must be signed in to change notification settings

mateuszwlosek/event-sourcing-cqrs-example

Repository files navigation

Event Sourcing + CQRS Example

Example of Event Sourcing Pattern with CQRS implemented in Spring Boot with EventStoreDB.

Read model stored in MongoDB.
Used Docker to containerize environment.

Architecture

Architecture

Services

Citizen Command Service

Exposes REST endpoints to create, update, and delete citizens.
The endpoints send EventStoreDB events.

To avoid eventual consistency, currentRevision validation was introduced (this obviously depends on the project use-case).

Sometimes it happens that the connection to EventStoreDB is broken, hence a very simple retry mechanism was implemented.

Citizen Event Handler MongoDB Read Model Service

Consumes EventStoreDB events and updated customers' read models stored in MongoDB.

It is possible to create more services similar to this one, which will handle the data differently, store it in different databases, etc.
It is also possible not to have a read model service at all. If there are not many events per aggregate, it is possible to build a model based on all occurred events from EventStoreDB every time an endpoint is requested.

Citizen Query Service

Exposes REST endpoints to query citizens. Returns a MongoDB Citizen read model data when the read model endpoint is requested, and all the events stored in EventStoreDB when the audit endpoint is requested.

Build and testing

Commands

# Build and run services
$ docker-compose up --build

# Create a citizen
$ curl --location --request POST 'localhost:8081/citizens' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "citizenId": "4jf74jfi84jmf",
    "firstName": "John",
    "lastName": "Smith",
    "address": "Mount Pleasant Gardens 33, London"
    }'

# Update the citizen
$ curl --location --request PUT 'localhost:8081/citizens' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "citizenId": "4jf74jfi84jmf",
    "firstName": "John",
    "lastName": "Smith",
    "address": "Moorfield Alley 15, London"
    }'

# Delete the citizen
$ curl --location --request DELETE 'localhost:8081/citizens?citizenId=4jf74jfi84jmf'

# Get the citizen's read model
$ curl --location --request GET 'localhost:8082/citizens?citizenId=4jf74jfi84jmf'

# Get the citizen's audit
$ curl --location --request GET 'localhost:8082/audit?citizenId=4jf74jfi84jmf'