All Projects → ddd-by-examples → All Things Cqrs

ddd-by-examples / All Things Cqrs

Comprehensive guide to a couple of possible ways of synchronizing two states with Spring tools. Synchronization is shown by separating command and queries in a simple CQRS application.

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to All Things Cqrs

Event Sourcing Jambo
An Hexagonal Architecture with DDD + Aggregates + Event Sourcing using .NET Core, Kafka e MongoDB (Blog Engine)
Stars: ✭ 159 (-66.46%)
Mutual labels:  kafka, mongodb, ddd, cqrs, domain-driven-design
Dotnet New Caju
Learn Clean Architecture with .NET Core 3.0 🔥
Stars: ✭ 228 (-51.9%)
Mutual labels:  kafka, mongodb, ddd, cqrs, domain-driven-design
Event Sourcing Castanha
An Event Sourcing service template with DDD, TDD and SOLID. It has High Cohesion and Loose Coupling, it's a good start for your next Microservice application.
Stars: ✭ 68 (-85.65%)
Mutual labels:  kafka, mongodb, ddd, cqrs, domain-driven-design
Eventflow.example
DDD+CQRS+Event-sourcing examples using EventFlow following CQRS-ES architecture. It is configured with RabbitMQ, MongoDB(Snapshot store), PostgreSQL(Read store), EventStore(GES). It's targeted to .Net Core 2.2 and include docker compose file.
Stars: ✭ 131 (-72.36%)
Mutual labels:  mongodb, ddd, cqrs, domain-driven-design
Java Ddd Example
☕🎯 Hexagonal Architecture + DDD + CQRS in a Java project using SpringBoot
Stars: ✭ 119 (-74.89%)
Mutual labels:  spring-boot, ddd, cqrs, domain-driven-design
Kkbinlog
支持mysql、MongoDB数据变更订阅分发
Stars: ✭ 112 (-76.37%)
Mutual labels:  kafka, mongodb, spring-boot, spring
Digital Restaurant
DDD. Event sourcing. CQRS. REST. Modular. Microservices. Kotlin. Spring. Axon platform. Apache Kafka. RabbitMQ
Stars: ✭ 222 (-53.16%)
Mutual labels:  kafka, spring-boot, ddd, cqrs
Hexagonal Architecture Acerola
An Hexagonal Architecture service template with DDD, CQRS, TDD and SOLID using .NET Core 2.0. All small features are testable and could be mocked. Adapters could be mocked or exchanged.
Stars: ✭ 293 (-38.19%)
Mutual labels:  mongodb, ddd, cqrs, domain-driven-design
Event Sourcing Cqrs Examples
Event Sourcing and CQRS in practice.
Stars: ✭ 265 (-44.09%)
Mutual labels:  events, ddd, cqrs, domain-driven-design
Goes
Go Event Sourcing made easy
Stars: ✭ 144 (-69.62%)
Mutual labels:  events, ddd, cqrs, domain-driven-design
Library
This is a project of a library, driven by real business requirements. We use techniques strongly connected with Domain Driven Design, Behavior-Driven Development, Event Storming, User Story Mapping.
Stars: ✭ 2,685 (+466.46%)
Mutual labels:  events, spring, ddd, domain-driven-design
Eventflow
Async/await first CQRS+ES and DDD framework for .NET
Stars: ✭ 1,932 (+307.59%)
Mutual labels:  events, ddd, cqrs, domain-driven-design
Cqrs Clean Eventual Consistency
CQRS, using Clean Architecture, multiple databases and Eventual Consistency
Stars: ✭ 247 (-47.89%)
Mutual labels:  events, mongodb, ddd, cqrs
Plastic
This project provides encapsulation of things like Domain, Application Rules, Business Rules or Business Logic in Application.
Stars: ✭ 30 (-93.67%)
Mutual labels:  cqrs, ddd, domain-driven-design
Clean-Architecture-Template
Configurable Clean Architecture template containing the DDD + CQRS approach for .NET Core applications.
Stars: ✭ 14 (-97.05%)
Mutual labels:  cqrs, ddd, domain-driven-design
Akkatecture
a cqrs and event sourcing framework for dotnet core using akka.net
Stars: ✭ 414 (-12.66%)
Mutual labels:  ddd, cqrs, domain-driven-design
library-php
WIP: A comprehensive Domain-Driven Design example with problem space strategic analysis and various tactical patterns.
Stars: ✭ 73 (-84.6%)
Mutual labels:  events, cqrs, domain-driven-design
typescript-ddd-example
🔷🎯 TypeScript DDD Example: Complete project applying Hexagonal Architecture and Domain-Driven Design patterns
Stars: ✭ 607 (+28.06%)
Mutual labels:  cqrs, ddd, domain-driven-design
CQELight
CQELight is an entreprise grade extensible and customisable framework for creating software with CQRS, DDD & Event Sourcing patterns
Stars: ✭ 21 (-95.57%)
Mutual labels:  events, cqrs, ddd
delta
DDD-centric event-sourcing library for the JVM
Stars: ✭ 15 (-96.84%)
Mutual labels:  cqrs, ddd, domain-driven-design

