Skip to content

UpgradeDependencyVersion does not update a <dependencyManagement> entry in a parent POM following ChangeDependency in the same run #8145

Description

@evie-lau

What version of OpenRewrite are you using?

I am using

  • OpenRewrite v8.86.0-SNAPSHOT
  • rewrite-migrate-java v3.39.0-SNAPSHOT

How are you running OpenRewrite?

Originally Maven plugin on a multi-module project. Discovered in rewrite-migrate-java module, but issue seems to lie with the underlying recipes here in rewrite.

Recreated in a simpler test in rewrite-migrate-java for EE10 testing.

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

Criteria

  1. multi-module project (this same test in a single-module project passed)
  2. Chaining ChangeDependency followed by UpgradeDependencyVersion

Resulting problems

  1. Parent POM only gets version upgrade from ChangeDependency, does not get upgrade from following UpgradeDependencyVersion
  2. Child POM gets new version added to it from UpgradeDependencyVersion

Files to reproduce

Multi-module maven project.

Parent POM:

<project>
    <groupId>com.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>child</module>
    </modules>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

Child POM:

<project>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>child</artifactId>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <!-- no <version> — inherited from parent dependencyManagement -->
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Run Jakarta EE10 recipe, which runs EE9 recipes first

  • EE9 runs ChangeDependency for javax -> jakarta artifacts
  • EE10 runs UpgradeDependencyVersion for many of the same artifacts that got modified from EE9 recipe

Alternatively, specifying the individual recipes in a test:

rewriteRun(
    spec -> spec.recipes(
    // Phase 1: rename javax → jakarta (EE9 migration)
    new ChangeDependency(
        "javax.servlet", "javax.servlet-api",
        "jakarta.servlet", "jakarta.servlet-api",
        "5.0.x", null, null, null),
    // Phase 2: bump jakarta EE9 → EE10
    new UpgradeDependencyVersion(
        "jakarta.servlet", "jakarta.servlet-api",
        "6.0.x", null, null, null)
    ),
...

What did you expect to see?

  1. Parent pom should upgrade from 4.0.0 to 6.0.x
<project>
    <groupId>com.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>child</module>
    </modules>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>6.0.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
  1. Child pom unchanged

What did you see instead?

  1. Parent POM stuck at EE9 level (5.0.0)
<project>
    <groupId>com.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <version>5.0.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
  1. Child POM got <version> tag added instead of upgrading parent POM
<project>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>child</artifactId>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>6.0.0</version>
            <!-- no <version> — inherited from parent dependencyManagement -->
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Reproduction

In JakartaEE10Test. This will use the EE10 recipe. Optionally use the recipe spec defined above

    @Test
    void ee10UpgradesShouldUpdateParentDependencyManagementWhenChildHasNoVersion() {
        rewriteRun(
          mavenProject("parent",
            //language=xml
            pomXml(
              """
                <project>
                    <groupId>com.example</groupId>
                    <artifactId>parent</artifactId>
                    <version>1.0-SNAPSHOT</version>
                    <packaging>pom</packaging>
                    <modules>
                        <module>child</module>
                    </modules>
                    <dependencyManagement>
                        <dependencies>
                            <dependency>
                                <groupId>javax.servlet</groupId>
                                <artifactId>javax.servlet-api</artifactId>
                                <version>4.0.0</version>
                                <scope>provided</scope>
                            </dependency>
                        </dependencies>
                    </dependencyManagement>
                </project>
                """,
              spec -> spec.after(pom ->
                assertThat(pom)
                  .as("Phase 1 rename applied: no javax coords").doesNotContain("javax.servlet")
                  .as("EE9 version not present in parent").doesNotContain("5.0.")
                  .as("EE10 version present in parent dependencyManagement").containsPattern("6\\.0\\.\\d+")
                  .actual())
            )
          ),
          mavenProject("child",
            //language=xml
            pomXml(
              """
                <project>
                    <parent>
                        <groupId>com.example</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0-SNAPSHOT</version>
                    </parent>
                    <artifactId>child</artifactId>
                    <dependencies>
                        <dependency>
                            <groupId>javax.servlet</groupId>
                            <artifactId>javax.servlet-api</artifactId>
                            <!-- no <version> — inherited from parent dependencyManagement -->
                            <scope>provided</scope>
                        </dependency>
                    </dependencies>
                </project>
                """,
              spec -> spec.after(pom ->
                assertThat(pom)
                  .as("Phase 1 rename applied in child").doesNotContain("javax.servlet")
                  .as("Child should not have an explicit version tag").doesNotContainPattern("<version>6\\.0\\.\\d+</version>")
                  .as("Child uses jakarta coords").contains("jakarta.servlet", "jakarta.servlet-api")
                  .actual())
            )
          )
        );
    }

Can comment out the EE9/EE10 assertions on parent POM to see the output for child POM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions