Class AddAggregateScopeToDeadlineCalls
- All Implemented Interfaces:
Cloneable
DeadlineManager calls of an Axon Framework 4 aggregate that
relied on the scope of the running handler.
Axon Framework 4 ran every aggregate handler inside the aggregate's scope, so schedule(trigger, name),
schedule(trigger, name, payload) and cancelAllWithinScope(name) described the scope themselves, as
new AggregateScopeDescriptor(type, identifier). The Axoniq Framework legacy module keeps these overloads,
but only a Saga handler runs inside a scope in Axon Framework 5: called from an entity handler they throw an
IllegalStateException. The recipe rewrites them to the overloads taking a ScopeDescriptor, passing
the descriptor Axon Framework 4 built:
- the type is the declared type of the class the aggregate's repository was configured for: the
typeof its@Aggregateor@AggregateRootannotation, or its simple name when it declares none. Axon Framework 4 used that type for every subtype of a polymorphic aggregate. As the configuration is not always in the sources, the recipe approximates that class: the topmost class of the hierarchy that a configuration call in the sources registers (configureAggregate(..),AggregateConfigurer.defaultConfiguration(..)orjpaMappedConfiguration(..), or a repositorybuilder(..)); else the topmost annotated class, which Spring registers as the root; else the class itself, unless it is abstract; - the identifier is the member annotated with
@AggregateIdentifier, or with@EntityIdor a persistence@Idon an annotated aggregate.
cancelAllWithinScope only cancels deadlines
whose scope equals the given one, including deadlines a not yet upgraded node scheduled.
The identifier is read when the call is made. Axon Framework 4 resolved it lazily, when the unit of work prepared its commit, but the legacy module runs a call made outside a Saga immediately, so a lazy identifier would be read at the same moment.
A creation command handler, a @CommandHandler constructor or a @CreationPolicy(ALWAYS) or
CREATE_IF_MISSING handler, has no identifier to read yet: the aggregate sets it once it applied its first
event. There the recipe reads the command's target identifier instead, when the command class in the aggregate's
source set declares exactly one @TargetAggregateIdentifier field, readable as a record accessor, a getter or
a public field. Axon Framework 4 routed the command to the aggregate of that identifier, and loaded an existing one
by it for CREATE_IF_MISSING.
Where the recipe cannot build the descriptor, it leaves a // TODO(axon4to5): marker on the statement: in
any other constructor or static method, which has no aggregate instance to read the identifier from (a creation
command handler becomes a static method in Axon Framework 5), in a creation handler whose command offers no such
target identifier, in a member entity of an aggregate, and
in an aggregate whose identifier or type the recipe cannot find. The recipe rewrites Java sources only: in an
aggregate written in another JVM language, such as Kotlin, it marks every such call instead. Calls with an explicit
scope, cancelSchedule and cancelAll, Sagas, and classes that are neither an aggregate nor one of
its entities are left alone. The recipe is idempotent.
- Since:
- 5.4.0
- Author:
- Mateusz Nowak
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classWhat 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 -
Method Summary
Modifier and TypeMethodDescriptiongetInitialValue(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, getVisitorMethods 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
-
Constructor Details
-
AddAggregateScopeToDeadlineCalls
public AddAggregateScopeToDeadlineCalls()
-
-
Method Details
-
getDisplayName
- Specified by:
getDisplayNamein classorg.openrewrite.Recipe
-
getDescription
- Specified by:
getDescriptionin classorg.openrewrite.Recipe
-
getInitialValue
public AddAggregateScopeToDeadlineCalls.Accumulator getInitialValue(org.openrewrite.ExecutionContext ctx) - Specified by:
getInitialValuein classorg.openrewrite.ScanningRecipe<AddAggregateScopeToDeadlineCalls.Accumulator>
-
getScanner
public org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext> getScanner(AddAggregateScopeToDeadlineCalls.Accumulator acc) - Specified by:
getScannerin classorg.openrewrite.ScanningRecipe<AddAggregateScopeToDeadlineCalls.Accumulator>
-
getVisitor
public org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext> getVisitor(AddAggregateScopeToDeadlineCalls.Accumulator acc) - Overrides:
getVisitorin classorg.openrewrite.ScanningRecipe<AddAggregateScopeToDeadlineCalls.Accumulator>
-