Comparing Maven project dependencies - maven

Is there a simple way to list the differences between the artefacts added to the classpath by one version of a Maven project and another?
Here is the problem I'm trying to solve. If I change the version of an artefact declared in a Maven project, the list of transitive dependencies added to the classpath by the dependency may change. I want know what those changes are before I commit a change to a dependency version. The primary reason I want to know what transitive dependencies will change on the classpath when I change the version number of declared dependency is concern that changing the version number of a declared dependency may cause the version of a transitive dependency to change to one that has a security vulnerability in it.
At the moment, I'm using the dependencies plugin tree goal to produce a before and after change dependency tree and then comparing the two by eye. This is not ideal.
I also know of a way to achieve my goal using the OWASP dependency check Maven plugin but this also seem not ideal.
Can anyone suggest a better solution to my problem that using the dependencies plugin or the OWASP dependency check plugin? Is there a Maven plugin to produce what I need?
Thanks

Please try
mvn dependency:list
It will list all the dependencies with version information.
now you can see the difference using any diff checker tool online.

Related

How to find transitive dependencies with dynamic versions in Gradle?

I have a Gradle project with a large set of transitive dependencies (from Spring, Apache, AWS etc).
I want to find out if any them have dynamic versions, e.g. 1.2+?
Ofc I do not want to search manually through all possible BOMs.
If I build a dependency tree with gradle dependencies I get a set of already resolved fixed versions unfortunately.
I guess there is probably another Gradle task/command for this.
The reason for this is that I want to know if I need to use dependency version locking mechanism.

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.

How can I find out hidden versions of dependencies and plugins in Maven?

We do not need to specify the versions and other parameters of Maven dependencies and plugins we use. We can do it only once in parent POM or may be in some other way and inherit that properties in our children POMs.
Unfortunately for many times I have met the projects where I cannot find the real parameters of dependencies and plugins that easily. I.e. the versions of dependencies are empty, but in parent POM there is no information about this.
So my questions are:
What are all the possible ways to specify the parameters of dependency and plugin in Maven? I.e. where can I look for version number if it is not present neither in plugin in child POM nor in plugin management in parent pom?
Is there any Maven command to find out where Maven takes these parameters from? For example, I may use the dependency:tree command. It will print a list of dependencies which will help me to understand the version dependency I am stuck about. But this is a hack, and it cannot help me with plugins. May be there is something better?
Before executing any command, Maven builds the "effective POM", see this stackoverflow answer for more details. You may view the effective POM for any project by running mvn help:effective-pom. Typically when I run this command I redirect the output into a file so I can view and search it in a text editor.
You asked about specific parts of the POM, dependencies and plugins. You're on the right track, the maven-dependency-plugin helps. The goals I use most often are dependency:tree, dependency:resolve, and dependency:resolve-plugins. The first two assist with project dependencies, the last one with plugins. Add the -U option to force Maven to update dependencies regardless of the update policies/repository metadata values.
It is also helpful when troubleshooting to start with an empty local repository.
Last but certainly not least, Maven will give warnings when a build uses a plugin without a specific version. ALWAYS specify an explicit version to fix the warning and avoid issues like this one.

Maven dependency conflict:snapshots has no priority

When there is a conflict in the dependency tree (same artifact but different versions) then, AFAIK, Maven will resolve the conflict by selecting the highest version of the dependency and will omit the 'old' ones.
However, when the newer version is a SNAPSHOT then apparently it will choose the older stable version over the SNAPSHOT.
In my case: some-artifact: 0.5.0-SNAPSHOTS (omitted for conflict with 0.4.0) => version 0.4.0 is picked over the wanted 0.5.0-SNAPSHOT.
I assume this functions as designed but I don't understand the reason why. Next to that, any idea if there is a way to tell Maven to take the SNAPSHOT over the stable version?
Your assumption about Maven's always selecting the highest version isn't accurate. Artifacts are chosen based on a number of factors including depth of the dependency in the tree, order in the tree, whether the dependency is a snapshot or a release, and dependency management, which pretty much overrides everything else.
Unfortunately, I don't know of any one, definitive source of information on Maven's dependency resolution algorithms. You'll find bits and pieces of it scattered all over. A few handy references:
Introduction to the Dependency Mechanism gives an overview of the topic with a good, if short, section on Transitive Dependencies and how they're selected from a dependency tree.
The Sonatype Maven book has a more thorough section on Project Dependencies in general that will add a lot to your knowledge about the subject.
An earlier section of that same book discusses Project Versions, which is strongly related to this problem and has a good section on SNAPSHOT versions, though not as much as I could wish on how they play into dependency resolution.
Project Relationships talks about the coordinate system and how project inheritance affects what dependencies get included.
Finally, the POM Reference is a good jumping-off point for almost anything to do with the pom. There's at least a brief description of every pom element that can help you understand enough to be able to begin searching for more info effectively.
As for some practical advice, the output of mvn dependency:tree is highly useful in discovering why a particular version of a dependency was chosen. It'll often even tell you something like "foo:bar:1.2 (was 1.1)". Once you figure out where the errant version is coming from, there are a number of ways to ensure a specific dependency version is used for a project:
Exclude wrongly-versioned dependencies from other dependencies that are causing them to be included in the build.
Add an explicit top-level dependency to your pom instead of relying on a transitive dependency.
List the dependency in the dependencyManagement section of your pom (scroll down a bit from this link) to force the dependency to have the specified characteristics, regardless of what level of transitive dependency it is. Use this option with care, as dependencyManagement is viral, in that other projects depending on your project will be "infected" with your dependency management. There's also a good section on dependency management in the pom reference.
If the 0.4.0 version is being pulled in as a transitive dependency via another dependency in your POM, then you should be able to exclude it. The dependency:tree goal should help you see if this is what's happening.
Maven is designed to favor release versions over snapshot versions. I'm not sure why you would have two dependencies in the same POM and not be able to resolve a conflict by removing one, so I will assume that one of the dependencies is inherited from a parent pom. In this case you can set the inherited dependency as <optional>true</optional> and I THINK it should allow the child POMs to override it, even with a lower version.
bad/hacky solution for if that doesn't work - edit your local repository in such a way that it doesn't realize the 0.5.0 version is a snapshot (or even edit your private nexus repo if you have the ability)

Force transitive dependency version in Gradle

I'm playing around with gradle trying to port my maven project and here's my problem:
In maven we have the <dependencyManagement> which provides a common (default) version for certain dependencies (which is used only when in a sub-pom this artifact is used without a version number). It also, from what I understand, forces a certain version for all transitive dependencies. So if I understand correctly even if artifact B which we have as a dependency has a dependency on artifact C version 1.0 then we will still use a version of artifact C defined in the <dependencyManagement> (so it might be 2.0). Is that correct?
If so then is there a way to do something similar in Gradle? I know that a common way of replacing the <dependencyManagement> is to simply create a Groovy map in one of the build scripts. But how can I force the transitive dependency version? If I use Gradle's "force" won't it affect all (not only transitive) dependencies (which is obviously not what I want)?
In Gradle, forcing a version (e.g. with Configuration.resolutionStrategy.force) will force it for all dependencies of the configuration, direct and transitive. There is no first-class feature that forces a version only for transitive dependencies. Do you have a valid use case for this? At the end of the day, both Gradle and Maven will select a single version for a dependency anyway, no matter where and how often it appears in the dependency tree.
There is a ResolutionStrategy feature that allows forcing artifacts versions including transitive dependencies: https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html
It is also possible to configure dependencies constraints: https://docs.gradle.org/current/userguide/dependency_constraints.html

Resources