All Things CQRS

A bunch of ways of doing CQRS with various Spring tools.

Getting Started

These instructions will get you and overview of how to synchronize two different datasources. We will do so by separating command and queries in a simple CQRS app. Each module represents a different way of introducing this pattern. Also, each module is a standalone Spring Boot application.

Prerequisites

What things you need to run the software:

Overview

Sample applications are based on a simple domain that serves credit cards. There are two usecases:

  • Money can be withdrawn from a card (Withdraw command)
  • List of withdrawals from a card can be read (query)

The important is that:

After a successful Withdraw command, a withdrawal should be seen in a result from list of withdrawals query.

Hence there is a need for some synchronization that makes state for commands and queries consistent.

Let's agree on a color code for commands, queries and synchronization. It will make our drawings consistent.

color code

Commands and queries handled in one class (no CQRS)

Code can be found under in-one-class module.

Running the app:

mvn spring-boot:run

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query:

curl http://localhost:8080/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result:

[{"amount":10.00}]

Architecture overview:

in-one-class

Automatic E2E test for REST API can be found here:

    @Test
    public void shouldSynchronizeQuerySideAfterSendingACommand() {
        // given
        UUID cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100)); //HTTP POST
        // when
        clientWantsToWithdraw(TEN, cardUUid); //HTTP GET
        // then
        thereIsOneWithdrawalOf(TEN, cardUUid);
    }

CQRS with application service as explicit synchronization

Code can be found under explicit-with-dto module. Same version, but with JPA entities as results of a query can be found here.

Running the app:

mvn spring-boot:run

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query:

curl http://localhost:8080/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result:

[{"amount":10.00}]

Architecture overview:

application-process

Automatic E2E test for REST API can be found here:

    @Test
    public void shouldSynchronizeQuerySideAfterSendingACommand() {
        // given
        UUID cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100)); //HTTP POST
        // when
        clientWantsToWithdraw(TEN, cardUUid); //HTTP GET
        // then
        thereIsOneWithdrawalOf(TEN, cardUUid);
    }

CQRS with spring application events as implicit synchronization

Code can be found under with-application-events module.

There is also a version with immutable domain module which just returns events. It Can be found here.

Running the app:

mvn spring-boot:run

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query:

curl http://localhost:8080/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result:

[{"amount":10.00}]

Architecture overview:

appevents

Automatic E2E test for REST API can be found here:

    @Test
    public void shouldSynchronizeQuerySideAfterSendingACommand() {
        // given
        UUID cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100)); //HTTP POST
        // when
        clientWantsToWithdraw(TEN, cardUUid); //HTTP GET
        // then
        thereIsOneWithdrawalOf(TEN, cardUUid);
    }

CQRS with trigger as implicit synchronization

Code can be found under trigger module.

Running the app:

mvn spring-boot:run

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query:

curl http://localhost:8080/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result:

[{"amount":10.00}]

Architecture overview:

trigger

Automatic E2E test for REST API can be found here:

    @Test
    public void shouldSynchronizeQuerySideAfterSendingACommand() {
        // given
        UUID cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100)); //HTTP POST
        // when
        clientWantsToWithdraw(TEN, cardUUid); //HTTP GET
        // then
        thereIsOneWithdrawalOf(TEN, cardUUid);
    }

