Cross-POM Alignment

DomTrip supports moving dependency versions from child POMs to a parent POM's <dependencyManagement> section, making the child dependencies version-less. Property definitions are automatically migrated or created in the parent as needed.

Aligning a Single Dependency

Move one dependency's version to the parent:

String childPom = """
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>
          <parent>
            <groupId>com.example</groupId>
            <artifactId>parent-project</artifactId>
            <version>1.0.0</version>
          </parent>
          <artifactId>child-module</artifactId>
          <dependencies>
            <dependency>
              <groupId>com.google.guava</groupId>
              <artifactId>guava</artifactId>
              <version>32.1.2-jre</version>
            </dependency>
          </dependencies>
        </project>
        """;

String parentPom = """
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.example</groupId>
          <artifactId>parent-project</artifactId>
          <version>1.0.0</version>
          <packaging>pom</packaging>
        </project>
        """;

PomEditor child = new PomEditor(Document.of(childPom));
PomEditor parent = new PomEditor(Document.of(parentPom));

// Move a single dependency's version to the parent's dependencyManagement
Coordinates guava = Coordinates.of("com.google.guava", "guava", null);
child.dependencies()
        .alignToParent(
                guava,
                parent,
                AlignOptions.builder()
                        .versionSource(AlignOptions.VersionSource.PROPERTY)
                        .namingConvention(AlignOptions.PropertyNamingConvention.DOT_SUFFIX)
                        .build());

// Child POM: dependency is now version-less
// Parent POM: has dependencyManagement entry + guava.version property

Aligning All Dependencies

Move all dependency versions to the parent in one call:

String childPom = """
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>
          <parent>
            <groupId>com.example</groupId>
            <artifactId>parent-project</artifactId>
            <version>1.0.0</version>
          </parent>
          <artifactId>child-module</artifactId>
          <dependencies>
            <dependency>
              <groupId>org.slf4j</groupId>
              <artifactId>slf4j-api</artifactId>
              <version>2.0.7</version>
            </dependency>
            <dependency>
              <groupId>com.google.guava</groupId>
              <artifactId>guava</artifactId>
              <version>32.1.2-jre</version>
            </dependency>
          </dependencies>
        </project>
        """;

String parentPom = """
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.example</groupId>
          <artifactId>parent-project</artifactId>
          <version>1.0.0</version>
          <packaging>pom</packaging>
        </project>
        """;

PomEditor child = new PomEditor(Document.of(childPom));
PomEditor parent = new PomEditor(Document.of(parentPom));

// Move ALL dependency versions to the parent
int moved = child.dependencies()
        .alignAllToParent(
                parent,
                AlignOptions.builder()
                        .versionSource(AlignOptions.VersionSource.PROPERTY)
                        .namingConvention(AlignOptions.PropertyNamingConvention.DOT_SUFFIX)
                        .build());
// Both dependencies are now managed by the parent

What Happens During Alignment

When a dependency is aligned to a parent POM:

  1. Version resolution - The child's version is resolved (including property lookup if ${...})
  2. Property migration - If the child uses a property reference, the property definition is migrated to the parent
  3. Managed dependency creation - A <dependency> entry is created in the parent's <dependencyManagement>
  4. Child version removal - The <version> element is removed from the child dependency
  5. Property cleanup - If the child property is no longer referenced anywhere, it is removed

Property Handling

Child version Target source Result in parent
2.0.7 (literal) LITERAL <version>2.0.7</version>
2.0.7 (literal) PROPERTY Property created + <version>${slf4j-api.version}</version>
${slf4j.version} (property) PROPERTY Property migrated + <version>${slf4j.version}</version>
${slf4j.version} (property) LITERAL <version>2.0.7</version> (resolved)

AlignOptions for Cross-POM

The AlignOptions control how versions are stored in the parent POM. Key options:

AlignOptions options = AlignOptions.builder()
    // How versions are stored in the parent's dependencyManagement
    .versionSource(AlignOptions.VersionSource.PROPERTY)
    // How property names are generated
    .namingConvention(AlignOptions.PropertyNamingConvention.DOT_SUFFIX)
    // Or use an explicit property name
    .propertyName("guava.version")
    .build();

API Reference

Method Description
dependencies().alignToParent(coords, parentEditor, options) Move a single dependency's version to the parent
dependencies().alignAllToParent(parentEditor, options) Move all dependency versions to the parent

Both methods return a count or boolean indicating how many/whether dependencies were moved. Dependencies that are already version-less (managed) are skipped.

Next Steps