Command Router
The framework module provides CommandRouter
as the core component responsible for command execution. Command execution can be triggered via one of the send() methods, providing a
Command instance and an optional command meta-data map. It comprises the following steps:
- routing the
Commandinstance to the responsibleCommandHandlerby means of a suitableCommandHandlerDefinition - reading the relevant, upcasted Java event objects using the event repository
- reconstructing the command execution state using the
StateRebuildingHandlerinstances defined within the configuredStateRebuildingHandlerDefinitioninstances - optionally caching the reconstructed state for future command executions
- executing the
CommandHandlerand capturing any Java object events published via theCommandEventPublisherand the optional command result (or exception) - publishing the captured events atomically using the event repository with suitable preconditions to avoid inconsistent writes due to race conditions
Configuration
An instance of CommandRouter can be obtained,
either by manually instantiating it or using Spring Boot autoconfiguration.
Manual Configuration
An instance of CommandRouter can be created providing the necessary
configuration properties:
- an
EventReaderinstance for reading events - an
ImmediateEventPublisherinstance for publishing new Java object events - a list of
CommandHandlerDefinitioninstances - a list of
StateRebuildingHandlerDefinitioninstances - an optional
StateRebuildingCacheinstance for caching reconstructed states - an optional
PropagationModespecifying, if and how command meta-data is to be propagated to the published events - an optional set
java.util.Set<String>specifying, which command meta-data keys (and their corresponding values) to propagate to the published events
The following example shows, how to instantiate a CommandRouter using a provided
EventRepository, a list of CommandHandlerDefinition
(containing the command handling logic),
and a list of StateRebuildingHandlerDefinition
(containing the state rebuilding logic).
package com.opencqrs.framework.command;
import com.opencqrs.framework.persistence.EventRepository;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class CommandRouterConfiguration {
public static CommandRouter commandRouter(
EventRepository eventRepository,
List<CommandHandlerDefinition> commandHandlerDefinitions,
List<StateRebuildingHandlerDefinition> stateRebuildingHandlerDefinitions
) {
return new CommandRouter(
eventRepository,
eventRepository,
commandHandlerDefinitions,
stateRebuildingHandlerDefinitions
);
}
}
The correct configuration can be confirmed, by sending a suitable command (covered by any of the supplied CommandHandlerDefinition) as follows:
public static void main(String[] args){
var commandRouter = commandRouter(...);
commandRouter.send(new MyCommand(42L)); // MyCommand class omitted for brevity
}
Spring Boot Auto-Configuration
For Spring Boot applications using the framework-spring-boot-starter module
CommandRouterAutoConfiguration provides a fully configured
CommandRouter Spring bean. The bean can be configured
with respect to instance caching and meta-data propagation using the properties defined within
CommandHandlingCacheProperties and
MetaDataPropagationProperties, respectivly,
e.g. as follows:
Note
CommandRouterAutoConfiguration automatically picks up
all Spring beans of type CommandHandlerDefinition and
StateRebuildingHandlerDefinition, respectively. Those
will be used to rebuild the write model prior to command execution
and executing command handlers.
With that configuration in place the autoconfigured CommandRouter instance
can be auto-wired within any other Spring bean, if needed. The configuration can be further customized by:
- overriding the
CommandRouterSpring bean with an application-defined one - by providing a custom
EventRepository