Class MoveSagaFieldToHandlerParameter

java.lang.Object
org.openrewrite.Recipe
org.axonframework.migration.MoveSagaFieldToHandlerParameter
All Implemented Interfaces:
Cloneable

public class MoveSagaFieldToHandlerParameter extends org.openrewrite.Recipe
Moves a Saga field of a configured type into a parameter of the Saga methods that use it, because the Axoniq Framework legacy module does not inject Saga fields.

Axon Framework 4 populated @Autowired or @Inject fields of a Saga instance through a ResourceInjector. The legacy module resolves Saga collaborators as handler method parameters instead, so an injected field stays null. For a private field of the configured type, this recipe:

  • adds a parameter of that type, named after the field, to every @SagaEventHandler and @DeadlineHandler method that uses the field, directly or through private helper methods. A parameter of that type the method already declares is reused instead. A @DeadlineHandler without parameters first gets a DeadlineMessage parameter: the collaborator resolves from the configuration, which ranks below the payload, so as the first parameter it would become the payload and the handler would stop matching its deadlines;
  • adds the same parameter to those private helper methods, and passes it along at their call sites;
  • removes the field, together with its annotations and leading comments, once nothing refers to it.
The calls on the collaborator itself are left as they are. When the field name clashes with a parameter or local variable of a method, the new parameter gets a numeric suffix and the field references in that method are renamed.

The migration is all-or-nothing per field. A use the recipe cannot move into a handler parameter leaves the field and every one of its uses untouched, rather than producing a half-migrated Saga. Such a use is one in a constructor, a static method, a non-private method that is not a handler (it may be called from outside the class), a field initializer or initializer block, a nested, local or anonymous class, a method reference to an affected method, an assignment to the field, an access through another instance, or a call of a @DeadlineHandler without parameters, which could not pass on its new DeadlineMessage parameter. The same applies when the class declares more than one such field.

Uses in other classes, such as subclasses, are not visible to the recipe, so only a field no other class can use is moved: a private field, or in Kotlin, where properties are public by default, any property of a final class. A Kotlin class is final unless declared open, abstract or sealed. A protected, package-private or public field stays where it is. A field left in place is marked by MarkSagaResourceInjection when it is injected; one that is not injected was never populated by Axon Framework 4 either, and needs no marker.

Only Sagas are changed: classes annotated with the Spring @Saga stereotype or declaring a @SagaEventHandler method. Other components, such as aggregates or Spring services, keep their fields, because they are still injected there. Java and Kotlin sources are supported. The recipe is idempotent.

Since:
5.4.0
Author:
Mateusz Nowak
  • Nested Class Summary

    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
    MoveSagaFieldToHandlerParameter(String fullyQualifiedTypeName)
    Creates the recipe for Saga fields of the given type.
  • Method Summary

    Modifier and Type
    Method
    Description
     
     
    Returns the fully qualified name of the field type this recipe moves into handler parameters.
    org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext>
     

    Methods inherited from class org.openrewrite.Recipe

    addDataTable, aggregateDataTableDescriptors, builder, buildRecipeList, causesAnotherCycle, clone, 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
  • Constructor Details

    • MoveSagaFieldToHandlerParameter

      public MoveSagaFieldToHandlerParameter(String fullyQualifiedTypeName)
      Creates the recipe for Saga fields of the given type.
      Parameters:
      fullyQualifiedTypeName - the fully qualified name of the field type to move into handler parameters
  • Method Details

    • getFullyQualifiedTypeName

      public String getFullyQualifiedTypeName()
      Returns the fully qualified name of the field type this recipe moves into handler parameters.
      Returns:
      the fully qualified name of the field type
    • getDisplayName

      public String getDisplayName()
      Specified by:
      getDisplayName in class org.openrewrite.Recipe
    • getDescription

      public String getDescription()
      Specified by:
      getDescription in class org.openrewrite.Recipe
    • getVisitor

      public org.openrewrite.TreeVisitor<?,org.openrewrite.ExecutionContext> getVisitor()
      Overrides:
      getVisitor in class org.openrewrite.Recipe