8.86.0 release (2026-07-01)
Total recipe count: 4455
This changelog only shows what recipes have been added, removed, or changed. OpenRewrite may do releases that do not include these types of changes. To see these changes, please go to the releases page.
Corresponding CLI version
- CLI version
4.3.7
New Recipes
- org.axonframework.migration.UpgradeAxonFramework_4_Jakarta: Migration file to upgrade from an Axon Framework Javax-specific project to Jakarta.
- org.axonframework.migration.UpgradeAxonFramework_4_Javax: Migration file to upgrade an Axon Framework Javax-specific project and remain on Javax.
- org.openrewrite.featureflags.launchdarkly.MarkIncompatibleEvaluationDetailAccessors: OpenFeature's
FlagEvaluationDetailsdoes not offer a direct replacement for everyEvaluationDetailaccessor. Add aTODOcomment ongetVariationIndex(),isDefaultValue()andgetReason()calls so they are migrated by hand, sincegetVariationIndex()andisDefaultValue()have no equivalent andgetReason()returns aStringrather than anEvaluationReason. - org.openrewrite.featureflags.launchdarkly.MigrateLDClientLifecycle: Migrate
LDClientlifecycle calls:close()becomesOpenFeatureAPI.getInstance().shutdown()andisInitialized()becomesOpenFeatureAPI.getInstance().getClient().getProviderState() == ProviderState.READY. OpenFeature manages provider state globally rather than per client instance, so the original receiver is dropped. - org.openrewrite.featureflags.launchdarkly.MigrateLDClientToOpenFeature: Replace
new LDClient(...)withOpenFeatureAPI.getInstance().getClient(). When the client is assigned to a local variable, the one-time provider bootstrapOpenFeatureAPI.getInstance().setProviderAndWait(new Provider(...))is generated from the original SDK key and configuration. In other positions (such as fields) the original configuration is preserved in aTODOcomment instead, as a statement cannot be inserted there. - org.openrewrite.featureflags.launchdarkly.MigrateLDContextToEvaluationContext: Convert
LDContext.create(...)andLDContext.builder(...)construction to OpenFeature'sMutableContext, mappingname(...)andset(...)attributes toadd(...)and dropping the terminalbuild()call. Targetingkind, multi-context and private attributes are left untouched for manual review. - org.openrewrite.featureflags.launchdarkly.MigrateLDValueToValue: Migrate
jsonValueVariation/jsonValueVariationDetailto OpenFeature'sgetObjectValue/getObjectDetails(reordering the context argument to last) and convert scalarLDValue.of(...)andLDValue.ofNull()defaults todev.openfeature.sdk.Value. To keep the result compilable, this recipe is skipped for files that use the structured buildersLDValue.buildObject(),LDValue.buildArray(),LDValue.parse(...)orLDValue.of(long), which require manual migration toStructure/List<Value>. - org.openrewrite.featureflags.launchdarkly.MigrateLaunchDarklyToOpenFeature: Migrate call sites from the LaunchDarkly server SDK to the vendor-neutral OpenFeature API, backed by the LaunchDarkly OpenFeature provider. Flag evaluations are renamed and their arguments reordered (LaunchDarkly takes the context as the second argument; OpenFeature takes it last),
LDContextconstruction becomesMutableContext, andLDClientbecomesdev.openfeature.sdk.Client. The one-time provider bootstrap (OpenFeatureAPI.setProviderAndWait(...)) is intentionally left for manual configuration. - org.openrewrite.github.UpgradeOfficialGitHubActions: Upgrades actions from the official
actionsandgithuborganizations to the newest known version, working entirely offline. Each reference is upgraded while preserving its existing precision: a major version (v4) moves to the newest major, a full version (v4.1.2) to the newest full version, and a commit SHA to the latest known commit. Actions that are not official, not known, or already up to date are left untouched. - org.openrewrite.java.jackson.JsonSerializeIncludeToJsonInclude: Move the deprecated
includeattribute of FasterXML's@JsonSerializeto a separate@JsonIncludeannotation. Theincludeattribute was deprecated in Jackson 2.x and removed in Jackson 3.x; running this recipe before the Jackson 2 → 3 package rename produces a correcttools.jackson.annotation.JsonIncludeon the Jackson 3 side. - org.openrewrite.java.jackson.ReadValueUrlToOpenStream: Jackson 3.x removed every
URL-acceptingreadValueoverload fromObjectMapper. Rewrite call sites to feedURL.openStream()into the survivingreadValue(InputStream, ...)overload, which is whatreadValue(URL, ...)did internally in Jackson 2.x. The caller's checked-exception story is unchanged:URL.openStream()declaresIOException, the same checked exception the removedreadValue(URL, ...)declared. - org.openrewrite.java.migrate.CommentJava24KotlinCap: Adds an explanatory comment to Maven
pom.xmlfiles in modules that were held at Java 24 because they compile Kotlin and depend onkotlin-stdlibolder than 2.3, which cannot target Java 25 bytecode. The comment names thekotlin-stdlibversion found and the next step needed to reach Java 25. Self-healing: the comment is added while the module is at Java 24 and removed again once the module reaches a higher Java version (for instance after its Kotlin was upgraded to 2.3), so it only ever remains on modules that truly stay at Java 24 — whether a Kotlin 1.x cap or a 2.0-2.2 module whose Kotlin upgrade could not be applied. Intended to run last, scoped to modules that compile Kotlin. - org.openrewrite.java.migrate.CommentKotlinModulesCappedAtJava24: Adds an explanatory comment to Kotlin modules that remain at Java 24 after the Java 25 migration, because Kotlin before 2.3 cannot target Java 25 bytecode. This covers both a Kotlin 1.x cap (which cannot be upgraded automatically) and a Kotlin 2.0-2.2 module whose upgrade to 2.3 could not be applied. Scoped to modules that actually compile Kotlin (i.e. contain
.ktsource files); the comment is self-healing, so a module that does reach Java 25 has it removed. - org.openrewrite.java.migrate.UpgradeBuildToJava24ForKotlin1x: Kotlin versions before 2.3 only support up to Java 24, and Kotlin 1.x cannot be safely upgraded automatically because crossing the K2 compiler default introduced in Kotlin 2.0 is a source-breaking change. Such modules are therefore capped at Java 24 and annotated with an explanation. Modules already on Kotlin 2.0-2.2 are instead bumped to Kotlin 2.3 by
UpgradeKotlinForJava25so they can reach Java 25. Applies only to modules that actually compile Kotlin (i.e. contain.ktsource files), so transitivekotlin-stdlibdependencies do not trigger the cap. - org.openrewrite.java.migrate.UpgradeKotlinForJava25: Only Kotlin 2.3 and later can target Java 25 bytecode, so modules on an older Kotlin are otherwise capped at Java 24. This recipe upgrades modules that compile Kotlin (i.e. contain
.ktsource files) and are already on Kotlin 2.0, 2.1, or 2.2 up to the latest Kotlin 2.3, so they can subsequently be migrated to Java 25. Modules on Kotlin 1.x are left untouched, as crossing the K2 compiler default introduced in Kotlin 2.0 is a source-breaking change that should not be applied automatically. As a safety net the module is also floored at Java 24: if the Kotlin upgrade cannot be applied (for instance because the version is managed externally by a parent or BOM), the module still lands on Java 24 rather than being left behind, and is raised the rest of the way to Java 25 only once it actually reaches Kotlin 2.3. - org.openrewrite.java.migrate.jakarta.MigratePluginsForJakarta11: Update plugins to be compatible with Jakarta EE 11.
- org.openrewrite.java.migrate.jakarta.MigratePluginsForJakarta9: Update plugins to be compatible with Jakarta EE 9.
- org.openrewrite.java.migrate.jakarta.ReplaceJakartaJwsWithJakartaXmlWs: Starting with Jakarta EE 10, the standalone
jakarta.jws-apiartifact was retired and its content was merged intojakarta.xml.ws-api. This recipe replaces a declaredjakarta.jws:jakarta.jws-apidependency in place withjakarta.xml.ws:jakarta.xml.ws-api, and addsjakarta.xml.ws:jakarta.xml.ws-apidirectly whenjakarta.jwswas only available transitively. - org.openrewrite.java.migrate.jakarta.UpgradeMavenEjbPluginConfiguration: Updates the
<ejbVersion>configuration ofmaven-ejb-pluginto4.0when the current value (or its resolved Maven property) indicates EJB 3.x. Handles the common pattern where<ejbVersion>is coupled to thejavax.ejb-apidependency version via a shared property, decoupling them after migration. - org.openrewrite.java.migrate.lang.ExtractExplicitConstructorInvocationArguments: JEP 513 allows statements before an explicit
super(..)orthis(..)constructor invocation. When such a call computes one of its arguments through a method invocation or object creation, this recipe extracts the non-trivial arguments into local variables declared right before the call, surfacing the work done before construction.
This is a strictly behavior-preserving transformation: argument expressions are already evaluated before the delegate constructor body runs, and such an argument can never reference the instance under construction, so hoisting them into preceding statements changes neither the order of side effects nor the set of legal references. Arguments are extracted in their original left-to-right order, and trivial arguments (literals and local variable references, which have no side effects) are left in place. Statements that follow the constructor invocation are deliberately not moved, as reordering them relative to the delegate constructor's side effects could change behavior.
- org.openrewrite.java.testing.assertj.DecomposeConjunctionAssertion: Split
assertThat(a && b).isTrue()into separateassertThat(a).isTrue()andassertThat(b).isTrue()statements, so each condition is asserted (and reported) on its own. This lets the dedicated assertion recipes simplify each conjunct, andCollapseConsecutiveAssertThatStatementsfuse them back into a single chain when the actual is a plain expression. Only the directassertThat(...).isTrue()form is decomposed;isFalse()is left alone, as negating a conjunction is not equivalent to negating each conjunct. - org.openrewrite.java.testing.assertj.SimplifyArrayLengthAssertion: Replace
assertThat(array.length)size assertions with the dedicated array assertions, such asassertThat(array).hasSize(n),assertThat(array).isEmpty()andassertThat(array).hasSameSizeAs(other). Works for both object and primitive arrays. - org.openrewrite.java.testing.assertj.SimplifyAssertJInstanceOfAssertion: Replace
assertThat(x instanceof Type).isTrue()with the dedicatedassertThat(x).isInstanceOf(Type.class), and the negated andisFalse()variants withisNotInstanceOf, so failures describe the actual type rather than justexpected true but was false. - org.openrewrite.java.testing.assertj.SimplifyAssertJNullRelatedAssertion: Replace
assertThat(x == null).isTrue()and its variants with the dedicatedassertThat(x).isNull()/assertThat(x).isNotNull(). Beyond being more expressive, this avoids the compilation error that results when thenullliteral ends up as theassertThatargument (e.g.assertThat(null == x).isTrue()becomingassertThat(null).isSameAs(x)). - org.openrewrite.java.testing.assertj.SimplifyHasSizeFromIsEqualToAssertion: Replace
assertThat(<int literal>).isEqualTo(collection.size())style assertions with the dedicatedassertThat(collection).hasSize(<int literal>). Only the structural size form is rewritten, where the comparison is on a primitiveintand reversing the assertion is behavior-preserving (unlike arbitraryisEqualToobject comparisons, which rely onequals). - org.openrewrite.java.testing.junit5.ImplausibleTimeoutToMinutes: JUnit Jupiter's
@Timeoutdefaults toTimeUnit.SECONDS, so a value such as@Timeout(10000)is interpreted as almost three hours, which is most likely a mistake where milliseconds were intended. This recipe rewrites such implausibly large second-based timeouts to the equivalent number of minutes, for instance@Timeout(value = 167, unit = TimeUnit.MINUTES), preserving the original (likely erroneous) semantics while making the mistake far more visible for review. - org.openrewrite.java.testing.mockito.PowerMockWhiteboxGetFieldToJavaReflection: Replace
Whitebox.getField(Class, String)withClass.getDeclaredField(String)plussetAccessible(true). Unlike PowerMock,getDeclaredFielddoes not traverse the class hierarchy for fields inherited from a superclass. - org.openrewrite.java.testing.mockito.PowerMockWhiteboxGetMethodToJavaReflection: Replace
Whitebox.getMethod(Class, String, Class...)withClass.getDeclaredMethod(String, Class...)plussetAccessible(true). Unlike PowerMock,getDeclaredMethoddoes not traverse the class hierarchy; calls passing an explicitClass[]array are left unchanged for manual migration. - org.openrewrite.java.testing.mockito.PowerMockWhiteboxInvokeConstructorToJavaReflection: Replace
Whitebox.invokeConstructor(..)withjava.lang.reflect.Constructorlookup andnewInstance()on the named class. Constructor parameter types are taken from the unambiguously resolved constructor, falling back to each argument's compile-time class; arrays passed to theObject...varargs overload are left unchanged for manual migration. - org.openrewrite.java.testing.testng.TestNgAssertEqualsDeepToAssertThat: Convert TestNG-style
assertEqualsDeep()andassertNotEqualsDeep()to AssertJ'sassertThat().usingRecursiveComparison().isEqualTo()/.isNotEqualTo(), which performs a deep, recursive comparison of theMap/Setcontents. - org.openrewrite.java.testing.testng.TestNgAssertEqualsNoOrderToAssertThat: Convert TestNG-style
assertEqualsNoOrder()to AssertJ'sassertThat().containsExactlyInAnyOrder()(arrays) orassertThat().containsExactlyInAnyOrderElementsOf()(collections). - org.openrewrite.java.testing.testng.TestNgAssertListToAssertThat: Convert TestNG-style
assertListContainsObject/assertListNotContainsObjectto AssertJ'sassertThat().contains()/.doesNotContain(), andassertListContains/assertListNotContains(predicate-based) to.anyMatch()/.noneMatch(). - org.openrewrite.java.testing.testng.TestNgAssertNotSameToAssertThat: Convert TestNG-style
assertNotSame()to AssertJ'sassertThat().isNotSameAs(). - org.openrewrite.java.testing.testng.TestNgAssertSameToAssertThat: Convert TestNG-style
assertSame()to AssertJ'sassertThat().isSameAs(). - org.openrewrite.java.testing.testng.TestNgAssertThrowsToAssertThat: Convert TestNG-style
assertThrows()andexpectThrows()to AssertJ'sassertThatExceptionOfType().isThrownBy()(orassertThatThrownBy()when no exception type is given) to allow for chained assertions on the thrown exception. - org.openrewrite.staticanalysis.AllBranchesIdentical: When every branch of an
if/elsechain executes the same code, the condition serves no purpose and the code block can be used directly. - org.openrewrite.staticanalysis.CollapsibleIfStatements: When an
ifstatement body contains only anotherifwith noelse, the two conditions can be combined with&&. Merging the conditions reduces nesting and makes the code easier to read. - org.openrewrite.staticanalysis.MergeIdenticalBranches: When two consecutive branches of an
if/else ifchain execute the same code, they can be merged by combining their conditions with||. This removes duplication and makes the intent clearer. - org.openrewrite.staticanalysis.RemoveDuplicateConditions: When an
if/else ifchain contains the same condition more than once, the second branch can never execute because the first matching branch always wins. The duplicate branch is dead code and should be removed. - org.openrewrite.staticanalysis.RemoveSelfAssignment: Self-assignments such as
x = xhave no effect and indicate a copy-paste error or typo where the left-hand or right-hand side should reference a different variable. - org.openrewrite.staticanalysis.RemoveUnconditionalValueOverwrite: When
map.put(key, value)is called twice in a row with the same key, the first call is dead code because its value is immediately overwritten. Remove the first call to make the intent clear. - org.openrewrite.staticanalysis.RemoveUnreachableMultiCatchAlternative: When an earlier
catchclause already covers a type, any latercatch(including a multi-catch alternative) for the same type or a subtype is unreachable and is a Java compile error. This commonly appears after type-substitution migrations (for example, renaming an exception so that twocatchclauses end up overlapping). This recipe drops the unreachable alternatives from later multi-catches, collapses a multi-catch to a regularcatchwhen only one alternative remains, and removes the entirecatchclause when all of its declared types are already covered. - org.openrewrite.staticanalysis.SimplifyRedundantLogicalExpression: When the same expression appears on both sides of
&&,||,&, or|, the result is always equal to that expression. For example,x && xis always justx. This is typically a copy-paste error where one side should have been different. - org.openrewrite.staticanalysis.UseStringCaseInsensitiveOrderRecipes: Replaces case-insensitive string comparator lambdas and method references with the JDK constant
String.CASE_INSENSITIVE_ORDER. Improves readability and removes one closure allocation per call site. - org.openrewrite.staticanalysis.UseStringCaseInsensitiveOrderRecipes$FromLambdaRecipe: Replace
(a, b) -> a.compareToIgnoreCase(b)withString.CASE_INSENSITIVE_ORDERwhen used as aComparator<String>. - org.openrewrite.staticanalysis.UseStringCaseInsensitiveOrderRecipes$FromMethodReferenceRecipe: Replace the method reference
String::compareToIgnoreCasewithString.CASE_INSENSITIVE_ORDERwhen used as aComparator<String>.
Removed Recipes
- io.axoniq.framework.migration.Axon4ToAxoniq5AxonServerConnector: Relocates the Axon Server connector from
org.axonframework.axonserver.connectortoio.axoniq.framework.axonserver.connector. The connector now lives in the Axoniq commercial offering (io.axoniq.framework:axon-server-connector). Class names are mostly preserved. - io.axoniq.framework.migration.Axon4ToAxoniq5Bom: Replaces the imported
org.axonframework:axon-bom(AF4) ororg.axonframework:axon-framework-bom(free AF5) in<dependencyManagement>with the Axoniq Framework 5 commercial BOMio.axoniq.framework:axoniq-framework-bom. - io.axoniq.framework.migration.Axon4ToAxoniq5DeadLetter: Relocates the Sequenced Dead-Letter Queue (DLQ) types from the open-source
axon-messagingmodule to the Axoniq commercialaxoniq-dead-lettermodule (io.axoniq.framework:axoniq-dead-letter). Class names — includingSequencedDeadLetterQueue,JpaSequencedDeadLetterQueue,JdbcSequencedDeadLetterQueue,DeadLetteredEventProcessingTask,EnqueuePolicy,Decisions,ThrowableCause— are preserved. - io.axoniq.framework.migration.Axon4ToAxoniq5DistributedMessaging: Relocates the distributed command-bus components (DistributedCommandBus, CommandBusConnector) from the AF4 open-source
axon-messagingmodule into the Axoniq commercialaxoniq-distributed-messagingmodule (io.axoniq.framework.messaging.commandhandling.distributed). Each AF4 fully-qualified name is mapped directly to its final Axoniq location, so this recipe is order-independent relative to the open-source messaging package rename. - io.axoniq.framework.migration.Axon4ToAxoniq5EventStreaming: Placeholder. The Axoniq event streaming module (
io.axoniq.framework:axoniq-event-streaming) consolidates multi-stream event consumption that lived inMultiStreamableMessageSource(available since Axon Framework 4.2) into a dedicated module in Axoniq Framework 5. AF4 applications usingMultiStreamableMessageSourceshould migrate toaxoniq-event-streamingonce they adopt Axoniq Framework 5; this recipe will gain class-level mappings as that migration becomes deterministic. - io.axoniq.framework.migration.Axon4ToAxoniq5SpringBoot: Swaps the Spring Boot starter dependency to the Axoniq commercial variant (
io.axoniq.framework:axoniq-spring-boot-starter). Accepts both the AF4 raw coordinate (org.axonframework:axon-spring-boot-starter) and the post-Axon4ToAxon5SpringBootExtensioncoordinate (org.axonframework.extensions.spring:axon-spring-boot-starter). Class-level mappings for the Axoniq autoconfig packageio.axoniq.framework.springboot.*are not yet implemented. - io.axoniq.framework.migration.Axon4ToAxoniq5Testcontainer: Relocates the Axon Server Testcontainer types from the AF4
axon-testpackageorg.axonframework.test.serverto the dedicated Axoniq commercial artifactio.axoniq.framework:axoniq-testcontainerunderio.axoniq.framework.testcontainer. The Enterprise (AxonServerEEContainer) and Standard (AxonServerSEContainer) edition variants both collapse into the unifiedAxonServerContainerin Axoniq 5. - io.axoniq.framework.migration.UpgradeAxon4ToAxoniq5: Migrates an Axon Framework 4.x application to Axoniq Framework 5 (commercial). Composes
UpgradeAxon4ToAxon5(the free leg) and then layers commercial-only migrations: BOM swap toio.axoniq.framework:axoniq-framework-bom, Spring Boot starter swap toio.axoniq.framework:axoniq-spring-boot-starter, source rewrites and Maven adds for Axon Server connector, sequenced dead-letter queue, and distributed messaging. - org.axonframework.migration.AddAxonTestFixtureTearDown: Adds an
@AfterEach tearDown()method callingstop()on theAxonTestFixturefield, when the test class has such a field but no existing@AfterEachmethod (and no method namedtearDown). Pairs withMigrateAggregateTestFixtureSetupwhich produces the field; the tear-down step was previously left for manual migration. Java sources only. - org.axonframework.migration.AddCommandAnnotation: Scans @CommandHandler methods and annotates their command parameter types with @Command. Also migrates @RoutingKey on a field to @Command(routingKey = "fieldName") on the class, removing the @RoutingKey field annotation.
- org.axonframework.migration.AddEntityCreatorAnnotation: Annotates existing no-arg constructors with
@EntityCreatorfor any class annotated with@EventSourcedEntityor the Spring@EventSourcedstereotype. Required by AF5 — the framework uses this annotation to instantiate the entity before applying events. Idempotent: skips constructors that are already annotated. - org.axonframework.migration.AddEventAnnotation: Scans @EventSourcingHandler methods and annotates their event parameter types with @Event. Migrates @Revision("x") on the class to @Event(version = "x"), removing the now-obsolete @Revision annotation.
- org.axonframework.migration.AddEventTagAnnotation: Scans event-sourced entity classes for their @AggregateIdentifier field and the event types used in @EventSourcingHandler methods, then annotates the corresponding field in each event class with @EventTag(key = "<EntitySimpleName>").
- org.axonframework.migration.AnnotateObsoleteSequencingPolicyProperty: Inserts a one-line
# TODO(axon4to5): ...comment above anyaxon.eventhandling.processors.<group>.sequencing-policyentry inapplication.properties/application.yml. AF5 moves the decision onto the handler class via@SequencingPolicy; deleting the property here would race the per-construct skill that drives the source-side annotation, so this recipe only annotates. Idempotent. - org.axonframework.migration.Axon4ToAxon5AmqpExtension: Placeholder for the AMQP extension migration. The AMQP extension lives at
org.axonframework.extensions.amqpin AF4 and does not yet have a finalized Axon Framework 5 equivalent. Update this recipe once the AF5 AMQP integration ships. - org.axonframework.migration.Axon4ToAxon5Bom: Renames the imported
org.axonframework:axon-bomBOM in<dependencyManagement>toorg.axonframework:axon-framework-bomand pins the imported version to the current Axon Framework 5 release. The BOM artifactId changed between Axon Framework 4 and Axon Framework 5; the groupId is unchanged. - org.axonframework.migration.Axon4ToAxon5CdiExtension: Placeholder for the CDI extension migration. The extension lives at
org.axonframework.extensions.cdiin AF4 and does not yet have a finalized Axon Framework 5 equivalent. Update this recipe once the AF5 CDI integration ships. - org.axonframework.migration.Axon4ToAxon5Common: Migrates
org.axonframework.configtoorg.axonframework.common.configuration, renamesConfigurerModuletoConfigurationEnhancer,ModuleConfigurationtoModule,LifecycleOperationstoLifecycleRegistry, relocatesEventProcessingConfigurerunder the messaging.eventhandling namespace, and swaps@ProcessingGroupfor the AF5@Namespaceannotation. - org.axonframework.migration.Axon4ToAxon5Conversion: Migrates the Serializer-based
org.axonframework.serializationnamespace to the new Converter-basedorg.axonframework.conversionnamespace. Note: this is a package rename; concrete renames such asJacksonSerializertoJacksonConverterare NOT applied here and must be handled separately. - org.axonframework.migration.Axon4ToAxon5EventSourcing: Relocates the
@EventSourcingHandlerannotation intoeventsourcing.annotation, relocatesSnapshotterinto the neweventsourcing.snapshot.apiAPI package, ensures theorg.axonframework:axon-eventsourcingdependency is present when the app uses event-sourcing types (the AF5 Spring Boot starter no longer pulls it transitively, so apps not using the BOM need it added explicitly — it transitively bringsaxon-modellingandaxon-messaging), and applies the source-level aggregate→entity rewrites — annotating no-arg constructors with the now-mandatory@EntityCreatorand replacingAggregateLifecycle.apply(...)with an injectedEventAppender#append(...). - org.axonframework.migration.Axon4ToAxon5JGroupsExtension: Placeholder for the JGroups extension migration. The JGroups extension at
org.axonframework.extensions.jgroupsprovided distributed command bus routing in AF4. In Axon Framework 5 the distributed command bus has moved into the AxonIQ commercial offering (io.axoniq.framework:axoniq-distributed-messaging). Code usingJGroupsConnectormust be replaced with the AxonIQ commercial distributed messaging APIs. - org.axonframework.migration.Axon4ToAxon5KafkaExtension: Placeholder for the Kafka extension migration. The Kafka extension lives at
org.axonframework.extensions.kafkain AF4 and does not yet have a finalized Axon Framework 5 equivalent. Update this recipe once the AF5 Kafka integration ships. - org.axonframework.migration.Axon4ToAxon5Messaging: Migrates the messaging core (command, event, query handling) from
org.axonframework.{command,event,query}handlinginto theorg.axonframework.messaging.*namespace, relocates handler & interceptor annotations into their.annotation.*subpackages, renamesEventBustoEventSink, fixesMetaDatacasing toMetadata, relocates the top-level messaging API (Message,Metadata,UnitOfWork,MessageHandlerInterceptor,MessageHandlerInterceptorChain,correlation.*) intomessaging.core.*, moves the sequencing policy package out ofeventhandling.asyncintomessaging.core.sequencing, relocatestokenstoreand the replay/reset annotations under their AF5 subpackages, and movesQueryGatewayinto its own gateway subpackage. - org.axonframework.migration.Axon4ToAxon5MetricsDropwizardExtension: Relocates
org.axonframework.metricstoorg.axonframework.extension.metrics.dropwizard, reflecting the move from a flatmetricsnamespace to a per-provider layout underextension.metrics.*. - org.axonframework.migration.Axon4ToAxon5MetricsMicrometerExtension: Relocates
org.axonframework.micrometertoorg.axonframework.extension.metrics.micrometer, reflecting the move into the per-providerextension.metrics.*layout. - org.axonframework.migration.Axon4ToAxon5Modelling: Migrates the modelling layer from the
aggregatevocabulary to theentityvocabulary: relocatesorg.axonframework.modelling.commandtoorg.axonframework.modelling.entity, renamesTargetAggregateIdentifiertoTargetEntityId,AggregateMembertoEntityMember,Repositoryintomodelling.repository, andCommandTargetResolvertoEntityIdResolver. Strips AF4-only modelling annotations (@AggregateIdentifier,@CreationPolicy) that have no AF5 successor — id resolution moved onto commands via@TargetEntityId, and the AF4 creation-policy semantics map onto static command handlers in AF5 (a manual rewrite the recipe cannot infer beyond removing the annotation itself). - org.axonframework.migration.Axon4ToAxon5MongoExtension: Placeholder for the Mongo extension migration. The Mongo extension lives at
org.axonframework.extensions.mongoin AF4 and does not yet have a finalized Axon Framework 5 equivalent. Update this recipe once the AF5 Mongo integration ships. - org.axonframework.migration.Axon4ToAxon5MultitenancyExtension: Placeholder for the Multitenancy extension migration. The extension lives at
org.axonframework.extensions.multitenancyin AF4 and does not yet have a finalized Axon Framework 5 equivalent. Update this recipe once the AF5 multitenancy story ships. - org.axonframework.migration.Axon4ToAxon5QueryResponseTypes: On two-argument
queryGateway.query(payload, ResponseType)calls, unwraps the AF4ResponseTypes.instanceOf(...)/optionalInstanceOf(...)/multipleInstancesOf(...)wrapper to the plainClass<R>form AF5 expects, and renamesquery(payload, multipleInstancesOf(R.class))toqueryMany(payload, R.class). Three-argumentquery(String, Object, ...)forms,subscriptionQuery(...), andstreamingQuery(...)are left untouched so the per-construct migration skill keeps the AF4 fingerprints it needs for design decisions. RemovesResponseType/ResponseTypesimports only when no references remain. - org.axonframework.migration.Axon4ToAxon5ReactorExtension: Relocates
org.axonframework.extensions.reactor.*toorg.axonframework.extension.reactor.*(singularextension) and inserts themessaging.segment in front of thecommandhandling,eventhandling, andqueryhandlingsubpackages. The bareextensions.reactor.messaging.*package (which holdsReactorMessageDispatchInterceptorand the interceptor chain) is moved underextension.reactor.messaging.core.*. - org.axonframework.migration.Axon4ToAxon5SpringAotExtension: The
org.axonframework.extensions.spring-aot:axon-spring-aotextension has no Axon Framework 5 port. Removes the dependency so the project compiles against AF5. Projects that need Spring AOT / native-image support against AF5 must reintroduce equivalent functionality manually — there is no drop-in replacement. - org.axonframework.migration.Axon4ToAxon5SpringBootActuatorExtension: Relocates
org.axonframework.actuatortoorg.axonframework.extension.springboot.actuator. The Actuator support is now nested under the Spring Boot extension namespace. - org.axonframework.migration.Axon4ToAxon5SpringBootExtension: Relocates
org.axonframework.springboottoorg.axonframework.extension.springboot, matching the Maven groupId move toorg.axonframework.extensions.spring. Covers both the autoconfigure and starter artifacts (apps depend on the starter, which transitively pulls autoconfigure). Also rewrites Spring Boot configuration property keys whose binding class moved or was renamed in AF5. - org.axonframework.migration.Axon4ToAxon5SpringCloudExtension: Placeholder for the Spring Cloud extension migration. The Spring Cloud extension at
org.axonframework.extensions.springcloudprovided distributed command bus routing in AF4. In Axon Framework 5 the distributed command bus has moved into the AxonIQ commercial offering (io.axoniq.framework:axoniq-distributed-messaging). Code usingSpringCloudCommandRoutermust be replaced with the AxonIQ commercial distributed messaging APIs. - org.axonframework.migration.Axon4ToAxon5SpringExtension: Relocates
org.axonframework.springtoorg.axonframework.extension.springand renames the Spring stereotype@Aggregateto@EventSourced. The stereotype rename is mapped from both the AF4 location and the post-package- move location, so the recipe is order-independent. - org.axonframework.migration.Axon4ToAxon5Test: Renames
AggregateTestFixtureandSagaTestFixtureto the unifiedAxonTestFixtureintroduced in Axon Framework 5, and rewrites AF4-style flat fixture call chains (fixture.given(...).when(...).expectEvents(...)) to the AF5 fluent given/when/then API (fixture.given().events(...).when().command(...).then().events(...)). Also generates an@AfterEach tearDown()callingfixture.stop()on test classes that declare anAxonTestFixturefield but have no existing@AfterEach. Targets theaxon-testMaven artifact. Hamcrest matcher conversions and Kotlin@AfterEachinsertion remain manual. - org.axonframework.migration.Axon4ToAxon5TracingOpenTelemetryExtension: Placeholder for the OpenTelemetry tracing extension migration. Revisioning of the distributed tracing extension for Axon Framework 5 is slated for a later release (see issue #3594). Update this recipe once the AF5 OpenTelemetry tracing integration ships.
- org.axonframework.migration.Axon4ToAxon5TracingOpenTracingExtension: Placeholder. The OpenTracing tracing extension at
org.axonframework.extensions.tracingis superseded by the OpenTelemetry tracing extension in Axon Framework 5 (seeAxon4ToAxon5TracingOpenTelemetryExtension). Code using OpenTracing must be migrated to OpenTelemetry manually. - org.axonframework.migration.ConfigureEventSourcedAnnotation: Adds explicit tagKey = "<EntitySimpleName>" and idType = <ResolvedType>.class to @EventSourced annotations that have no tagKey set. The tagKey is derived from the class simple name (matching the AF5 default). The idType is deduced from the type of the field annotated with @AggregateIdentifier in AF4. When that field is absent (e.g. POJO aggregate without an explicit identifier field) the idType falls back to Object.class and is flagged with a TODO(axon4to5): comment.
- org.axonframework.migration.ConvertCommandHandlerConstructorToCompanionObject: Rewrites Kotlin
@CommandHandler constructor(...)declarations intocompanion object { @JvmStatic @CommandHandler fun handle(...) }on the same class, matching the AF5 contract where@CommandHandlerno longer targets constructors. Parameter list and method body are preserved. - org.axonframework.migration.ConvertCommandHandlerConstructorToStaticMethod: Rewrites Axon Framework 4
@CommandHandlerconstructors intopublic static void handle(...)methods, matching the AF5 contract where@CommandHandlerno longer targets constructors. Parameter list and method body are preserved. - org.axonframework.migration.MigrateAggregateTestFixtureSetup: Rewrites
new AggregateTestFixture<X>(X.class)(the AF4 aggregate-fixture constructor) to AF5'sAxonTestFixture.with(EventSourcingConfigurer.create().registerEntity(EventSourcedEntityModule.autodetected(<IdType>.class, X.class))). The aggregate type X is read from the class-literal constructor argument; the id type is looked up via the cross-recipe map populated by AddEventTagAnnotation (while @AggregateIdentifier is still on the source). Only matches the AF4 AggregateTestFixture FQN — SagaTestFixture setups are left for manual migration. - org.axonframework.migration.MigrateAxonTestFixtureFluentApi: Rewrites the flat AF4
fixture.given(...).when(...).expectEvents(...)call shape to the AF5 fluentfixture.given().events(...).when().command(...).then().events(...)shape, including the leaf-method renames (expectNoEvents→noEvents,expectSuccessfulHandlerExecution→success,expectException+expectExceptionMessage→ singleexception(cls, msg), etc.). The fixture setup migration (constructor →AxonTestFixture.with(configurer),@AfterEach stop()) and Hamcrest matcher conversions stay manual. - org.axonframework.migration.MigrateCommandGatewayInEventHandler: Inside every
@EventHandlermethod in the class, rewrites calls of the formcommandGateway.send(...)/commandGateway.sendAndWait(...)(wherecommandGatewayis a class-levelCommandGatewayfield) tocommandDispatcher.send(...)on a method-levelCommandDispatcherparameter — adding the parameter when missing. Forvoidhandlers whose body is a single dispatch expression or a single try/catch with one dispatch per branch, the return type is widened toCompletableFuture<?>and the dispatch is converted toreturn ... .getResultMessage();. Once no other references to the gateway field remain, the field, its constructor parameter, and the matching assignment are removed. - org.axonframework.migration.MigrateKotlinDslBomImport: Swaps the
groupId:artifactIdprefix of a Spring Dependency ManagementmavenBom("g:a:${property("...")}")call in abuild.gradle.ktsscript, leaving the${property(...)}indirection in place. Optionally updates the literal value of the matchingextra["..."]declaration so the version follows the new BOM. Targets a gap ingradle.ChangeManagedDependencywhere the Kotlin string-template variant ofproperty(...)is not recognized. - org.axonframework.migration.MigrateMessageInterceptorSignatures: Rewrites the method signatures of
MessageHandlerInterceptorandMessageDispatchInterceptorimplementations to their AF5 shape:handle(UnitOfWork, InterceptorChain) -> ObjectbecomesinterceptOnHandle(M, ProcessingContext, MessageHandlerInterceptorChain<M>) -> MessageStream<?>(and similarly for the dispatch interceptor). The method body is left untouched — the droppedunitOfWork/interceptorChainreferences become compile errors, surfacing every call site that needs review. A class-level// TODO(axon4to5):comment points to the migration path doc. The message typeMis read from theimplementsclause; raw implementations fall back toMessage. Runs after the AF4 -> AF5 FQN renames. - org.axonframework.migration.MigrateSequencingPolicyLambda: Rewrites single-argument
SequencingPolicylambdas (e -> body) to the AF5 shape(e, ctx) -> Optional.ofNullable(body). The AF5SequencingPolicy.sequenceIdentifierFormethod takes both a message and aProcessingContext, and returnsOptional<Object>instead of a nullableObject. Adds thejava.util.Optionalimport. Leaves block-body lambdas, multi-parameter lambdas, and anonymous inner classes alone — those need manual rewriting since the AF4 method name (getSequenceIdentifierFor) and the AF5 method name (sequenceIdentifierFor) differ. - org.axonframework.migration.MigrateSnapshotTriggerDefinitionToAnnotation: Replaces AF4 Spring Boot @Bean methods returning SnapshotTriggerDefinition with the AF5 @Snapshotting annotation on the corresponding aggregate class. EventCountSnapshotTriggerDefinition maps to afterEvents; AggregateLoadTimeSnapshotTriggerDefinition maps to afterSourcingTime. Custom implementations leave a TODO comment for manual review.
- org.axonframework.migration.RemoveTypeArguments: Removes the generic type arguments (
<...>) from any usage of the configured fully-qualified type. Preserves the underlying type reference and its surrounding context (variables, parameters, return types, generic bounds, etc.). - org.axonframework.migration.ReplaceAggregateLifecycleApply: Replaces every
AggregateLifecycle.apply(X)(statically imported or via the class) witheventAppender.append(X), injecting anEventAppender eventAppenderparameter into the enclosing method when one is not already declared. Drops the staticapplyimport once no usages remain. - org.axonframework.migration.UpgradeAxon4ToAxon5: Migrates an Axon Framework 4.x application to free (Apache 2.0) Axon Framework 5. Bumps the Axon Framework dependency versions, applies per-module rename recipes (one per core framework module), and renames Maven coordinates within the
org.axonframework.*namespace. Does NOT touch features dropped from free AF5 (Axon Server, DLQ, DistributedCommandBus) — seeUpgradeAxon4ToAxoniq5for the commercial path. - org.axonframework.migration.UpgradeJava: Bumps the Java compiler target in pom.xml/build.gradle to the configured LTS (defaults to 21, the Axon Framework 5 minimum). No-op for modules already at or above the target — projects already on a higher Java release are left untouched.
- org.axonframework.migration.UpgradeKotlin: Bumps the
org.jetbrains.kotlin:*dependency versions and thekotlin-maven-pluginto the configured Kotlin line (defaults to "2.x", the latest Kotlin 2.x). No-op for modules already at or above the target — the underlying upgrade recipes never downgrade. Rejects targets below Kotlin 2.0. - org.openrewrite.java.migrate.UpgradeBuildToJava24: Kotlin versions before 2.3 only support up to Java 24. Applies only to modules that actually compile Kotlin (i.e. contain
.ktsource files), so transitivekotlin-stdlibdependencies do not trigger the cap.
Changed Recipes
- org.openrewrite.github.ChangeAction was changed:
- Old Options:
newAction: { type: String, required: true }newVersion: { type: String, required: true }oldAction: { type: String, required: true }
- New Options:
newAction: { type: String, required: true }newVersion: { type: String, required: true }oldAction: { type: String, required: true }oldSha: { type: String, required: false }
- Old Options:
- org.openrewrite.github.ChangeActionVersion was changed:
- Old Options:
action: { type: String, required: true }version: { type: String, required: true }
- New Options:
action: { type: String, required: true }oldSha: { type: String, required: false }version: { type: String, required: true }
- Old Options: