Uploaded image for project: 'Maven'
  1. Maven
  2. MNG-7368

Deeper merge logic for managed dependency declarations

    XMLWordPrintableJSON

Details

    Description

      When inheriting dependencyManagement from parent, Maven's current merge logic is at the level of the list of dependencies which involves choosing the entire child's dependency declaration over that of the parent, i.e., no merging actually happens at the dependency level (it is all or nothing). This essentially makes it impossible to incrementally build the dependencyManagement. If the child projects have to repeat the entire dependency declaration, it defeats the purpose of sharing them in a parent-pom across multiple related projects. E.g., one common reason for managing them in parent is to centralize version for all dependencies at one place, but if the child must repeat the version to change anything in that dependency such as scope or exclusion rules, then there is no longer one central place.

      I am attaching a very basic project structure (also attached as depman-inheritance.zip) to better demonstrate the issue.

      Parent POM with a couple of managed dependencies:

      parent/pom.xml
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>depman-inheritance</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>parent</name>
        <packaging>pom</packaging>
      
        <dependencyManagement>
          <dependencies>
            <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.11</version>
              <scope>test</scope>
            </dependency>
            <dependency>
              <groupId>org.apache.commons</groupId>
              <artifactId>commons-text</artifactId>
              <version>1.9</version>
            </dependency>
          </dependencies>
        </dependencyManagement>
      </project>
      

      Project Root POM trying to change just the scope of one of the dependencies:

      project/pom.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
          <groupId>depman-inheritance</groupId>
          <artifactId>parent</artifactId>
          <version>1.0-SNAPSHOT</version>
          <relativePath>../parent/pom.xml</relativePath>
        </parent>
      
        <groupId>depman-inheritance</groupId>
        <artifactId>project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>project</name>
        <packaging>pom</packaging>
      
        <modules>
          <module>module</module>
        </modules>
      
        <dependencyManagement>
          <dependencies>
            <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
      	<scope>compile</scope>
            </dependency>
          </dependencies>
        </dependencyManagement>
      </project>
      

      Module POM simply using the dependencies:

      project/module/pom.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
          <groupId>depman-inheritance</groupId>
          <artifactId>project</artifactId>
          <version>1.0-SNAPSHOT</version>
        </parent>
      
        <groupId>depman-inheritance</groupId>
        <artifactId>module</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>module1</name>
      
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
          </dependency>
          <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
          </dependency>
        </dependencies>
      </project>
      

      With this, if we run any maven command in the project, I get the below error:

      $ mvn dependency:tree
      ...
      [ERROR] [ERROR] Some problems were encountered while processing the POMs:
      [ERROR] 'dependencies.dependency.version' for junit:junit:jar is missing. @ line 17, column 17
       @
      [ERROR] The build could not read 1 project -> [Help 1]
      [ERROR]
      [ERROR]   The project depman-inheritance:module:1.0-SNAPSHOT (/Users/hdara/git/hdara/playground-mvn-project/depman-inheritance/project/module/pom.xml) has 1 error
      [ERROR]     'dependencies.dependency.version' for junit:junit:jar is missing. @ line 17, column 17
      ...
      

      I would like to propose that the support for deeper merging be added to Maven. There are however two aspects of this merging that I am not sure:

      • Should/Can it be applied to all non-key fields?
      • How to handle exclusion rules? Should they be overriding or be additive?

      Attachments

        1. depman-inheritance-1.zip
          2 kB
          Hari Krishna Dara

        Activity

          People

            Unassigned Unassigned
            haridsv Hari Krishna Dara
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: