Skip to content

Make three Spring migration recipes converge in a single cycle - #1192

Merged
knutwannheden merged 1 commit into
mainfrom
fix-non-convergence-bugs-cycles-2
Oct 20, 2026
Merged

knutwannheden merged 1 commit into
mainfrom
fix-non-convergence-bugs-cycles-2

Conversation

@knutwannheden

Copy link
Copy Markdown
Contributor

Three recipe tests carried expectedCyclesThatMakeChanges(2): a single run of UpgradeSpringBoot_2_3, UpgradeSpringBoot_2_0 (via MigrateLocalServerPortAnnotation) or UpgradeSpringCloud_2025_1 left a change for a second run. In each case a step decided from source state that an earlier step in the same cycle was about to change. None of them is iterative by design.

MigrateLocalServerPortAnnotation: drop the dependency step

Its AddDependency child added spring-boot-starter-web only if the code used the new web.server.LocalServerPort type, which exists only after this recipe's own edit. Rather than retrigger it on the old type, the step is gone, because the move needs no dependency. Both packages ship in the spring-boot artifact:

spring-boot-1.5.9.RELEASE.jar  org/springframework/boot/context/embedded/LocalServerPort.class
spring-boot-2.6.1.jar          org/springframework/boot/web/server/LocalServerPort.class

Retriggering would also have started adding starter-web in the 2.7+ chains, which move the annotation on to spring-boot-test in the same cycle. #541 was a bug in this very addition, and its test now asserts the pom is left alone.

AddSpringBootStarterValidation: match declared dependencies only

The "skip if jakarta.validation-api is present" precondition also matched the copy Boot 2.2's web starter brings in through spring-boot-starter-validation. The parent upgrade to 2.3 removes it, so the starter was added on the second cycle. #439 asked to skip when the API is declared, so the precondition now sets onlyDirect: true.

A module that declares hibernate-validator itself had been skipped through that same transitive match. A second precondition keeps skipping it. With Boot 2.3, spring-boot-starter-tomcat still brings jakarta.el, so a declared provider works without the starter.

A module whose only validation API comes transitively from some other library now gets the starter. The API alone does not enforce constraints, so that is the intended outcome.

UpgradeSpringCloud_2025_1: upgrade after swapping the parent

ChangeParentPom keeps the old parent's managed versions it would otherwise lose, e.g. spring-cloud-starter-config:4.3.0, by writing them into <dependencyManagement>. The org.springframework.cloud:* → 5.0.x upgrade ran before it and only bumped that entry on the second cycle, so it now runs after it. A multi-module build and a BOM version taken from ${spring-cloud.version} also converge in one cycle with this order.

The three tests now run with the default one cycle. shouldNotAddValidationStarterIfHibernateValidatorDeclared is new and fails without the second precondition.

- MigrateLocalServerPortAnnotation: drop the AddDependency step. It
  scanned for the type the recipe itself creates, and no dependency is
  needed: both LocalServerPort packages ship in the spring-boot artifact.
- AddSpringBootStarterValidation: the jakarta.validation-api precondition
  also matched the copy Spring Boot 2.2's web starter brings in
  transitively, which the parent upgrade removes. Match only direct
  declarations, and also skip modules that declare hibernate-validator.
- UpgradeSpringCloud_2025_1: ChangeParentPom retains the old parent's
  managed Spring Cloud versions, so upgrade org.springframework.cloud:*
  after it.

The tests no longer need expectedCyclesThatMakeChanges(2).
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Oct 20, 2026
@knutwannheden
knutwannheden merged commit 61ed1cc into main Oct 20, 2026
2 checks passed
@knutwannheden
knutwannheden deleted the fix-non-convergence-bugs-cycles-2 branch October 20, 2026 10:41
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant