CQRS basics and application structure

Fabio Hiroki - Dec 31 '19 - - Dev Community

Introduction

In this article, I will give an overview of the microservices patterns Event Sourcing and Command Query Responsibility Segregation (CQRS) patterns. Then I will show how to apply these concepts on a Spring Web Application using Axon Framework. You can check the final code on Github.

I recommend you to already have some basic concepts of Java and Spring Boot for better comprehension.

Event Sourcing

This pattern implies every application state change should be started by an event, which should be stored. For example, at an e-commerce site, after the user clicks a product to add to the cart, this action should send a JSON event containing the product id and quantity.

The final application state will then be defined by the sequence of previously processed events.

The main benefits of using Event Sourcing instead of maintaining only the last application state are:

  • Audit: you can search the stored events and verify exactly which events led to the next state.

  • Replay: if there's an error on event processing (ex.: database is down), you can just trigger the failed events again.

  • Replicate: you can publish the events on a message broker (ex.: Apache Kafka) and consume on another microservice.

CQRS

A pattern that proposes the separation of reading operations from writing or updating operations. This can be done in many ways, from just creating separate classes to using distinct databases.

The main benefit of CQRS is the logic division of code, making it clearer.

Demo Application Overview

The application will consist of a Spring Boot that simulates an e-commerce checkout platform. Through REST endpoints, you can add or edit a product containing attributes of id, name and quantity.

Following CQRS concepts, there will be separate modules for command and query:

  • Command Side: will contain the POST and PUT endpoints, that will generate its respective commands, which will be translated into events. The events will be stored into a MongoDb database in a raw format, while also being processed to generate the final application state and stored in a Postgres database.

  • Query Side: will contain the GET endpoint to fetch the latest snapshot of our e-commerce cart.

Axon Framework gives us a simple recipe on CQRS and Event Sourcing implementation, making it easy to understand the data flow.

Diagram representing the data flow from REST endpoint to event generation and aggregate change

Dependencies

  • spring-boot-starter
  • spring-boot-starter-web
  • spring-boot-starter-data-mongodb
  • spring-boot-starter-data-jpa
  • axon-spring-boot-starter
  • axon-mongo
  • postgresql

We will be using version 4.1.2 of axon-spring-boot-starter, which requires a separate Axon Server running to start our Spring Boot Application. To simplify this tutorial, we won't make use of Axon Server, so we can remove its dependency by declaring on build.gradle file:

compile('org.axonframework:axon-spring-boot-starter:4.1.2') {
  exclude group: 'org.axonframework', module: 'axon-server-connector'
}
Enter fullscreen mode Exit fullscreen mode

Command module configuration

We will start by creating the Command module. If you're using IntelliJ, you can do it by clicking File > New > Module, select Gradle, then Java. In ArtfactId type commandside then Finish. This step will create a folder called commandside in the root folder of your application containing a single build.gradle file. Check its configuration here on Github repository.

Next, you need to create the structure of a Spring Boot application inside commandside folder by creating a path internally containing your main package src/main/java/com/example/project/command. where it will be placed your @SpringBootApplication annotated class and all other package related classes. Check the final result here.

Inside src/main/resources, create an application.yml file to place your Postgres configuration. You can follow my example here.

The most important step now is the configuration of EventStorageEngine of Axon, which will be MongoDb in our example. To do this, create a Configuration class like this:

@Configuration
public class AxonConfig {

    // The `MongoEventStorageEngine` stores each event in a separate MongoDB document
    @Bean
    public EventStorageEngine storageEngine(MongoClient client) {
        return MongoEventStorageEngine
                .builder()
                .mongoTemplate(DefaultMongoTemplate
                        .builder()
                        .mongoDatabase(client)
                        .build())
                .build();
    }
}

Enter fullscreen mode Exit fullscreen mode

Query module doesn't require any special configuration. It will be a simple Spring Boot web application that fetches view models from the Postgres database.

Run your application now to check if everything works.

Conclusion

In this first part, we've discussed the basic concepts of CQRS and structured our demo application. In the next step, we will code the Command module.

. . . . . . . . . . . . . . . . . . . . . . . . . . . .