Maven: dependency appears in effective pom but not in dependency tree - maven

Working on a multi-module project.
GrandParent
\
Parent
\
Child
GrandParent has rogue_1 module in its <dependencyManagement> section as provided !
Parent does NOT have rogue_1 in its pom.xml at all.
Child does NOT have rogue_1 as a direct dependency in its pom.xml.
However it includes several other projects some of which may include rogue_1. (at least one does depend on rogue_1)
To be on the safe side, on ALL Child's dependencies I have added exclusions as follows:
<dependency> <!-- a direct dependency of Child -->
<groupId>erso</groupId>
<artifactId>galen</artifactId>
<exclusions>
<exclusion>
<groupId>resistance</groupId>
<artifactId>rogue_1</artifactId>
</exclusion>
</exclusions>
</dependency>
(in case for example galen.erso is bringing in the resistance.rogue_1)
However: rogue_1 DOES end up being displayed as a dependency in the outcome of
mvn help:effective-pom
(as provided !)
It is NOT in the ouctome of
mvn dependency:tree
Any suggestions?

mvn help:effective-pom
is basically a merger between the super POM (grand /+parent) dependencies and the simple POM that you defined at the project level. Hence you do see the rogue_1 under the XML created by effective-pom, of course your grandparent pom's dependencyManagement being the source. Here is a detailed read over the same.
mvn dependency:tree
on the other hand displays the tre of the dependencies used in your project. As you mentioned you've excluded this out of all your mentioned dependencies, so you shouldn't find the artifact listed here.
By the way, in both the cases the chances of having the rogue_1 in the classpath of your child module is zero.

You may get this sort of behaviour, if you have a profile either in your project, or one that you're inheriting (and that is somehow getting activated). As far as I recall, dependencies defined in a <profile/> do not show up on the dependency tree.

Related

How to figure out in what pom a dependency from effective pom is defined in IntelliJ Idea?

I have a big project that has parent pom, this one has another parent; in the project's pom file another project with bom file is included as a dependency, etc.
I click on pom and generate effective pom. Inside I see a dependency, for example this one
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
Is there an easy way in IntelliJ to find the pom where this dependency is defined?
In Ultimate version it's possible to generate a diagram for all maven dependencies:
https://www.jetbrains.com/help/idea/work-with-maven-dependencies.html#maven_dependency_diagram
Or you can execute mvn dependency:tree to build full dependency tree.
https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html
https://www.mkyong.com/maven/maven-display-project-dependency/

POM references a dependency and a parent the same way. How we choose what is what?

I found that syntax of parent and dependency references in POM are practically the same:
<parent>
<groupId>com.topdesk</groupId>
<artifactId>tis-parent</artifactId>
<version>3.4</version>
</parent>
Dependency has the same inner content. Why we choose to put something as parent instead of using dependency?
These are different concepts. Referencing a parent makes Maven look for a pom from which it inherits (using all the plugin definitions, profiles, declared dependencyManagement etc.), i.e. the parent and your pom are put together as one and executed.
Using a dependency means that Maven looks for a jar (unless you explicitly tell it to look for a pom, which essentially means that it adds all dependencies from that pom as transitive dependencies). This jar is put on the classpath (together with its dependency tree).

Maven: Include POM with used dependencies in assembly

We deliver our package with many external dependencies to customers. Now customers can use you libraries to develop stuff on top. For those who are also using Maven we would like to include a pom.xml file in the assembly which contains all dependencies, so they can simply use it in their Maven build:
It should contain all dependencies used by us as follows:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math</artifactId>
<version>2.1</version>
<scope>compile</scope>
</dependency>
Is there a way to achieve that in Maven?
The pom.xml for your jar/war is by default placed inside your jar/war in the location META-INF\maven\<groupId>\<artifacdId>
You have two choices:
The first one which is the most common and preferred way is relying on Maven's transitive dependency resolution.
Have a POM (assume called foo-api:1.0) in your project that declares the dependency (e.g. A:1.0:jar, B:1.0:jar).
Developer's own project (bar:2.0) should then simply depends on foo-api:1.0. Maven will simply include A:1.0:jar and B:1.0:jar as dependency of bar:2.0, through the transitive dependency resolution.
Another way is similar to the above approach, but use foo-api:1.0 as parent POM of bar:2.0.
Either way should work but which one is suitable depends on your design.

maven circular dependency + inheritance best practice

