Maven: how to override the dependency added by a library

Maven 2Dependencies

Maven 2 Problem Overview


Here's my generic problem:

My project P depends on A which depends on B which depends on C which depends on version 1.0.1 of D.

There's a problem with version 1.0.1 of D and I want to force the use of another module. I don't know how to declare this in my project's POMs since I haven't added a dependency on D directly. It's C which declared the dependency on D.

Important: In this case, not only the version is changed, but the group & artifact as well. So it's not just a matter of overriding the version of the dependency, but rather, of excluding a module and including another one.

In the concrete case, D is StAX whose 1.0.1 has a bug. According to the notes in the bug, "the problems were solved by replacing the stax-api-1.0.1 (maven GroupId = stax) by stax-api-1.0-2 (maven GroupId = javax.xml.stream)" so I'm trying just that.

Thus, D = stax:stax-api:jar:1.0.1 and C = org.apache.xmlbeans:xmlbeans:jar:2.3.0

I'm using maven 2.0.9 in case it matters.

Output of mvn dependency:tree"

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

In my project's POM I have the following dependency on "A":

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

Maven 2 Solutions


Solution 1 - Maven 2

Simply specify the version in your current pom. The version specified here will override other.

>Forcing a version
>A version will always be honoured if it is declared in the current POM with a particular version - however, it should be noted that this will also affect other poms downstream if it is itself depended on using transitive dependencies.


Resources :

Solution 2 - Maven 2

Alternatively, you can just exclude the dependency that you don't want. STAX is included in JDK 1.6, so if you're using 1.6 you can just exclude it entirely.

My example below is slightly wrong for you - you only need one of the two exclusions but I'm not quite sure which one. There are other versions of Stax floating about, in my example below I was importing A which imported B which imported C & D which each (through yet more transitive dependencies) imported different versions of Stax. So in my dependency on 'A', I excluded both versions of Stax.

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

Solution 3 - Maven 2

What you put inside the </dependencies> tag of the root pom will be included by all child modules of the root pom. If all your modules use that dependency, this is the way to go.

However, if only 3 out of 10 of your child modules use some dependency, you do not want this dependency to be included in all your child modules. In that case, you can just put the dependency inside the </dependencyManagement>. This will make sure that any child module that needs the dependency must declare it in their own pom file, but they will use the same version of that dependency as specified in your </dependencyManagement> tag.

You can also use the </dependencyManagement> to modify the version used in transitive dependencies, because the version declared in the upper most pom file is the one that will be used. This can be useful if your project A includes an external project B v1.0 that includes another external project C v1.0. Sometimes it happens that a security breach is found in project C v1.0 which is corrected in v1.1, but the developers of B are slow to update their project to use v1.1 of C. In that case, you can simply declare a dependency on C v1.1 in your project's root pom inside `, and everything will be good (assuming that B v1.0 will still be able to compile with C v1.1).

Solution 4 - Maven 2

I also had trouble overruling a dependency in a third party library. I used scot's approach with the exclusion but I also added the dependency with the newer version in the pom. (I used Maven 3.3.3)

So for the stAX example it would look like this:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>

Solution 5 - Maven 2

The accepted answer is correct but I'd like to add my two cents. I've run into a problem where I had a project A that had a project B as a dependency. Both projects use slf4j but project B uses log4j while project A uses logback. Project B uses slf4j 1.6.1, while project A uses slf4j 1.7.5 (due to the already included logback 1.2.3 dependency).

The problem: Project A couldn't find a function that exists on slf4j 1.7.5, after checking eclipe's dependency hierarchy tab I found out that during build it was using slf4j 1.6.1 from project B, instead of using logback's slf4j 1.7.5.

I solved the issue by changing the order of the dependencies on project A pom, when I moved project B entry below the logback entry then maven started to build the project using slf4j 1.7.5.

Edit: Adding the slf4j 1.7.5 dependency before Project B dependency worked too.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwishihadabetternameView Question on Stackoverflow
Solution 1 - Maven 2Colin HebertView Answer on Stackoverflow
Solution 2 - Maven 2scotView Answer on Stackoverflow
Solution 3 - Maven 2Kent Munthe CaspersenView Answer on Stackoverflow
Solution 4 - Maven 2Patrick KoorevaarView Answer on Stackoverflow
Solution 5 - Maven 2Fernando MaiaView Answer on Stackoverflow