Command Query Responsibility Segregation (CQRS) Using Event Driven Architecture (EDA) With Spring BOOT + AxonIQ + Async JPA Persistence
The starting point of CQRS design pattern is the notion of differentiating between READ and WRITE model. This design pattern professes if the QUERY capabilities of an application is very different or complex or may be, relational DB are not apt for querying (scalable, performant etc), it's better to separate/segregate query model from write model.
The center stone in implementing CQRS is Event Driven Architecture. In event driven architecture, modules interact with each other using EVENT and each module is independent & not aware of the other. In other words this architecture style enable Location transparency. To re-iterate, a component should neither be aware of nor make any assumptions about the location components it interact with. The module enroll/subscribe to event & take actions. It also help in cutting module dependencies (in pom.xml) and ease out creation of micro-services.
The following picture shows CQRS design pattern build using event driven architecture:
NOTE: Key Concepts Normally Mixed Up
- If QUERY model is not complex, do not go in the direction of CQRS
- EVENT != MESSAGE
- Event Driven != CQRS
- Event is never physically deleted i.e. delete is an another event. This aides in ML and AI e.g. Mr X first purchased Apple iphone and then canceled it and ultimately bought Samsung S9. This information is gold dust for Data Scientist and helps them understand customer purchase behaviour pattern.
In my opinion a monolithic application can be split into micro-services based architecture in following steps:
Step 1. Implement Modularizationi.e. create modules, each module is dedicated to perform single functional responsibility (also termed implementation of separation of concerns)
Step 2. Cut Module inter-dependencies
The Step 2 is very important and is the make or break situation in the endeavour to rollout micro-services based architecture. Event Driven architecture style plays very important part in implementing Step 2. AxonIQ is a nice framework to implement Event Driven programing model in a Domain Driven Design way. Using AxonIQ it's possible to work with root aggregator domain entity (Policy)
EventDrivenMicroServiceUsingAxonIQ mico-serivce is Policy application with:
- Separate WRITE model
- Separate READ model
- Events are stored in embedded AxonIQDB (using async JPA)
- READ is performed using JPA using jpa-eclipselink + Derby
- Inter module interaction can be in JVM interaction or over http or WebSocken etc. AxonIQ routes an event to an Event Bus (which can then be stored in AxonIQDB or Kafka or pumpkin db). The subscriber of an event can either go over http (or any other protocol) to action on the event request.
- Clear separation of domain object from entity (Policy is domain object & PolicyEntity is an entity - see class diagram below)
- Commands and Events are build using Kotlin.
NOTE:
- In above programming style, write needs to fast & asynchronous. JPA vendors does not provide async persistence but using jpa-eclipselink this can be achieved.
- Domain model is not anemic and also there is a clear separation of domain API from entity (persistence mechanism), they are not tightly coupled. This is of great help in creating modularization.
Below is the domain of EventDrivenMicroServiceUsingAxonIQ:
The following picture shows EventDrivenMicroServiceUsingAxonIQ from AxonIQ framework prospective:
- Download & setup jpa-eclipse for async persistence in local maven repo
git clone git@github.com:mgorav/jpa-eclipselink.git
cd jpa-ecliselink
mvn clean install -DskipTests
- Download & setup EventDrivenMicroServiceUsingAxonIQ
git clone git@github.com:mgorav/EvendDrivenMicroServiceUsingAxonIQ.git
cd EvendDrivenMicroServiceUsingAxonIQ
mvn clean install -DskipTests
- Run EventDrivenMicroServiceUsingAxonIQ
java -jar target/EventDrivenMicroServiceUsingAxonIQ-0.0.1-SNAPSHOT.jar
This will run the application on the port 8888. All the APIs exposed can be accessed by opening the swagger ui as shown below:
http://localhost:8888/swagger-ui.html
cf push target/EvendDrivenMicroServiceUsingAxonIQ-0.0.1-SNAPSHOT.jar
Access URL - https://eventdrivenmicroserviceusingaxoniq.cfapps.io/swagger-ui.html
In compositional micro-services based architecture, think EVENT based inter module interactions. This make each micro-service independent of each other. This helps in rolling out new functionality as micro-service fast. Also this architecture & programing style aides in building serverless micro-services or function as service. At the end it's all about how business functionality can be taken to production as fast as possible.