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
Command
instance to the responsibleCommandHandler
by means of a suitableCommandHandlerDefinition
- reading the relevant, upcasted Java event objects using the event repository
- reconstructing the command execution state using the
StateRebuildingHandler
instances defined within the configuredStateRebuildingHandlerDefinition
instances - optionally caching the reconstructed state for future command executions
- executing the
CommandHandler
and capturing any Java object events published via theCommandEventPublisher
and 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
EventReader
instance for reading events - an
ImmediateEventPublisher
instance for publishing new Java object events - a list of
CommandHandlerDefinition
instances - a list of
StateRebuildingHandlerDefinition
instances - an optional
StateRebuildingCache
instance for caching reconstructed states - an optional
PropagationMode
specifying, 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
CommandRouter
Spring bean with an application-defined one - by providing a custom
EventRepository