Flatten Plugin: Resolve dependencyManagement of bom without inherited

1.5k views Asked by At

I created an example project for this problem: https://github.com/robeatoz/flatten-resolve-dependency-management-without-inherited

Following project structure is given:

  • foo-build as the parent for all modules
  • foo-module-a as child module
  • foo-module-b as child module
  • foo-module-c as child module
  • foo-dependencies as bom

I used the flatten-maven-plugin and the property revision for CI friendly builds in all modules:

<groupId>stack.overflow</groupId>
<artifactId>foo-build</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>

<properties>
    <revision>0.1-SNAPSHOT</revision>
</properties>

The parent (foo-build) manages one external dependency:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>external.artifact</groupId>
            <artifactId>module-managed-in-parent</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>
</dependencyManagement>

The bom (foo-dependencies) manages the foo dependencies:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-a</artifactId>
            <version>${revision}</version>
        </dependency>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-b</artifactId>
            <version>${revision}</version>
        </dependency>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-c</artifactId>
            <version>${revision}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

I want that the flattened pom of the bom contains only the resolved foo dependencies without the dependencies managed by the parent (foo-build) like this:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-a</artifactId>
            <version>0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-b</artifactId>
            <version>0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>stack.overflow</groupId>
            <artifactId>foo-module-c</artifactId>
            <version>0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</dependencyManagement>

How do you have to configure the flatten-maven-plugin to achieve this?

I already tried <flattenMode>bom</flattenMode>, but then the flattened pom does not resolve the versions:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-a</artifactId>
      <version>${revision}</version>
    </dependency>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-b</artifactId>
      <version>${revision}</version>
    </dependency>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-c</artifactId>
      <version>${revision}</version>
    </dependency>
  </dependencies>
</dependencyManagement>

With the following configuration

<pomElements>
    <properties>remove</properties>
    <dependencyManagement>resolve</dependencyManagement>
</pomElements>

the flattened pom contains the managed dependency of the parent:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-a</artifactId>
      <version>0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-b</artifactId>
      <version>0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>stack.overflow</groupId>
      <artifactId>foo-module-c</artifactId>
      <version>0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>external.artifact</groupId>
      <artifactId>module-managed-in-parent</artifactId>
      <version>1.2.3</version>
    </dependency>
  </dependencies>
</dependencyManagement>
3

There are 3 answers

0
SimonT On

I have like the exact same usecase and I solved it with the following configuration.

You need to apply a very specific configuration to the flatten-plugin within the pom file of the BOM module:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>flatten-maven-plugin</artifactId>
    <configuration>
        <updatePomFile>true</updatePomFile>
        <pomElements>
            <dependencyManagement>expand</dependencyManagement>
        </pomElements>
    </configuration>
</plugin>

expand means that the dependencyManagement block will be replaced with the one from the effective pom where all references are properly resolved. updatePomFile is necessary because otherwise by default, the flattened pom would not be published for poms with <packaging>pom</packaging>

Here are the relevant parts from the flatten-plugin's documentation:

1
ursa On

It would be simpler to change your approach to more client-centric:

  1. Make foo-dependencies a root project (./pom.xml).

    • with only foo-* dependencies in dependency management section
    • modules list with a single foo-build module (would be truncated by flatten plugin)
    • generic project properties (would be truncated by flatten plugin)
  2. Make foo-build an intermediate project (./foo-build/pom.xml).

    • with third-party dependencies in dependency management section
    • with build-specific properties or profiles, required by your project (if any)
  3. Retain foo-module-* leaf modules with foo-build as a parent

If you insist on plain project structure (./foo-module-*/pom.xml), you can use relativePath to point parent module, e.g.:

<parent>
    <groupId>stack.overflow</groupId>
    <artifactId>foo-build</artifactId>
    <version>${revision}</version>
    <relativePath>../foo-build/pom.xml</relativePath>
</parent>

<artifactId>foo-module-a</artifactId>

This way you will receive:

  • clear foo-dependencies as you wish;
  • zero copy-paste for foo-* dependencies;
  • flexibility to build whatever and however you like in foo-build without side-effects on foo-dependencies (neither now nor in the future).
0
Chuang Hou On

You don't need to change the version with ${revision}, use ${project.version}, take a try