A state change within an application starts with a Command. A Command is a combination of expressed intent (which describes what you want done) as well as the information required to undertake action based on that intent. A Command Handler is responsible for handling commands of a certain type and taking action based on the information contained inside it.
The use of an explicit command dispatching mechanism has a number of advantages. First of all, there is a single object that clearly describes the intent of the client. By logging the command, you store both the intent and related data for future reference. Command handling also makes it easy to expose your command processing components to remote clients, via web services for example. Testing also becomes a lot easier, you could define test scripts by just defining the starting situation (given), command to execute (when) and expected results (then) by listing a number of events and commands (see Chapter 8, Testing). The last major advantage is that it is very easy to switch between synchronous and asynchronous command processing.
The next sections provide an overview of the tasks related to creating a Command Handling infrastructure with the Axon Framework.
The Command Handler is the object that receives a Command of a pre-defined type and
takes action based on its contents. In Axon, a Command may be any object. There is no
predefined type that needs to be implemented. The Command Handler, however, must
CommandHandler interface. This interface declares only a
Object handle(T command, UnitOfWork uow), where T is the
type of Command this Handler can process. The concept of the UnitOfWork is explained in
Section 3.4, “Unit of Work”. It is not recommended to use return values, but they
are allowed. Always consider using a "fire and forget" style of command handlers, where
a client does not have to wait for a response. As return value in such a case, you are
recommended to use
Void.TYPE, the official representation of the
Note that Command Handlers need to be explicitly subscribed to the Command Bus for the specific types of Command they can handle. See Section 3.3, “Configuring the Command Bus”.
More often than not, a command handler will need to process several types of
closely related commands. With Axon's annotation support you can use any POJO as
command handler. Just add the
@CommandHandler annotation to your
methods to turn them into a command handler. These methods should declare the
command to process as the first parameter. They may take an optional second
parameter, which is the
UnitOfWork for that command (see Section 3.4, “Unit of Work”). Note that for each command type, there may only be
one handler! This restriction counts for all handlers registered to the same command
You can use the
AnnotationCommandHandlerAdapter to turn your
annotated class into a
CommandHandler. The adapter also takes a
CommandBus instance. Use the
subscribe() method on the
adapter to subscribe all the annotated handlers to the command bus using the correct
If you use Spring, you can add the
Note that you need to be careful when mixing manual wrapping and the use of annotation-config element. This might result in command handler being subscribed twice.
It is not unlikely that most command handler operations have an identical
structure: they load an Aggregate from a repository and call a method on the
returned aggregate using values from the command as parameter. If that is the case,
you might benefit from a generic command handler: the
AggregateAnnotationCommandHandler. This command handler uses
@CommandHandler annotations on the aggregate's methods to identify
which methods need to be invoked for an incoming command. If the
@CommandHandler annotation is placed on a constructor, that command
will cause a new Aggregate instance to be created.
AggregateAnnotationCommandHandler still needs to know which
aggregate instance (identified by it's unique Aggregate Identifier) to load and
which version to expect. By default, the
AggregateAnnotationCommandHandler uses annotations on the command
object to find this information. The
annotation must be put on a field or getter method to indicate where the identifier
of the target Aggregate can be found. Similarly, the
@TargetAggregateVersion may used to indicate the expected
@TargetAggregateIdentifier annotation can be placed on a field or
a method. The latter case will use the return value of a method invocation (without
parameters) as the value to use. If this value is an instance of
AggregateIdentifier, it will be directly used. If it is a
java.util.UUID, it will be wrapped in a
UUIDAggregateIdentifier. Any other object will have its
toString() value wrapped in a
If you prefer not to use annotations, the behavior can be overridden by supplying
CommandTargetResolver. This class should return the
AggregateIdentifier and expected version (if any) based on a given
|Creating new Aggregate Instances|
The CommandBus provides two methods to dispatch commands to their respective handler:
dispatch(command, callback) and
first parameter is the actual command to dispatch. The optional second parameter takes a
callback that allows the dispatching component to be notified when command handling
is completed. This callback has two methods:
onFailure(), which are called when command handling returned normally,
or when it threw an exception, respectively.
The calling component may not assume that the callback is invoked in the same thread
that dispatched the command. If the calling thread depends on the result before
continuing (which is a highly discouraged approach), you can use the
FutureCallback. It is a combination of a
defined in the java.concurrent package) and Axon's
Best scalability is achieved when your application is not interested in the result of
a dispatched command at all. In that case, you should use the single-parameter
version of the
dispatch method. If the
CommandBus is fully
asynchronous, it will return immediately after the command has been successfully
received. Your application will just have to guarantee that the command is processed and
with "positive outcome", sooner or later...
In many cases, however, your application will want to be able to wait for the
result of a command. Especially in the cases where guarantees are more important
than scalability and the user interface needs the outcome of the command. In such
case, you can choose to use the
FutureCallback, or the simpler
CommandTemplate wraps a
CommandBus and allows some
"send and wait" type operations to be executed using a single method call. Some
methods allow you to specify a timeout. If no response has been received before the
timeout has expired, an exception is thrown. Note that the time starts counting when
dispatch method of the
CommandBus has returned. In the
case of the
SimpleCommandBus, timeouts are ignored, since the
dispatch method only returns after the
callbacks have been notified.
The Command Bus is the mechanism that dispatches commands to their respective Command
Handler. Commands are always sent to only one (and exactly one) command handler. If no
command handler is available for a dispatched command, an exception
NoHandlerForCommandException) is thrown. Subscribing multiple command
handlers to the same command type will result in subscriptions replacing each other. In
that case, the last subscription wins.
Axon provides a single implementation of the Command Bus:
SimpleCommandBus dispatches and
commands and executes the handler in the calling thread. You can subscribe and
unsubscribe command handlers using the
unsubscribe methods, respectively. They both take two parameters: the
type of command to (un)subscribe the handler to, and the handler to (un)subscribe. An
unsubscription will only be done if the handler passed as the second parameter was
currently assigned to handle that type of command. If another command was subscribed to
that type of command, nothing happens.
The Unit of Work is an important concept in the Axon Framework. The processing of a command can be seen as a single unit. Each time a command handler performs an action, it is tracked in the current Unit of Work. When command handling is finished, the Unit of Work is committed and all actions are finalized. This means that any repositores are notified of state changes in their aggregates and events scheduled for publication are send to the Event Bus.
The Unit of Work serves two purposes. First, it makes the interface towards repositories a lot easier, since you do not have to explicitly save your changes. Secondly, it is an important hook-point for interceptors to find out what a command handler has done.
In most cases, you are unlikely to need access to the Unit of Work. It is mainly used
by the building blocks that Axon provides. If you do need access to it, for whatever
reason, there are a few ways to obtain it. The Command Handler receives the Unit Of Work
through a parameter in the handle method. If you use annotation support, you may add the
optional second parameter of type
UnitOfWork to your annotated method. In
other locations, you can retrieve the Unit of Work bound to the current thread by
CurrentUnitOfWork.get(). Note that this method will throw an
exception if there is no Unit of Work bound to the current thread. Use
CurrentUnitOfWork.isStarted() to find out if one is available.
Note that the Unit of Work is merely a buffer of changes, not a replacement for Transactions. Although all staged changes are only committed when the Unit of Work is committed, its commit is not atomic. That means that when a commit fails, some changes might have been persisted, while other are not. Best practices dictate that a Command should never contain more than one action. If you stick to that practice, a Unit of Work will contain a single action, making it safe to use as-is. If you have more actions in your Unit of Work, then you could consider attaching a transaction to the Unit of Work's commit. See Section 3.5.1, “Transaction management”.
Your command handlers may throw an Exception as a result of command processing. By
default, these exceptions will cause the UnifOfWork to roll back all changes. As a
result, no Events are stored or published. In some cases, however, you might want to
commit the Unif of Work and still notify the dispatcher of the command of an
exception through the callback. The
SimpleCommandBus allows you to
instance indicates whether an exception should perform a rollback on the Unit of
Work, or a commit. Axon provides two implementation, which should cover most of the
RollbackOnAllExceptionsConfiguration, which is the default, will
cause a rollback on any exception (or error). The other is the
RollbackOnUncheckedExceptionConfiguration, which will commit the
Unit of Work on checked exceptions (those not extending
RuntimeException) while still performing a rollback on Errors and
One of the advantages of using a command bus is the ability to undertake action based on all incoming commands. Examples are logging or authentication, which you might want to do regardless of the type of command. This is done using Command Handler Interceptors. These interceptors can take action both before and after command processing. Interceptors can even block command processing altogether, for example for security reasons.
Interceptors must implement the
CommandHandlerInterceptor interface. This
interface declares one method,
handle, that takes three parameters: the
command, the current
UnitOfWork and an
InterceptorChain is used to continue the dispatching process.
The command handling process can be considered an atomic procedure; it should either be processed entirely, or not at all. Axon Framework uses the Unit Of Work to track actions performed by the command handlers. After the command handler completed, Axon will try to commit the actions registered with the Unit Of Work. This involves storing modified aggregates (see Chapter 4, Domain Modeling) in their respective repository (see Chapter 5, Repositories and Event Stores) and publishing events on the Event Bus (see Chapter 6, Event Processing).
The Unit Of Work, however, it is not a replacement for a transaction. The Unit Of Work only ensures that changes made to aggregates are stored upon successful execution of a command handler. If an error occurs while storing an aggregate, any aggregates already stored are not rolled back. If this is important to your application, consider using a Transaction Interceptor on the command bus that attaches a transaction to the Unit of Work.
Axon provides the
SpringTransactionalInterceptor, which uses Spring's
PlatformTransactionManager to manage the actual transactions. A
transaction is committed after a successful commit of the Unit of Work, or rolled
back as the Unit of Work is rolled back.
There is no point in processing a command if it does not contain all required information in the correct format. In fact, a command that lacks information should be blocked as early as possible, preferably even before any transaction is started. Therefore, an interceptor should check all incoming commands for the availability of such information. This is called structural validation.
Axon Framework has support for JSR 303 Bean Validation based validation. This
allows you to annotate the fields on commands with annotations like
@Pattern. You need to include a JSR 303
implementation (such as Hibernate-Validator) on your classpath. Then, configure a
BeanValidationInterceptor on your Command Bus, and it will
automatically find and configure your validator implementation. While it uses
sensible defaults, you can fine-tune it to your specific needs.
You want to spend as less resources on an invalid command as possible. Therefore, this interceptor is generally placed in the very front of the interceptor chain. In some cases, a Logging or Auditing interceptor might need to be placed in front, with the validating interceptor immediately following it. Transaction Management is better done after structural validation, as it often requires remote resources.
Well designed events will give clear insight in what has happened, when and why. To use the event store as an Audit Trail, which provides insight in the exact history of changes in the system, this information might not be enough. In some cases, you might want to know which user caused the change, using what command, from which machine, etc.
AuditingInterceptor is an interceptor that allows you to attach
arbitray information to events just before they are stored or published. The
AuditingInterceptor uses an
retrieve the information to attach to these events. You need to provide the
implementation of the
An Audit Logger may be configured to write to an audit log. To do so, you can
AuditLogger interface and configure it in the
AuditingInterceptor. The audit logger is notified both on succesful
execution of the command, as well as when execution fails. If you use event
sourcing, you should be aware that the event log already contains the exact details
of each event. In that case, it could suffice to just log the event identifier or
aggregate identifier and sequence number combination.
Note that the log method is called in the same thread as the command processing. This means that logging to slow sources may result in higher response times for the client. When important, make sure logging is done asynchronously from the command handling thread.