WelcomeTo
WelcomeTo

Reputation: 20571

Maven overrides transitive dependency

Overall applicatiom I'm using Apache HttpComponents dependency:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.2</version>
    </dependency>

But also another library uses this artifact, but different version (4.3.2, not 4.5.2):

    <dependency>
        <groupId>com.sendgrid</groupId>
        <artifactId>sendgrid-java</artifactId>
    </dependency>

The problem is that API between this versions is changed and I'm getting this error:

Caused by: java.lang.ClassNotFoundException: org.apache.http.ssl.SSLContexts

How I can say to maven not to override Sendgrid's version of HttpComponents (4.3.2) with 4.5.2?

EDIT: version of httpcomponents is specified in dependencyManagement section of parent pom

Upvotes: 3

Views: 1722

Answers (2)

ursa
ursa

Reputation: 4591

It is impossible in a simple maven project to have 2 different versions of the same artifact in the classpath. So you cannot have 4.3.2 and 4.5.2 versions in the classpath simultaneously.

However there are several options... You can either

  • use in your project the older version (4.3.*), compatible with sendgrid-java dependency (simplest way); or
  • update sendgrid-java dependency, if newer one is compatible with http components 4.5.* (preferred way); or
  • mark sendgrid-java as a 'provided' dependency, build a separate class loader in runtime and load it with correct dependencies versions (a bit tricky, but I saw this approach in a couple bank applications)

Upvotes: 0

A_Di-Matteo
A_Di-Matteo

Reputation: 27812

Given the following parent pom.xml section:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.sendgrid</groupId>
        <artifactId>sendgrid-java</artifactId>
        <version>2.0.0</version>
    </dependency>
</dependencies>

<modules>
    <module>module-a</module>
    <module>module-b</module>
</modules>

Indeed in module-a the dependency tree is the following, executing:

mvn dependency:tree

We get as part of the output:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ module-a ---   
[INFO] com.sample:module-a:jar:0.0.1-SNAPSHOT   
[INFO] \- com.sendgrid:sendgrid-java:jar:2.0.0:compile   
[INFO]    +- org.json:json:jar:20140107:compile   
[INFO]    +- org.apache.httpcomponents:httpcore:jar:4.3.2:compile   
[INFO]    +- org.apache.httpcomponents:httpclient:jar:4.5.2:compile     
[INFO]    |  +- commons-logging:commons-logging:jar:1.2:compile   
[INFO]    |  \- commons-codec:commons-codec:jar:1.9:compile   
[INFO]    +- com.sendgrid:smtpapi-java:jar:1.0.0:compile   
[INFO]    \- org.apache.httpcomponents:httpmime:jar:4.3.4:compile   

Note:

  • We get org.apache.httpcomponents:httpclient:jar:4.5.2:compile
  • We also get org.apache.httpcomponents:httpcore:jar:4.3.2:compile
  • A potential versons mismatch happens here between libraries of the same family

Adding then to the module-a's pom.xml the following:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.3.2</version>
        </dependency>
    </dependencies>
</dependencyManagement>

And re-running our dependency tree execution, we get as part of the output:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ module-a ---  
[INFO] com.sample:module-a:jar:0.0.1-SNAPSHOT  
[INFO] \- com.sendgrid:sendgrid-java:jar:2.0.0:compile   
[INFO]    +- org.json:json:jar:20140107:compile  
[INFO]    +- org.apache.httpcomponents:httpcore:jar:4.3.2:compile  
[INFO]    +- org.apache.httpcomponents:httpclient:jar:4.3.2:compile  
[INFO]    |  +- commons-logging:commons-logging:jar:1.1.3:compile  
[INFO]    |  \- commons-codec:commons-codec:jar:1.6:compile  
[INFO]    +- com.sendgrid:smtpapi-java:jar:1.0.0:compile  
[INFO]    \- org.apache.httpcomponents:httpmime:jar:4.3.4:compile  

We now get httpcore and httpclient aligned, with the versions we wanted.

Also note the httpmime to version 4.3.4, it's a fix version change, but still a misalignment (should be harmless though).

In this case it seems you are adding governance at parent level in dependencyManagement (good approach), but then at the level of one of the modules you need to override it. That can happen, but better to properly comment it, for maintenance and for the future yourself looking at it in the future.

Also note: other modules in this project would not be affected by this change, that is, they will still get version 4.5.2. If the final result of the whole multimodule build is an ear or war file, for example, carefully check what you eventually get.

Upvotes: 1

Related Questions