How to make dependencyManagement in Maven transitive - maven

In maven, dependencyManagement can be used to resolve dependency conflict problems.
Now I'm developping a common lib project which will be used by many other projects. I want to use dependencyManagement to resolve all dependency conflicts so that other projects don't need to handle it.
However, when I add the common lib as dependency of other projects, I find that the dependencyManagement not works. In other words, I meet the same dependency conflict problems which already been resolved in dependencyManagement of the common lib.
I know copy-paste of dependencyManagement to everywhere is a way to make it, but it's very ugly and hard to maintain.
Is there any other way to achieve the goal?
Thanks.

Yes, your "common lib" can declare the desired versions as <dependency> (not just in dependencyManagement) and can also use exclusions to exclude the undesired ones. This works also transitively.
It would be great to have transitivity also for dependencyManagement, but it might make the very complex dependency resolution process of Maven even more complex.

Related

Transitive dependencies in maven

I have read about transitive dependency in maven but it makes me little confused. can anyone please explain about transitive dependency in maven and what are the advantages and disadvantages.Thanks in advance.
Start very simple. Assume you are using a library like the Apache Tika lib. So you express this by defining a dependency in your pom file by something like this:
<project...>
<dependencies>
<dependency>
<groupId>..</groupId>
<artifactId>tika-core</artifactId>
<version>1.19</version>
</dependency>
</dependencies>
</project>
The Tika lib also has dependencies on its own which mean the dependencies of Tika are expressed in their pom file and those dependencies are called Transitive Dependencies.
The simple advantage is that you don't need to think about the transitive dependencies. This means you only need to think: I would like to use Tika lib and don't need to bother about their dependencies...
So If you use a class of Tika core in your code you have the dependency available. One tip about best practice is: If you are using a class of a transitive dependency, then make it a direct dependency (add it to your pom file).
Maven documentation assumes that you already know what a transitive dependency is. This may not be the case! So let's dive in...
First things first
A transitive dependency is
A depends on B
B does not depend on A
B depends on C
==> Therefore A depends on C
It's as simple as that.
The good news is
Maven is great at managing dependencies! From Maven documentation:
Maven avoids the need to discover and specify the libraries that your own dependencies require by including transitive dependencies automatically.
So most of the time you won't have to bother about it.
And beyond
However, Maven understands you may need more advanced features, therefore, it proposes several dependency related mechanisms, such as dependency management, mediation, scope, exclusion and optional.
Dependency management, for example, is a very popular feature, because it enforces the versions of dependencies used by a project or a set of project.
Exclusion alows you to exclude transitive dependencies from a project. This feature is useful to manage dependencies incompatibility.
And so on...

What are the disadvantages of using undeclared maven dependencies (through transitive dependencies)?

Maven includes transitive dependencies in a project class path to eliminate the need to redefine these dependencies over and over again each time a module depends on a third party module.
The version of transitive dependencies used can be controlled from a dependency management section in the root pom. So it is controllable.
So why using transitive dependencies in a project without explicitly declaring it in its pom file is considered a bad practice ?
Usually, you update your dependencies after some time.
The update can lead to lost transitive dependencies which will then directly affect your program.
If, on the other hand, you write down all dependencies you use explicitly, it is much easier to make updates and see what you really use.

Reducing Maven Dependencies

I am using Maven to build my project. There are lot of dependencies which are in provided and runtime scope. The build size is large and I want to remove the unwanted dependencies. So is there any way in which I can check which dependencies are unwanted.
The best way to minimize dependencies to the ones you really need is to not embed that dependencies. If you simply use the maven-bundle-plugin on your code it will create Import-Package statements for the code you really need. This might even give you a good hint on what dependencies you might be able to exclude for embedding.
In general in OSGi the goal should be to not have that many dependencies in the first place. If you use libraries with extensive dependencies then your should question the quality of these.

How two know when a maven project has the same transitive dependenciy twice of different versions?

I have to add a new dependency to a maven project. This dependency has four transitive dependencies(according to http://mvnrepository.com/) and between them, there is spring-data-jpa jar.
The maven project I am working in has many dependencies configured in the pom so I understand there could be a big possibility that there is already a spring-data-jpa dependency in the project(transitive or not).
When you work in a large project with many dependencies and you have to add a new one, how to check if there is already the same transitive dependency of a different version? I have to check manually the transitive dependencies for each direct dependency configured? Has maven a warning for this situation?
How maven works in this situation? I mean, there could be two spring-data-jpa jars of different versions(this would be a problem) or maven resolves this in another way?
The simple answer is that the dependency plugin can tell you. The longer answer is that there are a number of different situations to consider about transitive dependency management, and how the plugin helps and what to do about it differs for each one.
Maven automatically chooses which dependency to include if two dependencies have the same coordinates (groupId, artifactId) with different versions. Broadly speaking, it picks the version that's highest in the tree - effectively overriding dependencies defined in downstream transitive dependency poms. So, if you have two different versions of exactly the same dependency then you will still only find one version of the dependency on the relevant classpath.
The dependency plugin can help you identify this situation by highlighting points where its made a decision, but you probably want to use the dependencyManagement section of your top-level pom to ensure that the dependencies which you bring in are the ones you expect.
Separate difficulties can arise when a dependency changes its groupId or artifactId. Then you can get two dependencies on the classpath - one with an old version on the old coordinates and one with the new version on the new coordinates. As examples, Spring, Hibernate and Apache commons have all found themselves doing this at some point or another. In this case all you can do is use to the dependency plugin to identify duplicated dependencies and then use exclusions tags to explicitly exclude them as transitive dependencies from the dependencies which are pull them in.
It's important to note that all of this dependency management can cause unintended breakage. If the thing that your application depends on really does depend on some specific version of a package as a transitive dependency then you can break it by overriding that version. So testing the features that you use is essential.
Have you tried the Maven Dependency Plugin? There's some useful goals you can run, such as mvn dependency:tree etc.

Is there a way to disallow dependencies on certain artifacts in Maven?

I have a problem with the maven artifact for junit. It comes packaged with hamcrest, but I like to use a later version of hamcrest, so my projects need to use junit-dep and exclude the hamcrest dependencies.
I have a parent pom.xml with a dependencyManagement section to handle the version of junit-dep that I want and ensure that hamcrest is excluded. However, I'm constantly running into an issue where some other test library includes a transitive dependency to junit.
Note that it's not the version number that's a problem. It is the particular artifact. I don't want junit, I want junit-dep. Is there any way to say in my dependencyManagement (or anywhere else) that I never want to include junit of any version at all?
Unfortunately, there is no global exclude option in dependency management.
On the other hand, if you don't want JUnit jar do be included ever, you may play the same trick as commons-logging-99.0-does-not-exist.jar.
Here is the link that describes the trick -> http://day-to-day-stuff.blogspot.com/2007/10/announcement-version-99-does-not-exist.html
Personally, I've found out that it's easier to do the job by using <exclusions> tag.

Resources