Maven Concepts - Dependencies
Internal
!!!The Dependency Mechanism
Source article "Introduction to the Dependency Mechanism" [1]
!!!Transitive Dependencies
Maven walks the dependency graph of your direct dependencies, allowing you to avoid the need to discover and specify those libraries by hand. This is possible because Maven reads the project files of the dependencies, recursively, from their repositories. There is no limit on the number of recursive levels Maven can walk.
Since the transitive dependency graph can grow pretty large, Maven offer a series of features that can be used to limit and manage the extent of the graph ([dependency mediation|MavenConcepts#DependencyMediation], [dependency management|MavenConcepts#DependencyManagement], [dependency scope|MavenConcepts#DependencyScope], [excluded dependencies| MavenConcepts#ExcludedDependencies], [optional dependencies|MavenConcepts#OptionalDependencies]).
!!!Dependency Mediation
Dependency mediation is used when multiple version of the same artifact are found while building the transitive graph.
The default mediation mechanism is "nearest definition", where the "closest" dependency in the graph dictates the version. However, a certain (different) version can be guaranteed by declaring it explicitly in the [dependency management|MavenConcepts#DependencyManagement] section of the POM.
If two dependency versions are at the same depth, the declaration order counts: the first declaration wins.
!!!Dependency Scope
The dependency scope is a declarative feature that allows you to only include dependencies appropriate for the current stage of the build. There are 6 scopes:
!!compile
The default scope, when none is specified. Compile dependencies are available in all classpaths of the project and propagated to dependent projects.
!!provided
Makes the dependencies available on the compilation and test class path, but does not includes the dependencies in the artifacts - because "provided" dependencies are assumed to be provided by the deployment environment. The provided scope is not transitive.
!!runtime
Places the dependencies in the runtime and test classpaths, but not in the compile classpath.
!!test
This scope indicates that the dependency is not required for normal use of the application. The dependency is placed on the test compilation and test execution classpaths.
!!system
Similar with "provided", except that the dependency artifact must be specified in the POM - it is not looked up in a repository:
{{{
... <dependency> <groupId>javax.sql</groupId> <artifactId>jdbc-stdext</artifactId> <version>2.0</version> <scope>system</scope> <systemPath>${java.home}/lib/rt.jar</systemPath> </dependency>
...
<dependency> <groupId>sample</groupId> <artifactId>com.sample</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/yourJar.jar</systemPath> </dependency> ...
}}}
!!import
This scope is only used with a dependency of the type "pom" in <dependencyManagement> section. The effect is inclusion of the dependencies specified in the POM's <dependencyManagement> section. This is used to implement the [Bill of Materials (BOM) pattern|MavenConcepts#BOM]. Since they are replaced, dependencies with a scope of "import" do not participate in limiting the transitivity of a dependency.
!!!How Scopes Affect Transitivity
If a dependency is set to the scope in the left column, transitive dependencies of that dependency with the scope across the top row will result in a dependency in the main project with the scope listed at the intersection. No scope listed means the dependency will be omitted:
| | compile | provided | runtime | test |compile | compile | - | runtime | - |provided | provided| - | provided | - |runtime | runtime | - | runtime | - |test | test | - | test | -
!!!Dependency Management
The dependency management is a Maven feature that provide the following functions:
1. It allows for the __centralization of the dependency information__. The dependency management can be used to specify versions for dependencies whose version were not specified directly in the <dependencies> section.
2. __Dependency information inheritance__. When you have a set of projects that inherit a common parent you can put all the information about the dependencies in the <dependencyManagement> section of the common POM and have simpler references to artifacts in child POMs.
3. It allows project authors to declare __specific versions for their dependencies, when those dependencies are encountered in the transitive dependency graph__ (you can see it as a mask that applies to the transitive dependency graph).
!!!Excluded Dependencies
Dependencies that are pulled in with the transitive dependency graph can be explicitly excluded with the <exclusion> element.
!!!Optional Dependencies
Optional dependencies do are not included in the transitive dependency graph. Optional means "excluded by default".
!!!BOM
BOM (Bill of Material) is a pattern that allow projects to import managed dependencies from another project. This is accomplished by declaring a "pom" artifact as a dependency with the "import" scope (the bill of materials). The bill of materials is essentially versioning a list of dependencies.
A project ("bom") can declare itself a "bill of materials" and it defines the versions of the artifacts that will be created in the library of artifacts. This effectively incapsulates a set of versions and gives a unique version to the incapsulated list. Other project (X) can import it, thus importing all dependencies declared in the bill of material.
Also see [import scope|MavenConcepts#import].
"bom" POM:
{{{ <project ...>
<groupId>com.test</groupId> <artifactId>bom</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <properties> <project1Version>1.0.0</project1Version> <project2Version>1.0.0</project2Version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.test</groupId> <artifactId>project1</artifactId> <version>${project1Version}</version> </dependency> <dependency> <groupId>com.test</groupId> <artifactId>project2</artifactId> <version>${project1Version}</version> </dependency> </dependencies> </dependencyManagement>
</project> }}}
X POM:
{{{ <project ...>
<groupId>X</groupId> <artifactId>x</artifactId> <version>1.0</version> <packaging>jar</packaging> <dependencyManagement> <dependencies> <dependency> <groupId>com.test</groupId> <artifactId>bom</artifactId> <version>1.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.test</groupId> <artifactId>project1</artifactId> </dependency> <dependency> <groupId>com.test</groupId> <artifactId>project2</artifactId> </dependency> </dependencies>
</project> }}}