Class AggregateDeadlineCommandTranslator

java.lang.Object
org.axonframework.deadline.AggregateDeadlineCommandTranslator
All Implemented Interfaces:
ScopeAware

@Internal public class AggregateDeadlineCommandTranslator extends Object implements ScopeAware
Translates a fired DeadlineMessage scoped to an AggregateScopeDescriptor into a command, dispatched through a CommandGateway.

Implements ScopeAware so it can be reached through a ScopeAwareProvider the same way a Saga manager is. Its send(Message, ProcessingContext, ScopeDescriptor) dispatches the deadline's payload and metadata as a command named <aggregateType>.<deadlineName>: a QualifiedName with the aggregate type as namespace and the deadline's DeadlineMessage.getDeadlineName() as local name. It writes the AggregateScopeDescriptor's identifier into the dispatched command's metadata under "scope-descriptor-based-entity-identifier". AggregateDeadlineEntityIdResolverConfigurationEnhancer registers the resolver that reads this metadata entry as the application-wide default, used whenever the command's payload carries no @TargetEntityId.

Naming the command after the aggregate type and the deadline keeps deadlines apart that share a payload type, such as two deadlines carrying a UUID, and deadlines of different aggregate types that share a name. The aggregate type is the one Axon Framework 4 stored with the deadline: the aggregate's simple class name, unless its @Aggregate annotation set another type. The migrated handler of a deadline with a payload becomes @CommandHandler(commandName = "<aggregateType>.<deadlineName>") void handle(<Payload> payload, ...). A deadline scheduled without a payload carries null as its Message.payload(), and is dispatched with the deadline name as its payload instead, so its handler becomes @CommandHandler(commandName = "<aggregateType>.<deadlineName>") void handle(String deadlineName, ...).

Handlers migrated with an earlier version of this translator are named after the deadline's payload type, or after the deadline name alone for a deadline without a payload. To keep them working, a deadline that finds no handler for its qualified name is dispatched again under that earlier name, and a warning asks to rename the handler.

Constructed and registered by the AggregateDeadlineCommandTranslatorConfigurationEnhancer.

Since:
5.4.0
Author:
Steven van Beelen
See Also:
  • Constructor Details

    • AggregateDeadlineCommandTranslator

      public AggregateDeadlineCommandTranslator(CommandGateway commandGateway)
      Initializes an AggregateDeadlineCommandTranslator, dispatching translated commands through the given commandGateway.
      Parameters:
      commandGateway - the CommandGateway to dispatch a fired aggregate deadline's command through
  • Method Details

    • canResolve

      public boolean canResolve(ScopeDescriptor scopeDescription)
      Check whether this implementation can resolve a Scope object based on the provided scopeDescription. Will return true in case it should be able to resolve the Scope and false if it cannot.

      Returns true for every AggregateScopeDescriptor, regardless of the aggregate type it describes, since routing to the right entity is delegated to the dispatched command's @TargetEntityId, not resolved here.

      Specified by:
      canResolve in interface ScopeAware
      Parameters:
      scopeDescription - a ScopeDescriptor describing the Scope to be resolved
      Returns:
      true in case it should be able to resolve the Scope and false if it cannot
    • send

      public void send(Message message, ProcessingContext context, ScopeDescriptor scopeDescription) throws Exception
      Send a Message to a Scope which is described by the given scopeDescription.

      Dispatches the message's payload and metadata as a command named after the aggregate type of the scopeDescription and DeadlineMessage.getDeadlineName(), through the configured CommandGateway, passing the given context along so the command runs within the deadline's firing unit of work. Waits for the command's result with FutureUtils.joinAndUnwrap(java.util.concurrent.CompletableFuture), rethrowing a failure so the caller applies its own failure handling.

      When the command bus has no handler for that name, the message is dispatched again under the name an earlier version of this translator used, for handlers migrated with it: named after the payload's type, or after the deadline name alone for a message without a payload.

      A message whose payload is an UnknownDeadlinePayload (its stored type could not be resolved) is not dispatched: this method logs a warning naming the deadline, the stored type and the aggregate scope, and returns.

      A message whose payload is null is dispatched with DeadlineMessage.getDeadlineName() as its payload.

      The dispatched command's metadata always carries the scopeDescription's identifier under "scope-descriptor-based-entity-identifier", so the target entity can be resolved from it instead of from the payload.

      Specified by:
      send in interface ScopeAware
      Parameters:
      message - The Message to be sent to a Scope.
      context - The ProcessingContext in which the message is being processed.
      scopeDescription - A D extending ScopeDescriptor, describing the Scope to send the given message to.
      Throws:
      IllegalArgumentException - if the given message is not a DeadlineMessage, or if the given scopeDescription is not an AggregateScopeDescriptor
      Exception - if sending the message failed. Might occur if the message handling process throws an exception.