Is there anyway to exclude artifacts inherited from a parent POM?

Artifacts from dependencies can be excluded by declaring an <exclusions> element inside a <dependency> But in this case it's needed to exclude an artifact inherited from a parent project. An excerpt of the POM under discussion follows:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>      
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

base artifact, depends on javax.mail:mail-1.4.jar , and ALL-DEPS depends on another version of the same library. Due to the fact that mail.jar from ALL-DEPS exist on the execution environment, although not exported, collides with the mail.jar that exists on the parent, which is scoped as compile .

A solution could be to rid off mail.jar from the parent POM, but most of the projects that inherit base, need it (as is a transtive dependency for log4j). So What I would like to do is to simply exclude parent's library from the child project , as it could be done if base was a dependency and not the parent pom:

...
    <dependency>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <type>pom<type>
        <exclusions>
          <exclusion>
             <groupId>javax.mail</groupId>
             <artifactId>mail</artifactId>
          </exclusion>
        </exclusions>
    </dependency>
...

Some ideas:

  • Maybe you could simply not inherit from the parent in that case (and declare a dependency on base with the exclusion). Not handy if you have lot of stuff in the parent pom.

  • Another thing to test would be to declare the mail artifact with the version required by ALL-DEPS under the dependencyManagement in the parent pom to force the convergence (although I'm not sure this will solve the scoping problem).

  • <dependencyManagement>
      <dependencies>
        <dependency>    
          <groupId>javax.mail</groupId>
          <artifactId>mail</artifactId>
          <version>???</version><!-- put the "right" version here -->
        </dependency>
      </dependencies>
    </dependencyManagement>
    
  • Or you could exclude the mail dependency from log4j if you're not using the features relying on it (and this is what I would do):
  • <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.15</version>
      <scope>provided</scope>
      <exclusions>
        <exclusion>
          <groupId>javax.mail</groupId>
          <artifactId>mail</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.jms</groupId>
          <artifactId>jms</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.sun.jdmk</groupId>
          <artifactId>jmxtools</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.sun.jmx</groupId>
          <artifactId>jmxri</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    
  • Or you could revert to the version 1.2.14 of log4j instead of the heretic 1.2.15 version (why didn't they mark the above dependencies as optional?!).

  • You can group your dependencies within a different project with packaging pom as described by Sonatypes Best Practices:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>base-dependencies</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <packaging>pom</packaging>
        <dependencies>
            <dependency>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
                <version>1.4</version>
            </dependency>
        </dependencies>
    </project>
    

    and reference them from your parent-pom (watch the dependency <type>pom</type> ):

    <project>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <packaging>pom</packaging>
        <dependencies>
            <dependency>
                <artifactId>base-dependencies</artifactId>
                <groupId>es.uniovi.innova</groupId>
                <version>1.0.0</version>
                <type>pom</type>
            </dependency>
        </dependencies>
    </project>
    

    Your child-project inherits this parent-pom as before. But now, the mail dependency can be excluded in the child-project within the dependencyManagement block:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>test</groupId>
        <artifactId>jruby</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <parent>
            <artifactId>base</artifactId>
            <groupId>es.uniovi.innova</groupId>
            <version>1.0.0</version>
        </parent>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <artifactId>base-dependencies</artifactId>
                    <groupId>es.uniovi.innova</groupId>
                    <version>1.0.0</version>
                    <exclusions>
                        <exclusion>
                            <groupId>javax.mail</groupId>
                            <artifactId>mail</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

    Have you tried explicitly declaring the version of mail.jar you want? Maven's dependency resolution should use this for dependency resolution over all other versions.

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>test</groupId>
      <artifactId>jruby</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <parent>
            <artifactId>base</artifactId>
            <groupId>es.uniovi.innova</groupId>
            <version>1.0.0</version>
        </parent>
        <dependencies>          
            <dependency>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
                <version>VERSION-#</version>
                <scope>provided</scope>
            </dependency> 
            <dependency>
                <groupId>com.liferay.portal</groupId>
                <artifactId>ALL-DEPS</artifactId>
                <version>1.0</version>
                <scope>provided</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </project>
    
    链接地址: http://www.djcxy.com/p/29700.html

    上一篇: Maven:如何覆盖由库添加的依赖项

    下一篇: 无论如何排除从父POM继承的工件?