Share on LinkedIn
Pocket

This article is a presentation of a new little , I have developed and used on several projects.

The framework is for Spring Framework and requires .0. The is on GitHub and downloadable from Bintray or JCenter.

spring-cqrs-arch

Download

Purpose

This module is an implementation of a model inspired from the CQRS ( link from Fowler ) model.

CQRS Architecture

CQRS Architecture

The idea is the following : the software functionalities are split between the read and the write accesses made by the user.

Advantages

The strongest advantages of this architecture are – according my experience – :

  • Evolutive architecture : this architecture model enforces several OOP architecture principles (design patterns, transverse functionalities)
  • Easy testing : the module and the architecture allows the developer to do unit-testing or component-based testing of its code. Furthermore this implementation is also providing out of the box : logging, profiling and tracing (file export) to push the debugging further
  • Spring compatible : this architecture is compatible with IOC, Java and Spring
  • Microservice compatible : this module can be used to implement a monolith and split it as microservices later, or directly as microservices if you implement a Bus.

Cleancode

Some bad smells often found in Spring / Java Web applications are avoided with this model.

By instance : * God / Mother classes : Some years ago, it was quite common to find Java classes also known as Services containing quite a bunch of methods, a big grape of autowired services and poorly tested. These classes were highly fragile, hard to mock and . By creating a class per command and therefore by usecase, the java classes are fine-grained,easier to mock and . * Excessive parameters The developer has to encapsulate the data into an Command object to pass it through the gate. This way, the OOP is enforced into the Core of this model.

Implementation model for an web application using CQRS principles.

Scope

This module is offering basically the Command architecture principles, and a way to send events.

For the query part, I recommend a progressive approach :

  • Use the same database and the same database access technology (with ORM)
  • Use another database access technology (without ORM or NoSQL)
Module architecture design

Module architecture design

How to use

Configuration

The module requires to define a Bean to start it (CqrsConfiguration).

The easiest way is to create a Configuration bean and to declare the configuration inside :

@Configuration
public class CqrsModuleConfiguration {
 public CqrsConfiguration configure() {
        CqrsConfiguration configuration = new CqrsConfiguration();
        // Configure there
        return configuration;
 }
}

How to begin

To conceive an application using CQRS, you need to think that way :

  • What are my use cases : define your use-cases expressed as operation s(READ or Write) or eventually a sequence flow diagram per use-case
  • Distinguish your write access : for example create a new user, edit his phone number. Avoid as much as possible generic and poor business meaning operations as CRUD (Create, Update, Delete). Think about what are you trying to update ? His personal details ? Are you toggling the email configuration flag ? Obviously all the se operations are a write and could be written as a big Update method. Cqrs is enforcing the DDD approach. Meaning is a rule to write better application toward functional design rather than technical design and to increase the productivity.
  • Start by writing your commands : that is the easiest part :

Write a command

A command is a basic Pojo :

public class CreateUserCommand {
    public String email;
    public String password;
}

Every command is tested using the Validation API and usually the Hibernate validator API.

public class CreateUserCommand {
    @NonEmpty
    @Email
    public String email;
    @NonEmpty
    @Size(minimum=8)
    public String password;
}

It means the gate will validate the command before executing them.

If you pay attention, you should be able to convert your request body or payload directly as a Command.

Send the command

To send a command, you need to send the object through the gate.

To do so, inject the Gate dependency with @Autowired

@RestController
public class MyController {
        @Autowired
        private Gate gate;
}

You have two possibilities to send a command :

  • a synchronous way : gate.dispatch(command);
  • an asynchronous way : gate.dispatchAsync(command);

The methods are returning the results of the command execution.

Write a command handler

To write a command handler, you need to implement a Spring bean defining the interface ICommandHandler.

The interface ICommandHandler is taking two type parameters : * the first one is the command handled : exemple CreateNewCommand * the second is the returned type of the command handler: the result produced by the execution of the command.

example :

@CommandHandler
public class CreateNewUserCommandHandler implements ICommandHandler<CreateNewUserCommand, Integer> {
@Override
    public Integer handle(final CreateNwUserCommand command) throws Exception {

        return 1;
    }
}

We also recommend to send events to notify the change in the repository. The gate is offering such proxy. The default bus is in Guava but can be implemented using the Spring applicationEvent or more complex implementations.

@CommandHandler
public class CreateNewUserCommandHandler implements ICommandHandler<CreateNewUserCommand, Integer> {

@Autowired
private Gate gate;

@Override
    public Integer handle(final CreateNewUserCommand command) throws Exception {
            gate.dispatchEvent(new EventNewUserCreated());
        return 1;
    }
}

Spring Profiles

Here are the following profiles to enable features in the module :

@Profile("guava_bus")

Exception Handling

Here is the list of Exception that may be thrown by the CQRS Gate :

  • CommandExecutionException.java : When the execution has failed, the default exception handler is wrapping the checked exception in this exception.
  • CommandHandlerNotFoundException.java : When a command is sent through the gate but no handler has been found.
  • CqrsException.java : Base exception class
  • InvalidCommandException.java : Commands are validated using the JEE Api validation. If an invalid command hs been sent to the Gate, the Exception will be returned. The exception encloses a ConstraintsViolationException with the list of invalid properties.

The gate is provided with a default Exception handler with the following behaviour :

  • Any caught exception is wrapped inside a CommandExecutionException.

The behaviour can be changed using your own ICommandExceptionHandler.

Listener on command execution

It is possible to implement a listener (or many) to trap the execution of a command through the gate.

To do so, simply implement a new Spring bean implementing the interface ICommandExecutionListener.

@Bean
public class DemoBean implements ICommandExecutionListener {

}

Transactions

Transaction can be implemented in two ways :

  • Creating an ICommandExecutionListener and trigger the transaction as a wrapper over the execution of a transaction
  • Directly on the CommandHandler by adding the appropriate @Transaction

References

Share on LinkedIn
Pocket


Sylvain Leroy

Senior Software Quality Manager and Solution Architect in Switzerland, I have previously created my own company, Tocea, in Software Quality Assurance. Now I am offering my knowledges and services in a small IT Consulting company : Byoskill and a website www.byoskill.com Currently living in Lausanne (CH)