@AggregateCommandHandler
This chapter dives into the heart of processing commands within an Aggregate in Evento. You'll explore the @AggregateCommandHandler
annotation and discover how to effectively handle command events to manage state changes in your domain model.
The @AggregateCommandHandler
Annotation
@AggregateCommandHandler
AnnotationThe @AggregateCommandHandler
annotation serves as the cornerstone for defining methods that handle commands within an Aggregate. It essentially marks a method within your Aggregate Root class as responsible for processing a specific domain command.
Here's a breakdown of the annotation's definition:
Java
Usa il codice con cautela.content_copy
@Retention(RetentionPolicy.RUNTIME)
: This ensures that the annotation information is retained at runtime, allowing Evento to access it during application execution.@Target(ElementType.METHOD)
: This specifies that the annotation can only be applied to method declarations within your Aggregate Root class.@Handler
: This indicates that the annotated method is a handler for domain commands.init (default false)
: This optional parameter allows you to mark a specific command handler as an initializer for the Aggregate. Initializers are responsible for creating a new Aggregate instance.
Implementing @AggregateCommandHandler
Methods
@AggregateCommandHandler
MethodsAn @AggregateCommandHandler
method must adhere to a specific structure to effectively handle commands:
Domain Command as the First Parameter: The first parameter of the method must be a subtype of the
DomainCommand
class representing the specific command being handled.Aggregate State as the Second Parameter: The second parameter of the method should be of the type
AggregateState
for the corresponding Aggregate. This provides access to the current state of the Aggregate.Optional Additional Parameters: Depending on your specific requirements, you might include additional parameters like
CommandGateway
for sending follow-up commands orCommandMessage
for accessing details about the received command.Return Type: Domain Event Object: The
@AggregateCommandHandler
method must return a subtype of theDomainEvent
class. This returned event object signifies the outcome of processing the command and encapsulates the state change resulting from the command's execution.
Processing Flow within an @AggregateCommandHandler
Method
@AggregateCommandHandler
MethodHere's a breakdown of the typical processing flow within an @AggregateCommandHandler
method:
Validation Phase:
The method performs validations on the received
DomainCommand
object. This ensures that the command is syntactically correct (all fields have the provided formats) and semantically consistent (the proposed domain change aligns with the current state of the Aggregate). Techniques like assertions might be used for validation.
Event Forging Phase:
Assuming the command passes validation, the method constructs a new
DomainEvent
object that represents the state change resulting from the command's execution. This event object encapsulates the details of the change that will be applied to the Aggregate State.
Example: @AggregateCommandHandler
in Action
The provided code examples showcase two @AggregateCommandHandler
methods:
handle
method forDemoCreateCommand
: This method validates theDemoCreateCommand
and, upon successful validation, creates aDemoCreatedEvent
reflecting the new Aggregate state.handle
method forDemoUpdateCommand
: This method validates theDemoUpdateCommand
and, if valid, creates aDemoUpdatedEvent
representing the updated state.
ptional Parameters for @AggregateCommandHandler
Methods
@AggregateCommandHandler
MethodsWhile the core structure of an @AggregateCommandHandler
method involves the DomainCommand
and AggregateState
parameters, there are several optional parameters you can leverage to enhance command handling capabilities:
CommandGateway (Optional)
: This parameter provides access to theCommandGateway
interface. This interface allows you to send follow-up commands within the same transactional context as the current command. For instance, after handling aDemoUpdateCommand
, you might want to send a separate command to notify an external system about the update. By utilizingCommandGateway
, you can achieve this within the same transaction, ensuring data consistency.
While the CommandGateway
provides a convenient way to trigger follow-up commands within your @AggregateCommandHandler
methods, it's crucial to be mindful of potential challenges regarding cross-domain consistency.
The Issue:
Event sourcing systems are not inherently transactional across multiple Aggregates. When you send a new command using CommandGateway
within an @AggregateCommandHandler
method, there's no guarantee that both commands will succeed or fail atomically.
Here's a scenario to illustrate the concern:
You handle a command in an Aggregate and use
CommandGateway
to send a follow-up command to another Aggregate.The first command successfully processes and generates an event.
However, the follow-up command sent to the other Aggregate might fail due to validation errors or other unforeseen circumstances.
In this situation, you've potentially modified the state of your first Aggregate but haven't achieved the intended outcome in the second Aggregate. This can lead to inconsistencies in your overall domain model.
emember, the key lies in understanding the potential implications of cross-domain consistency when using CommandGateway
. By employing alternative strategies like Sagas complex workflows, you can ensure a more robust and consistent domain model in your Evento applications.
CommandMessage<T extends DomainCommand> (Optional)
: This parameter provides access to theCommandMessage
object that encapsulates the receivedDomainCommand
. TheCommandMessage
offers additional information about the command, including:Metadata: The
CommandMessage
might contain metadata associated with the command. This metadata could include information like the source of the command (e.g., user ID) or tracing information for debugging purposes.Timestamp: The
CommandMessage
typically holds a timestamp representing the time the command was received by the system. This can be useful for auditing purposes or ensuring temporal ordering of events.
Remember: While CommandMessage
provides access to metadata and timestamp, these are often already available within the received DomainCommand
object itself. The decision to use CommandMessage
depends on your specific needs and whether you require additional information beyond the core command data.
Instant (Optional)
: This parameter allows you to explicitly specify the timestamp for the domain command being created. By default, most event creation methods within Evento likely use the current system time. However, in specific scenarios, you might want to set a custom timestamp for the event.Metadata (Optional)
: The same Metadata object carried by the message.
By strategically using these optional parameters, you can create more versatile and informative @AggregateCommandHandler
methods within your Evento Aggregates.
In essence, the @AggregateCommandHandler
annotation empowers you to define clear and concise methods within your Aggregate Root class that handle domain commands, perform validations, and generate corresponding domain events to manage state changes.
The next chapter will explore how these generated domain events are applied to update the Aggregate State within Evento.
Last updated