Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven pulling in dependency that is not specified in POM

Tags:

java

maven

h2

I have a maven project consisting of a parent POM and several sub-modules. It compiles and runs fine within Intellij (I'm assuming this uses javac and not Maven).

When I run maven clean install, the build fails because of "RequireUpperBoundDeps", which from the documentation means a version resolved during the build is lower than a dependency's version for the same artifact. Here is the (sanitized) output:

[INFO] --- maven-enforcer-plugin:1.4:enforce (enforce-maven) @ my-service ---
[WARNING] Rule 1: org.apache.maven.plugins.enforcer.RequireUpperBoundDeps failed with message:
Failed while enforcing RequireUpperBoundDeps. The error(s) are [
Require upper bound dependencies error for com.h2database:h2:1.3.168 paths to dependency are:
+-com.example.services:my-service:1.0.0-SNAPSHOT
  +-com.h2database:h2:1.3.168
and
+-com.example.services:my-service:1.0.0-SNAPSHOT
  +-com.example.libs:my-libs:2.0.0
    +-com.h2database:h2:1.3.168 (managed) <-- com.h2database:h2:1.4.190
]

This seems to be implying that h2 is a direct dependency of my-service, but it is not declared as such in any poms, module or parent. h2 should only be coming from my-libs. Furthermore, it claims that h2 is "managed" to be version 1.3.168. I have no idea where it's getting this information. my-libs uses h2 version 1.4.190.

I've tried starting with a totally fresh .m2 directory, excluding h2 from the my-libs dependency, explicitly including h2 under my-service (both versions). Nothing works, and excluding h2 from the dependency results in a NoSuchPropertyException on one of my classes that interact with the database (via JDBI).

How can I get maven to recognize the correct version of h2 to include and to successfully build my project?

like image 451
tytk Avatar asked May 16 '16 23:05

tytk


People also ask

What happens if Maven dependency version is not specified?

Each maven dependency defined in the pom must have a version either directly or indirectly for example, through dependencyManagement or parent. That being said, if the version is not given, then the version provided in the dependencyManagement or the parent pom will be used.

What happens if you don't specify version in POM xml?

of your question: If you don't specify a version there are various different outcomes: a) you will get an error... b) if you have defined the version in the dependency management of the project's parent's pom, then that version is taken. The parent of the project doesn't have to be an enclosing superproject.

How do you exclude a dependency from pom?

Open the dependency POM and find the transitive dependency you want to exclude. Copy groupId and artifactId . In your project POM, underneath your active dependency, enter exclusions and using code completion paste the copied info of the dependency you want to exclude.

What happens if you don't specify a version in Maven?

Maven won't allow any other either. Build will fail if version is not found.


1 Answers

Someone wrote an excellent article HERE that provides and understanding of what is happening and possible solutions. Here is the summary -

For this deps tree in the error

+-com.example.services:my-service:1.0.0-SNAPSHOT
  +-com.example.libs:my-libs:2.0.0
    +-com.h2database:h2:1.3.168 (managed) <-- com.h2database:h2:1.4.190

The com.example.services:my-service project has dependency on version 1.3.168 of com.h2database:h2 artifact. Also, com.example.libs:my-libs needs the same artifact but of different version - 1.4.190.

Declare com.h2database:h2:1.3.168 in your pom (Upgrade Scenario)

NB: This might not be a suitable solution for all projects.

Alternatively, you can exclude com.h2database:h2:1.4.190 from com.example.libs:my-libs. That way, com.example.libs:my-libs will end up using and older version in com.h2database:h2:1.3.168 (downgrade scenario)

To do the latter, your pom entry will look like this:


    <dependency>
      <groupId>com.example.libs</groupId>
      <artifactId>my-libs</artifactId>
      <version>2.0.0</version>
      <exclusions>
        <exclusion> 
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>

It is a decision you have to make based on your project. I usually start by doing some investigations using mvn dependency:tree.

like image 129
papigee Avatar answered Oct 28 '22 04:10

papigee