Saturday, October 03, 2015

Exploring CQRS with Axon Framework: The Command, Command Bus and Command Handling Components

In this post we look at how to use Axon Framework to build out the command handling parts in a CQRS application.

It is part of a series of post that explores CQRS with Axon Framework.

As stated in the introductory post, these series of post is accompanied by the exploringCQRSwithAxon  project on Github. The project is a trivial application that simulates two bank accounts. It will support debiting, crediting and transfer between these two accounts. It is intended to help illustrate the features discussed as we explore how Axon Framework can be used to build application following CQRS stipulations.

The sample application is built with Axon Framework and Spring Boot. It uses the 2.4.1 version of Axon Framework, as you will notice in the Pom.xml

<dependency>
   <groupId>org.axonframework</groupId>
   <artifactId>axon-core</artifactId>
   <version>2.4.1</version>
  </dependency>
  <dependency>
   <groupId>org.axonframework</groupId>
   <artifactId>axon-test</artifactId>
   <version>2.4.1</version>
   <scope>test</scope>
  </dependency>

For the purpose of this series we would be using only the axon-core and axon-test modules.


Following with the sample application.
To follow this post with the accompanying application:

first clone the repo:
git clone git@github.com:dadepo/exploringCQRSwithAxon.git

then check out to the appropriate commit hash to have the project in a state that illustrates the topics covered in this post:
git checkout 0529ada7987eeadb37d88c9db95673e5883bddc8.

Objective of this post


The goal is to set up the command handling components of the application. Specifically, we would explore how to use Axon’s command bus, how to create commands and have it routed to command handlers.


Let us look at how this is achieved, by starting with Commands.

Commands
Commands are regular, plain, objects, (usually referred to as POJO’s), that are used to capture the intent of what needs to happen within a system together with the necessary information that is required.

Axon Framework does not require commands to implement any interface or extend any class. As said earlier, they are POJO’s. The general recommendation though, is to have commands immutable.

Another general recommendation regarding commands is that they have names that expresses the intent they embody. So, for example, if a commands conveys that an appointment should be canceled, then the name of the class should probably be named something like CancelAppointmentCommand.

In the accompanying project you will find the CreditAccount and DebitAccount classes. They are commands which, as can be seen from their names, expresses the intent to have an account either credited or debited.

public class CreditAccount {

private final String account;
private final Double amount;

public CreditAccount(String account, Double amount) {
this.account = account;
this.amount = amount;
}

public String getAccount() {
return account;
}

public Double getAmount() {
return amount;
}
}

and DebitAccount

public class DebitAccount {

   private final String account;
   private final Double amount;

   public DebitAccount(String account, Double amount) {
       this.account = account;
       this.amount = amount;
   }

   public String getAccount() {
       return account;
   }

   public Double getAmount() {
       return amount;
   }
}

They contain both the account number and amount to be credited or debited.

A command is intended to have only one and just one recipient. The recipient of a command is called the command handler, which we look at next.

Command Handlers
Command handlers are the components that receives commands and acts on them.

Commands by themselves are just "message carriers". The command handlers are the components that acts based on the intent (or message) captured in commands.

In Axon Framework you create a command handler via two ways:
  1. by having an Object implement the CommandHandler interface 
  2. or, if using Axon with Spring, use the AnnotationCommandHandlerBeanPostProcessor which allows us to have Spring beans that have methods annotated with @CommandHandler be turned into a command handler.
In our accompanying application, DebitAccountHandler is a command handling component that is implemented by implementing the CommandHandler interface, as seen below:

public class DebitAccountHandler implements CommandHandler {

@Override
public Object handle(CommandMessage commandMessage, 
 UnitOfWork unitOfWork) throws Throwable {
       DebitAccount debitAccountCommand = 
            (DebitAccount) commandMessage.getPayload();

       String account = debitAccountCommand.getAccount();
       Double amount = debitAccountCommand.getAmount();
       System.out.println("I can handle the debitAccount command: "
                                  + "Account to debit: " + account
                                  + " Amount to debit with: "+ amount);

       return null;
   }
}

