Is it a better approach to explicitly include a dependency version (that is already being included via another dependency), or exclude the unwanted versions where they’re coming in as a transitive dependency?
Example:
There’s a library: initech-ibrary
of v2.0.5
, which has the following dependencies:
<dependency>
<groupId>com.initech</groupId>
<artifactId>printer-tools</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>penny-pinching</artifactId>
<version>3.0.11</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>tps-reports</artifactId>
<version>3.4.9</version>
</dependency>
Approach 1
An application has the following dependencies declared
<dependency>
<groupId>com.initech</groupId>
<artifactId>initech-ibrary</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>other-tools</artifactId>
<version>2.0.10</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>printer-tools</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>penny-pinching</artifactId>
<version>3.0.11</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>tps-reports</artifactId>
<version>3.4.9</version>
</dependency>
These specific versions (for printer-tools
, penny-pinching
and tps-reports
) are not defined due to incompatibilities with the application or needing a specific older version for a feature or anything like that - they’re just there to prevent other versions being picked up transitively because other-tools
has a dependency on an older version of initech-ibrary
than the currently declared v2.0.5
.
Approach 2
<dependency>
<groupId>com.initech</groupId>
<artifactId>initech-ibrary</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.initech</groupId>
<artifactId>other-tools</artifactId>
<version>2.0.10</version>
<exclusions>
<exclusion>
<groupId>com.initech</groupId>
<artifactId>tps-reports</artifactId>
</exclusion>
</exclusions>
</dependency>
This approach specifically excludes tps-reports
from other-tools
because it has a dependency on an older version of initech-ibrary
which is pulling in an older version of tps-reports
than what is in initech-ibrary
v2.0.5
, and that older version is being used instead.
Approach 1 has the problem that when the version of initech-library
gets updated, then all the other dependencies need to be looked up and also updated but it has the benefit of not having to worry about the wrong versions being pulled in, whereas Approach 2 simplifies the dependencies, but requires the developer to be more aware of any version changes and future dependency additions.
What are the other possible problems that could occur from each approach?
Thanks!
There is a third possibility, which I prefer:
Define the version of the dependency in the <dependencyManagement>
section of your POM. This means that you get the (recent) versions that you want, but if the transitive dependency is no longer in the dependency tree (after an update), the dependencyManagement just does nothing, so you do not pollute your artifact with unnecessary dependencies. Furthermore, if you read the POM, it is clear that these versions are not your dependencies, but transitive ones.