I have a few projects in the following structure: Project A, B, C
They are all under a parent project D. in pom.xml under D folder:
<module>A</module>
<module>B</module>
<module>C</module>
The dependency among them is like : A<--B<--C.
And A,B,C are sharing lots of common dependencies.
1.What's the best practice to organize the dependencies in this case in order to make sub poms very light, also the duplicated dependencies are excluded?
2.What should be put into "dependencies" section and what should be put into "dependency-management" section of the parent pom?
3.common dependencies are more like:
log4j, slf4j, thrift, jetty, javax.servlet etc...
most of them are transitive dependencies other than directly required by my projects. Does it make sense put them in the parent D's pom.xml as dependencies, let the sub projects(A,B,C) to inherit them from D? I noticed that if you do so, mvn dependency:tree is going to give you warning like.
[WARNING] Unused declared dependencies found: log4j, slf4j ....
If that gives me warning, I assume it's something maven doesn't recommend u to do?
Most important: Only declare dependencies directly required by a module. It is difficult to suggest anything specific without knowing more about your modules and their dependencies. What are examples for common dependencies in your case? Maybe reorganizing your modules helps in reducing common dependencies. Depending on your project it might be reasonable to put all classes from your modules A, B and C that depend on the same artifact into a new module E.
In my opinion nothing should be put into the dependencies section in the parent pom (and seeing the warning, it seems maven feels the same ;-)). At least put all the versions of dependencies used in more than one module into the dependency-management section of your parent. This helps to always stay at the same version of a specific dependency over your whole project.
As in 2. you should only specify the version of these artifacts in your dependencies-management section in the parent and repeat them in each module that needs it without specifying version. As stated in 1. you should only specify the direct dependencies. For example if you are using slf4j you should only need log4j in the module containing your main class.
To sum up:
Declare only direct dependencies of a module, transitive dependencies are handled automatically by maven (this is one of the main reasons to use maven at all).
Only declare needed dependencies: For example in the case of slf4j you only need one module depending on slf4j-log4j12, all the other modules need only to depend on slf4j-api.
Define versions in your parent pom so all submodules use the same version. Do this in the dependencyManagement section like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
</dependencyManagement>
For each module specify all direct dependencies in the modules pom but without version like this:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>
To handle a lot of dependencies that are shared by a lot of modules you can also use this method: Create a new "dependency collection module" (let's call it X) that does nothing but depend on each needed artifact. Now each module only needs to depend on X to automatically depend on its dependencies too. I don't recommend this method though because (among other reasons) now each module relies on the dependencies in X and you cannot be sure what happens if you remove a dependency from X and you need to look at more than one pom to find a modules direct dependencies.
Hope this helps a bit :-)

Is there a simple way to remove unused dependencies from a maven pom.xml?

I have a large Maven project with many modules and many pom.xml files. The project has changed and I suspect the pom's contain some unnecessary dependencies. Is there is a command which removes any unused dependencies from a pom?
The Maven Dependency Plugin will help, especially the dependency:analyze goal:
dependency:analyze analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused and declared.
Another thing that might help to do some cleanup is the Dependency Convergence report from the Maven Project Info Reports Plugin.
You can use dependency:analyze -DignoreNonCompile.
This will print a list of "used undeclared" and "unused declared" dependencies (while ignoring runtime/provided/test/system scopes for unused dependency analysis.)
But be careful while using this:
As some libraries used at runtime are considered unused!
For more details refer to this link
As others have said, you can use the dependency:analyze goal to find which dependencies are used and declared, used and undeclared, or unused and declared. You may also find dependency:analyze-dep-mgt useful to look for mismatches in your dependencyManagement section.
You can simply remove unwanted direct dependencies from your POM, but if they are introduced by third-party jars, you can use the <exclusions> tags in a dependency to exclude the third-party jars (see the section titled Dependency Exclusions for details and some discussion). Here is an example excluding commons-logging from the Spring dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.5</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Have you looked at the Maven Dependency Plugin ? That won't remove stuff for you but has tools to allow you to do the analysis yourself. I'm thinking particularly of
mvn dependency:tree
I had similar kind of problem and decided to write a script that removes dependencies for me. Using that I got over half of the dependencies away rather easily.
http://samulisiivonen.blogspot.com/2012/01/cleanin-up-maven-dependencies.html
You can use DepClean https://github.com/castor-software/depclean/
DepClean is a tool to automatically remove dependencies that are included in your Java dependency tree but are not actually used in the project's code.
You can use dependency_cleaner https://github.com/junaidbs/dependency_cleaner
This jar will help to identify and remove unwanted dependency from pom.
It will automate the process of Removing a dependency and run then check whether the dependency needful
If you are using eclipse, right-click on the jar in Maven Dependencies:
Select Maven -> Exclude Maven Artifact...

Resources