while the CreditAccountHandler uses annotations:

@Component
public class CreditAccountHandler {

@CommandHandler
public void handle(CreditAccount creditAccountCommand){

   System.out.println("I can handle the creditAccount command: "
               + "Account to credit: " + creditAccountCommand.getAccount()
               + " Amount to credit with: "+ creditAccountCommand.getAmount());
  }
}

This requires AnnotationCommandHandlerBeanPostProcessor to be configured in the Spring Application context.

As can be seen from the code above, what these command handlers do for now is to print out messages to the console.

So now we have touched on commands, and command handlers, the next question is how do commands get delivered to their respective command handlers?

Command bus
The command bus is the component that routes commands to their respective command handlers.

The Axon Framework, as at of version 2.4.1, comes with four different types of Command Bus out of the box that can be used to dispatch commands to command handlers: The SimpleCommandBus, DisruptorCommandBus, AsynchronousCommandBus and
RecordingCommandBus. They all have unique properties: for example the AsynchronousCommandBus processes commands asynchronously while the DisruptorCommandBus would be most appropriate in a distributed setup.

In our application, we would be using the SimpleCommandBus.

Since we are working with Spring Framework, to have the SimpleCommandBus we would configure it as a bean in Spring's application context. This we do in the AppConfiguration class.

@Configuration
public class AppConfiguration {

 @Bean
 public SimpleCommandBus commandBus() {
    SimpleCommandBus simpleCommandBus = new SimpleCommandBus();
    // This manually subscribes the command handler: 
    // DebitAccountHandler to the commandbus
    simpleCommandBus.subscribe(DebitAccount.class.getName(), 
                                             new DebitAccountHandler());
    return simpleCommandBus;
 }


 @Bean
 AnnotationCommandHandlerBeanPostProcessor 
            annotationCommandHandlerBeanPostProcessor() {
       /**
        * The AnnotationCommandHandlerBeanPostProcessor 
        * finds all beans that has @CommandHandler
        * and subscribed them to the commandBus with the 
        * first argument of the method being the
        * the command type the method will be subscribed to.
        */
       AnnotationCommandHandlerBeanPostProcessor handler = 
               new AnnotationCommandHandlerBeanPostProcessor();

       handler.setCommandBus(commandBus());
       return handler;
 }

 @Bean
 public DefaultCommandGateway commandGateway() {
       return new DefaultCommandGateway(commandBus());
  }
 }


The first bean we have configured is the SimpleCommandBus.

Note that, as with many things in the Axon Framework, you can provide a custom implementation as drop in replacement to almost all of the components that Axon provides, for example you can easily have a custom command bus, all that is needed to be done is to implement the CommandBus interface.

For a command Bus to be able to route commands to command handlers, it needs to be aware of the commands and know their respective command handlers. This is achieved by subscribing command handlers to commands on the command bus.

The command bus interface defines the subscribe() method which can be used to do just exactly that. This is how the DebitAccountHandler command handler is subscribed to the DebitAccount command in the accompanying project.

For example, looking at the code that configures the SimpleCommandBus:

@Bean
 public SimpleCommandBus commandBus() {
   SimpleCommandBus simpleCommandBus = 
                    new SimpleCommandBus();

   // This manually subscribes the command handler: 
   // DebitAccountHandler to the commandbus
   simpleCommandBus.subscribe(DebitAccount.class.getName(), 
                    new DebitAccountHandler());
       return simpleCommandBus;
 }

As you see in the code, we use the subscribe() method to inform the SimpleCommandBus of the DebitAccount command and that it’s command handler is DebitAccountHandler.

We can also use the AnnotationCommandHandlerBeanPostProcessor to achieve the registering of commands with command handlers. If using Axon Framework with Spring, this should be the recommended method since having to manually subscribe each and every individual command handlers to commands in an application would quickly turn into a boring and laborious task. The recommended method is to use the @AnnotationDriven annotation which was added since version 2.3, It prevents having to explicitly declare a bean of type AnnotationCommandHandlerBeanPostProcessor. To use it, just annotate the Spring @Configuration class with @AnnotationDriven and all the @CommandHandler's and @EventHandler's will be automatically scanned and registered with their respective Bus. The accompanying sample application has been updated (with the d6c9f18750f8f7d4c341c80a07bdf44c5a815783 commit) to use the @AnnotationDriven.

