Class MigrateAggregateDeadlineHandler

java.lang.Object
org.openrewrite.Recipe
org.openrewrite.ScanningRecipe<MigrateAggregateDeadlineHandler.Accumulator>
org.axonframework.migration.MigrateAggregateDeadlineHandler
All Implemented Interfaces:
Cloneable

public class MigrateAggregateDeadlineHandler extends org.openrewrite.ScanningRecipe<MigrateAggregateDeadlineHandler.Accumulator>
Replaces the Axon Framework 4 @DeadlineHandler of an aggregate with the Axon Framework 4 @CommandHandler that receives the deadline once it fires.

On the Axoniq Framework legacy module, a deadline scheduled for an aggregate scope fires as a command: a deadline with a payload becomes a command named after its payload class, and a deadline without a payload becomes a command named after the deadline, carrying the deadline name as its payload. The recipe maps every handler onto the command that reaches it:

  • a handler with a payload parameter becomes a plain @CommandHandler. The deadlineName attribute is dropped, as the command is routed by its payload type only;
  • a handler without a payload parameter but with a payloadType keeps that payloadType;
  • a handler without a payload parameter and with a deadlineName becomes @CommandHandler(commandName = <deadlineName>), which accepts the deadline name payload. This only holds when every DeadlineManager#schedule call of that deadline passes no payload, so the scanning phase collects these calls over all sources, resolving deadline names given as string literals or constants.
The recipe uses the Axon Framework 4 @CommandHandler on purpose: the Axon Framework 5 upgrade that runs afterwards moves it to the Axon Framework 5 package and migrates the handler like any other aggregate command handler. The deadline payload class is left untouched, since the target entity is resolved from the deadline's aggregate scope.

Where the deadline cannot reach the handler as a command, the recipe leaves a // TODO(axon4to5): marker:

  • a handler that names neither a deadline nor a payload type handled every deadline of the aggregate, and an Object, interface or abstract payload parameter names no command. These keep their @DeadlineHandler;
  • a handler that matched its deadline by name alone keeps its @DeadlineHandler when that deadline is scheduled with a payload, which Axon Framework 4 matched as the payload type defaulted to Object, but which now arrives as a command named after the payload class. It is kept as well when the recipe cannot tell: no schedule call of that name is in the sources, for example as another module schedules it, or a deadline with a payload is scheduled under a name that is no literal or constant;
  • a handler of a member entity keeps its @DeadlineHandler: Axon Framework 4 delivered a fired deadline to the aggregate root and to every member entity, while a command reaches an entity in a collection only through a routing key;
  • two handlers of one aggregate, its root and member entities included, that receive the same payload type, which Axon Framework 4 told apart by deadline name or message type, now receive the same command;
  • a DeadlineMessage parameter does not match the command message that now arrives.
The recipe rewrites Java sources only: in an aggregate written in another JVM language, such as Kotlin, it marks every @DeadlineHandler instead. Saga classes, which keep their @DeadlineHandler on the legacy module, are left alone. The recipe is idempotent.
Since:
5.4.0
Author:
Mateusz Nowak
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    What the scanning phase learns about the source classes.

    Nested classes/interfaces inherited from class org.openrewrite.Recipe

    org.openrewrite.Recipe.Builder, org.openrewrite.Recipe.DelegatingRecipe
  • Field Summary

    Fields inherited from class org.openrewrite.Recipe

    contributors, examples, PANIC
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
     
     
    getInitialValue(org.openrewrite.ExecutionContext ctx)
     
    org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext>
     
    org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext>
     

    Methods inherited from class org.openrewrite.ScanningRecipe

    clone, generate, generate, getAccumulator, getVisitor

    Methods inherited from class org.openrewrite.Recipe

    addDataTable, aggregateDataTableDescriptors, builder, buildRecipeList, causesAnotherCycle, createRecipeDescriptor, equals, getContributors, getDataTableDescriptors, getDescriptor, getEstimatedEffortPerOccurrence, getExamples, getInstanceName, getInstanceNameSuffix, getJacksonPolymorphicTypeTag, getMaintainers, getName, getRecipeList, getTags, hashCode, maxCycles, noop, onComplete, run, run, run, setContributors, setExamples, validate, validate, validateAll, validateAll, withOptions

    Methods inherited from class java.lang.Object

    finalize, getClass, notify, notifyAll, toString, wait, wait, wait