In my project I have module M1 it use library A. This library have dependency to library B.
And in another module M2 I want to use library B.
And of course I have "root" module which depend on all my modules so versions of library B should be the same across all projects.
So I added B to dependency of my M2 module but don't know how to specify it version because I need exactly same version as library A use.
If I specify current version of library B then when I will upgrade library A to new version I will forget to update version of B in my module.
Also I don't want to put A as dependency of M2 because I need only limited part of it's functionality.
What is best practices for my case?
The maven enforce plugin can break the build if the versions diverge so that yo do not forget to update: see https://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html
There are several options some of them you exclude explicitely. Let me mention them for the sake of completeness anyway:
Include B as a dependency in M2.
Advantage: Cleanest solution with respect to adding only those functionality to M2 that's actually needed.
Disadvantage: Version of B in M2 has to be kept in sync with versin of B in A manually.
Include A as a dependency in M2.
Advantage: Central <DependencyManagement> can be used in your parent POM. Hence, Versions of B will always be the same in all sub-projects.
Disadvantage: Functionality of A not needed in M2 is added to M2.
Include M1 as a dependency in M2.
Advantage: M2 always uses the same version of B as A without having to deal with B as a dependency at all.
Disadvantage: Functionality of M1 and of A not needed in M2 is added to M2.
Use <dependency>/.../<exclusion> to exclude B from A in M1.
Advantage: Central <DependencyManagement> can be used in your parent POM. Hence, Versions of B will always be the same in all sub-projects.
Disadvantage: Version of B has to be kept in sync with version of B in A manually.
[Input is welcome in case there's anything else I haven't thought of.]
Try Maven Enforcer Plugin's Dependency Convergence mentioned by Assen Kolov in his answer. If it works for a mixture of direct and transitive dependencies, like in your case, as well, I'd use it in conjunction with 1.
Related
I would like to implement a release system similar to the one used at a large PNW company at which I worked recently. I would like to know if I can model it with Maven (to which I am relatively new).
I have applications A1, A2, ..., An. They depend on library L. I would like to designate the next release of L to be version 2.0. I would like A1 - An to declare dependency on L v2.0.
I would then like to release successive L artifacts, preferably named something like L-[timestamp]-[git-hash] (so that, given an artifact, I can identify the source that created it) as L v2.0. Any subsequent rebuilds of any of A1 - An would build against that newly-released version.
Can I do this with Maven?
Yes, you should be able to accomplish this with Maven.
Have a look at the Versions Maven plugin. It has a goal versions:use-latest-releases that will replace the release version of an artifact in your POM with the latest released version that it finds in the repository.
For example, you could use the Versions plugin to update the L dependency in A's POM before cutting the next release of A using release:perform.
versions:use-latest-releases: http://www.mojohaus.org/versions-maven-plugin/use-latest-releases-mojo.html
release:perform: https://maven.apache.org/maven-release/maven-release-plugin/perform-mojo.html
Does Maven install the necessary dependencies when adding a plugin to the pom file?
For example, when adding the following code to a pom file, does maven download the necessary dependencies for that plugin?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
Yes to both questions. Sub-dependencies are called Transitive Dependencies and are handled natively in Maven 2.0. You can read about it more on the Maven website.
Specifically:
Transitive dependencies are a new feature in Maven 2.0. This allows
you to avoid needing to discover and specify the libraries that your
own dependencies require, and including them automatically.
This feature is facilitated by reading the project files of your
dependencies from the remote repositories specified. In general, all
dependencies of those projects are used in your project, as are any
that the project inherits from its parents, or from its dependencies,
and so on.
There is no limit to the number of levels that dependencies can be
gathered from, and will only cause a problem if a cyclic dependency is
discovered.
With transitive dependencies, the graph of included libraries can
quickly grow quite large. For this reason, there are some additional
features that will limit which dependencies are included:
Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are
encountered. Currently, Maven 2.0 only supports using the "nearest
definition" which means that it will use the version of the closest
dependency to your project in the tree of dependencies. You can always
guarantee a version by declaring it explicitly in your project's POM.
Note that if two dependency versions are at the same depth in the
dependency tree, until Maven 2.0.8 it was not defined which one would
win, but since Maven 2.0.9 it's the order in the declaration that
counts: the first declaration wins.
"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if
dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A
-> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a
dependency to D 2.0 in A to force the use of D 2.0
Dependency management - this allows project authors to directly specify the versions of artifacts to be used when they are encountered
in transitive dependencies or in dependencies where no version has
been specified. In the example in the preceding section a dependency
was directly added to A even though it is not directly used by A.
Instead, A can include D as a dependency in its dependencyManagement
section and directly control which version of D is used when, or if,
it is ever referenced.
Dependency scope - this allows you to only include dependencies appropriate for the current stage of the build. This is described in
more detail below.
Excluded dependencies - If project X depends on project Y, and project Y depends on project Z, the owner of project X can explicitly
exclude project Z as a dependency, using the "exclusion" element.
Optional dependencies - If project Y depends on project Z, the owner
of project Y can mark project Z as an optional dependency, using the
"optional" element. When project X depends on project Y, X will depend
only on Y and not on Y's optional dependency Z. The owner of project X
may then explicitly add a dependency on Z, at her option. (It may be
helpful to think of optional dependencies as "excluded by default.")
If you take a look at the plugin pom
http://repo1.maven.org/maven2/org/codehaus/sonar/sonar-maven-plugin/2.7/sonar-maven-plugin-2.7.pom
Maven will pull all relevant dependencies for the plugin according to
<dependencies>
section of the plugin pom
I'm not quite sure of the best way to handle the following situation in my Maven project...
I have two direct dependencies A and B. Both depend on different versions of C. Dependency A is compatible with both versions of C, but dependency B is only compatible with it's declared version of C. I'd like to simply use whatever version of C that B declares.
I realize that I can exclude the dependency of C in dependency A, but then if I ever removed dependency B or if C was removed as a dependency of B...A would not work anymore.
I also realize that I can declare B's current version of C in my dependency management section, but then I would not seamlessly get the change if B ever changed it's version of C.
What is the prescribed way to handle this sort of situation?
The best way as recommended, although, slightly indirectly, by the maven docs is to use the dependency management feature. Quoting the doc,
A second, and very important use of the dependency management section
is to control the versions of artifacts used in transitive
dependencies.
I can understand that you are forced to update the version of C on your target project, say T, every time B uses a new version of C, but you also have to look at this from the T's POV - the target project T, ought to know and be able to control all the versions of the transitive dependencies it has.
I was exploring archiva as the intenal maven repository manager. I need to manage dependecies.
My application is bundle of modules. I would like to manage dependencies on the basis of higher version.
For eg. Module A uses version 1 of the dependency. While module B uses version 2 of the same dependecy.
Now if a person want to use both the modules then the result should be such that the version two should get referred instead of version 1.
I think that is not a wanted behaviour. What if Version 1 and 2 are incompatible. If you have controll of both Modules A and B than its better to let them use the same version of their dependencies. I Typically declare common dependencies in the parent POM in the dependencyManagement section to so each submodule uses the same version.
I was exploring maven, currently using Ant. The application which we use here have different modules.
Now if I add dependencies to those how I can solve version conflict. Example module A has the dependecy of version1. while module B has the dependency of version2 now If someone need to work with both the module together than it will automatically resolve to version2 that is higher version.
Is there any internal behavior of maven or any command that I can use to resolve version conflicts?
Maven "solves" this problem by using the nearest declaration for transitives dependencies.
e.g.
A -> X -> externalLib 2.0
B -> externalLib 1.0
C -> A,B will result in using externalLib 1.0 since the declaration (over B) of 1.0 is nearer to C that over A and X
If they have the same distance the position within the POM file decides.
This is typically not the kind of "solution" you want. Since they might be incompatible it is better to choose a version manualle explicitely and declare this version in the pom of C
C -> externalLib 2.1
Note, if there is no version that is compatible to both X and B, there is no solution and Java does not support several versions of the same lib in one classloader. In this case you thould think of using OSGi or similar.
this link provides solution to your problem
http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html