The AnnotationCommandHandlerBeanPostProcessor scans for command handlers by finding beans that have the @CommandHandler annotation, finds a command bus within the application context and subscribe the command handler to the command it is intend to handle.

The first argument of the method that has the @CommandHandler is the command the command handler is meant to handle.

The code below shows how we wired up the AnnotationCommandHandlerBeanPostProcessor.

@Bean
AnnotationCommandHandlerBeanPostProcessor 
          annotationCommandHandlerBeanPostProcessor() {
 /**
  * The AnnotationCommandHandlerBeanPostProcessor finds all beans that has 
  * @CommandHandler
  * and subscribed them to the commandBus with the first argument of 
  * the method being the the command type the method will be subscribed to.
 */
 AnnotationCommandHandlerBeanPostProcessor handler = 
                      new AnnotationCommandHandlerBeanPostProcessor();

 handler.setCommandBus(commandBus());
 return handler;
}

Command Gateway
Even though it is possible to use the command bus directly to send out commands, it is usually recommended to use a command gateway. This is because the command gateway offers a "friendlier" API than having to use the command bus directly.

It also allows us to perform certain functionalities, for instance, with a command gateway, we have the facility to easily set up a retry mechanism for failed commands, intercept commands and modify them before they are dispatched to the command handling component.

Axon Framework provides the DefaultCommandGateway as an implementation of CommandGateway. We would be using this in our application to send out commands instead of directly using a command bus. The DefaultCommandGateway is configured thus:

@Bean
public DefaultCommandGateway commandGateway() {
   return new DefaultCommandGateway(commandBus());
}

If you had cloned the exploringCQRSwithAxon project and checked out the hashcode 0529ada7987eeadb37d88c9db95673e5883bddc8, you can run the application by switching to the root directory and execute mvn spring-boot:run.

Once the application is started, go to localhost:8080, you see the following page:


If you select Account one, type in 10 in the input field and click on debit account, you will see "I can handle the debitAccount command: Account to debit: acc-one Amount to debit with: 10.0" in the console.

You will get "I can handle the creditAccount command: Account to credit: acc-two Amount to credit with: 10.0" if you select account two, typed in 10, and clicked on credit Account.

An Overview.

Interacting with the UI inputs sends requests to the IndexController, which exposes the /debit and /credit endpoints.

When requests hit these endpoints, the IndexController creates commands, grabs hold of the command gateway (which has been injected) and dispatch the command.

@Controller
public class IndexController {

   @Autowired
   private CommandGateway commandGateway;

   @RequestMapping("/debit")
   @ResponseBody
   public void doDebit(@RequestParam("acc") String accountNumber, 
                       @RequestParam("amount") double amount) {
       DebitAccount debitAccountCommand = 
                 new DebitAccount(accountNumber, amount);

       commandGateway.send(debitAccountCommand);
   }

   @RequestMapping("/credit")
   @ResponseBody
   public void doCredit(@RequestParam("acc") String accountNumber, 
                         @RequestParam("amount") double amount) {
       CreditAccount creditAccountCommand = 
                       new CreditAccount(accountNumber, amount);
       commandGateway.send(creditAccountCommand);
   }
}

And since we have configured the command gateway with a command bus which knows how to route the commands that was dispatched, we have the DebitAccountHandler and CreditAccountHandler invoked respectively.

There are more functionalities of the components of Axon Framework we mentioned in this post. (some being for advanced use cases), but our exploration so far, should provide a good introduction to these components and how to put them to use.

We will now turn our focus to the other components represented in the CQRS diagram which will lead us to explore some concepts from Domain Driven Development.

The next post will be Overview of Some DDD concepts: Entity, Aggregate, Aggregate Root and Repository.

No comments: