Skip to content

Renaming a parent's dependencyManagement leaves child modules with a stale MavenResolutionResult #8463

Description

@timtebeek

What version of OpenRewrite are you using?

Latest main (reproduced at 560b40c).

What is the smallest, simplest way to reproduce the problem?

In a multi-module build, a child module declares a dependency without a <version> and the parent POM manages it. ChangeDependencyGroupIdAndArtifactId renames the dependency in the child and the <dependencyManagement> entry in the parent — deliberately not writing an explicit version into the child (see providedDependencyManagedByLocalParentDoesNotGetExplicitVersion, parentAndBomManagedToJustParentManaged).

That output is correct on disk, but the child document's MavenResolutionResult still holds the parent's parse-time model, in which the old coordinates are managed and the new ones are not. Any recipe that runs afterwards in the same run and calls maybeUpdateModel() on the child then re-resolves against that stale parent and fails:

rewriteRun(
  spec -> spec.recipes(
    new ChangeDependencyGroupIdAndArtifactId("com.squareup.okhttp3", "mockwebserver", null, "mockwebserver3", "5.x", null),
    new RemoveDependency("org.awaitility", "awaitility", null)),   // any recipe that updates the model
  // parent POM: <dependencyManagement> for com.squareup.okhttp3:mockwebserver
  // child POM:  <dependency> com.squareup.okhttp3:mockwebserver with no <version>
);

What did you expect to see?

No marker: after the run, the parent manages mockwebserver3 and the child resolves.

What did you see instead?

<!--~~(No version provided for direct dependency com.squareup.okhttp3:mockwebserver3:compile)~~>--><dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>mockwebserver3</artifactId>
</dependency>

Two consequences:

  1. Error markers on every child module, on POMs that are actually fine. Observed in a Moderne SaaS run of "Spring Boot 4.0 best practices": 56 markers across spring-cloud/spring-cloud-sleuth (30) and spring-projects-experimental/spring-cloud-sleuth-otel (26), all from UpgradeOkHttpMockWebServer -> ChangeDependency. The full spring-cloud-sleuth POM chain (root → teststests/brave → module) reproduces it exactly.
  2. Worse, later recipes make decisions from the stale model. AddDependency for the new coordinates sees a model that still lists the old ones and can add a second, duplicate <dependency> next to the renamed one — which is what finos/legend-shared shows for jakarta.ws.rs:jakarta.ws.rs-api.

The staleness is structural: each document has its own MavenResolutionResult, and UpdateMavenModel re-resolves a child through getProjectPoms(), which yields the parent's requested Pom as captured at parse time. Edits to the parent document do not propagate to a child document's getParent() within the same pass.

Are you interested in contributing a fix?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions