| layout | post | |||
|---|---|---|---|---|
| title | Axon - CQRS with Spring Boot by examples | |||
| date | 2018-10-23 | |||
| tags |
|
We already introduced CQRS architectures a while ago here. The focus was to migrate a legacy monolith application into a CQRS architecture. However, we didn't go in deep by actually coding it. Let's do this using Axon Framework and Spring Boot. We'll create a library application from scratch.
Axon is not just a framework, but an infrastructure that also involves an Axon server. The Axon server manages a bus event and all the mecanisms to manage the commands and queries:

This image is taken from the official Axon documentation for version 4.
Where all our events will be stored? In the Event Store running under the Axon Server (see AxonServerEventStore.java for more information). If we want to use an embedded event store in, let's say, a RDBMS instance or in Mongo, Axon provides custom implementations for this. More in here. This is something we'll like to explore further in the future.
Aggregates are the domain objects in Axon. We can configure our configuration to match the aggregate to an entity in our database.
When we connect our application, Events will be read on-demand when an existing aggregate is targeted by a command. To enhance efficiency when processing multiple commands to the same aggregate, Axon supports caching repositories that would keep the aggregate in memory to avoid another read of the same events. Once aggregates are totally synchronized, it will be ready to be used. See AggregateLifecycle.java.
We'll use the official docker image to startup an Axon server instance:
docker run -d --name axonserver -p 8024:8024 -p 8124:8124 axoniq/axonserver
Feel free to startup a server instance yourself by downloading the binaries from here.
In order to check the installation was succeded, browse to "http://localhost:8024/" and we should see the Axon dashboard:

We'll use the Axon Spring Boot Starter maven dependency in the pom.xml for all our projects:
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>This is the easiest way to get warm with Axon. Spring Boot eases the configuration using default components in Axon. For more information, go to here.
Also, Axon provides a very good tutorial or recipe with Spring Boot.
Let's start coding! We'll write a library application where we can organize books into different libraries.

We need to start thinking on events. What is a library? In object oriented programming, a library is just a set of books. In event oriented programming, a library is:
- event 1: library named "My Library"
- event 2: Added book "x" to "My Library"
- event 3: Added book "y" to "My Library"
Note, we can redefine the concept of libraries anytime by adding a new event. And the most important, we have a time-scale of our library thanks to events.
On the other hand, we have the commands. A command is an use case in our application and it can derivate in a set of events that will define the current state.
Therefore, let's continue coding our application.
We'll use Spring Boot which is the easiest way to startup our application:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}This is only for testing purposes. For production, we'd need to provide a persistence state of the event store and use a distributed queue. We'll write about these refinements in a future post.
The commands are the use cases of our application and needs to verify the data is correct before adding an event. Therefore, we don't need to validate the events afterwards.
- Register a Library
Let's define the command to register a new library:
public class RegisterLibraryCommand {
@TargetAggregateIdentifier
private final Integer libraryId;
private final String name;
<