-
Notifications
You must be signed in to change notification settings - Fork 948
Home
This example application is the money transfer application described in my talk Building and deploying microservices with event sourcing, CQRS and Docker. This application consists of loosely coupled components that communicate using events and are implemented using event sourcing (ES) and command query responsibility separation (CQRS). These components can be deployed as separate services or, as they are here, packaged as a monolithic application for simplified development and testing.
The application has an event-driven architecture that uses event sourcing (ES) and command query responsibility separation (CQRS). This big idea with event sourcing is that instead of persisting an entity’s current state, the application’s persists the entity’s state changing events. Event sourcing is a simple yet reliable way of building event-driven applications. For more information on event sourcing, please see the introduction to event driven architecture.
CQRS is often used in conjunction with event sourcing. It decomposes the application into the command side, which uses event sourcing and handles update requests, and the query side, which subscribes to events published by the command side and handles query requests. By separating concerns, CQRS simplifies the command and query sides and allows them to be developed, optimized and scaled independently. For more information on CQRS, please see the introduction to event driven architecture.
The following diagram shows the application’s architecture.
Let's now look at how the command side of the application is implemented.
The application's domain model defines two aggregates that are implemented using event sourcing: MoneyTransfer and Account. To perform a transfer, you create a MoneyTransfer aggregate that specifies the ids of the from and to and the amount of money to transfer. The application transfers money between the accounts using an event-driven eventually consistent workflow. Each step of the workflow updates a single aggregate, which generates an event that triggers the next step.
The following diagram shows the flow:
The Account and MoneyTransfer aggregates reside in separate modules that only communicate via events
The Accounts module consists of the following components
- AccountController - handles the HTTP POST request to create an Account
- Account - the Account aggregate that implements the business logic for accounts
- AccountWorkflow - subscribes to events published by MoneyTransfer and updates Account
The Money Transfers module consists of the following components:
- MoneyTransferController - handles the HTTP POST request to create a MoneyTransfer
- MoneyTransfer - the MoneyTransfer aggregate that implements the business logic for money transfers
- MoneyTransferWorkflow - subscribes to events published by Account and updates the MoneyTransfer
Let's now look of the query side of the application.
The application maintains a CQRS-style denormalized view of accounts in MongoDB.
The module responsible for updating MongoDB consists of the following components:
- AccountQueryWorkflow - subscribes to events published by Account and MoneyTransfer and updates MongoDB using the AccountInfoRepository
- AccountInfoRepository - repository for Account info implemented using Spring Data for Mongo
The module that handles HTTP-based queries consists of:
- AccountQueryController - handles the GET request for the denormalized view of an Account and it's transactions. It queries MongoDB using AccountInfoRepository
The example application is written using an event sourcing framework. Please read the framework's developer guide