maven: include indirect dependencies or not? - java

Let's say I have a maven project that depend on one external library libA. And libA depends on libB. In my pom.xml, I declare libA as a dependency and all is well.
Not let's assume that during dev, I start using classes from libB too. libB is already pulled in the project through libA, so everything compiles fine and work, but should I also declare libB in my pom.xml?
If I don't, mvn dependency:analyze will complain that I use undeclared dependencies.
If I declare libB, maven will load it only once to avoid duplicates, so if I declare it after, it's as if I didn't, and if I declared it before, I risk forcing a version of libB incompatible with libA.
What's the better answer?

Do what Federico suggests. It is the Maven way.

Related

NoClassDefFoundError when Maven test-scoped dependency overrides transitive compile-scoped dependency

We have several deployables, and have extracted common code into several libraries. Deployable app A has a (default-scoped) Maven dependency on library B, and a test-scoped dependency on library C.
I made a change to library B, which used a method from, and so created a dependency on, library C. This caused app A to fail at run-time with NoClassDefFoundErrors. App A's unit tests all passed, of course, so we only found this in our staging environment. (Other apps either had no direct dependency on library C, or had a default-scoped dependency on it, and so continued to work.)
The obvious fix worked, of course: I edited A's pom.xml to make the dependency on C default scope.
My question is: Are we doing something wrong? Or is this how things are supposed to work? Is anyone aware of an automated way of detecting the potential problem at build-time and failing the build?
You are not doing something wrong. Maven made a peculiar design choice here. See also
Maven: test vs. transitive compile, especially Tunakis comment on my question.
and
Maven dependency within dependency with different scope
My advice: Eliminate C from A's pom.xml. Only add test dependencies if these dependencies are not already on the dependency tree.

Do transitive dependencies need to be on the compile-time path?

I am using Maven as my build tool for my java application, but this question might be applicable to other build tools.
I declared a dependency on A.jar in my pom.xml
A.jar also had a pom.xml and declared a dependency on B.jar
I used classes from B.jar in my code, and maven compiled my code just fine.
I'm confused because I would have expected to have to explicitly declare a dependency on B.jar in my pom.xml in order to use stuff from it.
Is this normal behavior for other build tools (adding transitive dependencies to the compile time path)?
Why do you need transitive dependencies in order to compile? I understand that they are needed when the code is packaged and/or at runtime. But I can't seem to think of a case where transitive dependencies are needed for compiling.
You should have a dependency if you have an import.
The mvn dependency:analyze can help.
i believe the thought is
...the jar is going to be packaged to be used at runtime ( by the dependency A.jar). So why not let the project have access to them.

How do I tell maven that an artifact has been renamed?

Consider the following scenario.
I have a Java 1.8 project that depends on a java 8 artifact called foo-bar and a java 5 artifact called baz-qux. baz-qux also depends on foo-bar. But it uses the special slimmed down java 5 build called foo-bar-java5. Thus by including baz-qux into my project, I transitively bring in foo-bar-java5. In the end I have an undesirable state where I now have foo-bar and foo-bar-java5. Apparently there's no way to do a global exclude. So I can't just exclude foo-bar-java5. Instead, I must clutter up my cluttered pom and exclude it everywhere it will be pulled in transitively.
With that said, is there any way I can specify that foo-bar provides foo-bar-java5? Or is the only option to truly exclude foo-bar-java5 everywhere?
Here is an answer from another question that may work for you:
https://stackoverflow.com/a/9623517/2879838
Basically, explicitly list the foo-bar-java5 as a dependency in your project and list it as provided. This will tell maven not to put that jar into the archive during the build. This should be a lot less messier than excluding it everywhere.

Can I add maven dependencies that are packed as anything other than .jar?

I just produced my first parent-module project with maven, and successfully installed it. Can I add this project as a dependency in another project, only by referring to the parent? My Eclipse IDE complains that it can't find the parent.jar, but that is not a surprise, as it is packaged as parent.pom.
Question:
So is it possible to add a parent (.pom) dependency, and get all transitive dependencies for free, or do I have to add .jar's.
Bonus Question:
Is it possible to add dependencies to other packaging formats as well, like a war? I can't really figure out how that would work, or why I would need that at this point though. Just curious.
Disclaimer:
I'm still learning maven, and find the philosophy and theory of it to be great. However, there are so many pits and reefs that seems to pop out, and more than once, I struggle to see if I'm trying to do something impossible, or if there is another mistake in configurations I.E. Right now Eclipse says it can't find any of my .m2 referenced dependencies in this one particular project. I have no idea why, as other projects works fine. I am in other words trying to find the error, by checking one area at the time...
Answer: Yes, you can add different types such as pom, test-jar and so on. Jar is just the default
Bonus Answer: Yes, you can specify type war as well
The Maven-Guide defines the following types: "The current core packaging values are: pom, jar, maven-plugin, ejb, war, ear, rar, par."
Here is a example on how a POM is included:
<dependencies>
<dependency>
<groupId>com.my</groupId>
<artifactId>comm-group</artifactId>
<type>pom</type>
</dependency>
</dependencies>
This (the pom of comm-group) is oftenly used to group certain dependencies and include all of them using the type-pom.
Here is additional information on grouping: http://blog.sonatype.com/2009/10/maven-tips-and-tricks-grouping-dependencies/#.VFC7LR_JY8c Note that there are similar behaviours you could create using polymorphism.
I had my issues with maven when we migrated from Ant and i still have certain concernes on it (like were is the advantage of maven if 80% of our SWEs apply wrong scopes, types and so on leading to a massive drawback if they just 'need to add a fcking jar' as well as to refactorings lead by "maven gurus").
BUT: I can guarantee you that if you go throught http://maven.apache.org/pom.html completely you will aquire statisfieing results compared to ANT over time.
Update: I just ran into the case where my pom could not be included on the remote build server while it worked building it from inside Intellij Idea/ Eclipse. Type definition in my case had to be lowercase (e.g. 'pom' instead of 'POM').

Finding unused (compile-scoped) jars in multiple projects using maven ?

I have a webapp that consists of multiple projects. We assemble using Ant and we suspect that some of the jars in /java directory are unneeded.
To find unneeded jars I ran
mvn dependency:analyze -DignoreNonCompile
to get a list of unused declared jars for each project. However it is possible that a jar unused by one project is still used by another. To check this, I ran
mvn dependency:tree
to get the dependency structure of all projects.
Using information from these commands, I will now use a script to check if a jar exists such that it is unused in all projects that declare it. Is this a reasonable approach for compile-scoped jars? What about jars in other scopes?
Thanks.
However it is possible that a jar unused by one project is still used
by another.
I recommend to declare all needed dependencies as direct dependencies and not rely on transitive dependencies which might get removed in a newer version.
Define the versions of the dependencies in the DependencyManagement section of the common parent POM and omit the versions later when declaring the dependcies. Like this you can make sure you're using the same version of the dependencies in all your projects.

Categories