CQRS with transaction log tailing as synchronization

Synchronization done by listening to database's transaction log, which is a log of transactions accepted by a database management system.

Code can be found under with-log-tailing module.

Additional components:

  • MySQL to keep withdrawals and credit cards.
  • Apache Kafka for pub/sub for messages read from database transaction log (in this case it is MySQL).
  • Kafka Connect with Debezium to read MySQL’s transaction log and stream messages to Kafka’s topic.
  • Spring Cloud Stream to read messages from Kafka’s topic.

Running the app, remember to be in root of the project:

  • In docker-compose.yaml, under service kafka - CHANGE IP to match your host machine. Keep port pointing to 9092:
ADVERTISED_LISTENERS=PLAINTEXT://YOUR_HOST_IP:9092
  • Run the whole infrastructure:
docker-compose up
  • Tell Kafka Connect to tail transaction log of MySQL DB and send messages to Kafka:
curl -i -X POST -H "Accept:application/json" -H  "Content-Type:application/json" http://localhost:8083/connectors/ -d @source.json --verbose

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query:

curl http://localhost:8080/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result can be seen below. Remember that it takes time to read transaction log and create a withdrawal. Hence a withdrawal might be not immedietly seen:

[{"amount":10.00}]

Architecture overview:

logtailing

Since it is problematic (or immposible) to test transaction log tailing, there is no E2E test that verifies commands and queries. But we can test if a message arrival in Kafka's topic results in a proper withdrawal created. The code is here:

    @Test
    public void shouldSynchronizeQuerySideAfterLogTailing() {
        // given
        String cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100));
        // when
        creditCardUpdateReadFromDbTransactionLog(TEN, cardUUid);
        // then
        thereIsOneWithdrawalOf(TEN, cardUUid);
    }

CQRS with Domain Events as synchronization

Synchronization done by sending a domain event after succesfully handling a command.

Code can be found under events module. It has 2 further modules, architecture is fully distributed. There is a source (deals with commands) and sink (deals with queries).

Additional components:

  • H2 DB to keep credit cards.
  • MongoDB to keep withdrawals.
  • Spring Data Reactive MongoDb to reactively talk to Mongo
  • Project Reactor to serve non-blocking web-service
  • Apache Kafka for pub/sub for domain events
  • Spring Cloud Stream to read/write messages from/to Kafka’s topic.

Running the app, remember to be in root of the project:

  • Run the whole infrastructure:
docker-compose up

A sample Withdraw command:

curl localhost:8080/withdrawals -X POST --header 'Content-Type: application/json' -d '{"card":"3a3e99f0-5ad9-47fa-961d-d75fab32ef0e", "amount": 10.00}' --verbose

Verifed by a query (notifce a different port: 8888!):

curl http://localhost:8888/withdrawals?cardId=3a3e99f0-5ad9-47fa-961d-d75fab32ef0e --verbose

Expected result can be seen below. Remember that it takes time to publish and read domain events from Kafka. Hence a withdrawal might be not immedietly seen:

[{"amount":10.00}]

Architecture overview:

events

Since it is not recommended to test 2 microservices in one test, there is no E2E test that verifies commands and queries. But we can test if a message arrival in Kafka's topic results in a proper withdrawal created. The code is here:

    @Test
    public void shouldSeeWithdrawalAfterGettingAnEvent() {
        //when
        anEventAboutWithdrawalCame(TEN, cardID);

        //then
        thereIsOneWithdrawalOf(TEN, cardID);
    }

Also it is possible to test if a successful withdrawal is followed eventually by a proper domain event publication. The code is here.

    @Test
    public void shouldEventuallySendAnEventAboutCardWithdrawal() throws IOException {
        // given
        UUID cardUUid = thereIsCreditCardWithLimit(new BigDecimal(100));
        // when
        clientWantsToWithdraw(TEN, cardUUid);
        // then
        await().atMost(FIVE_SECONDS).until(() -> eventAboutWithdrawalWasSent(TEN, cardUUid));
    }

CQRS with Axon Framework

Take a look here

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].