[maven-2] Maven: how to override the dependency added by a library

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>

Thanks in advance.

This question is related to maven-2 dependencies

The answer is


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.


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>

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).


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>