Project Dependencies
Unless your project
is small, your project may need external Java APIs or frameworks which are
packaged in their own JAR files. These JAR files are needed on the classpath
when you compile your project code.
Keeping your project up-to-date
with the correct versions of these external JAR files can be a comprehensive
task. Each external JAR may again also need other external JAR files etc.
Downloading all these external dependencies (JAR files) recursively and making
sure that the right versions are downloaded is cumbersome. Especially when your
project grows big, and you get more and more external dependencies.
Luckily, Maven has
built-in dependency management. You specify in the POM file what external
libraries your project depends on, and which version, and then Maven downloads
them for you and puts them in your local Maven repository. If any of these
external libraries need other libraries, then these other libraries are also
downloaded into your local Maven repository.
You specify your
project dependencies inside the dependencies element in the
POM file.
Here is an example:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jenkov.crawler</groupId>
<artifactId>java-web-crawler</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
</build>
</project>
Notice
the
dependencies
element in bold. Inside it are two dependency
elements. Each dependency
element describes an external
dependency.
Each
dependency is described by its
groupId
, artifactId
and version
. You may remember that this is also how you identified your
own project in the beginning of the POM file. The example above needs the org.jsoup
group's jsoup
artifact in version 1.7.1
, and the junit
group's junit
artifact in version 4.8.1
.
When this
POM file is executed by Maven, the two dependencies will be downloaded from a
central Maven repository and put into your local Maven repository. If the
dependencies are already found in your local repository, Maven will not
download them. Only if the dependencies are missing will they be downloaded
into your local repository.
Sometimes a
given dependency is not available in the central Maven repository. You can then
download the dependency yourself and put it into your local Maven repository.
Remember to put it into a subdirectory structure matching the
groupId
, artifactId
and version
. Replace all dots (.) with / and
separate the groupId
, artifactId
and version
with / too. Then you have your subdirectory structure.
The two
dependencies downloaded by the example above will be put into the following
subdirectories:
MAVEN_REPOSITORY_ROOT/junit/junit/4.8.1
MAVEN_REPOSITORY_ROOT/org/jsoup/jsoup/1.7.1
External Dependencies
An external
dependency in Maven is a dependency (JAR file) which is not located in a Maven
repository (neiterh local, central or remote repository). It may be located
somewhere on your local hard disk, for instance in the
lib
directory of a webapp, or
somewhere else. The word "external" thus means external to the Maven
repository system - not just external to the project. Most dependencies are
external to the project, but few are external to the repository system (not
located in a repository).
You
configure an external dependency like this:
<dependency>
<groupId>mydependency</groupId>
<artifactId>mydependency</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}\war\WEB-INF\lib\mydependency.jar</systemPath>
</dependency>
The
groupId
and artifactId
are both set
to the name of the dependency.
The
scope
element value
is set to system
.
The
systemPath
element is set
to point to the location of the JAR file containing the dependency.
The
${basedir}
points to the directory
where the POM is located. The rest of the path is relative from that directory.
Snapshot
Dependencies
Snapshot
dependencies are dependencies (JAR files) which are under development. Instead
of constantly updating the version numbers to get the latest version, you can
depend on a snapshot version of the project. Snapshot versions are always
downloaded into your local repository for every build, even if a matching
snapshot version is already located in your local repository. Always
downloading the snapshot dependencies assures that you always have the latest
version in your local repository, for every build.
You can tell
Maven that your project is a snapshot version simply by appending
-SNAPSHOT
to the version number in the
beginning of the POM (where you also set the groupId
and artifactId
). Here is a version
element example:<version>1.0-SNAPSHOT</version>
Notice
the
-SNAPSHOT
appended to the version number.
Depending on
a snapshot version is also done by appending the
-SNAPSHOT
after the version number when
configuring dependencies. Here is an example:<dependency>
<groupId>com.jenkov</groupId>
<artifactId>java-web-crawler</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
The
-SNAPSHOT
appended to the version
number tells Maven that this is
a snapshot version.
You can configure how often Maven shall download snapshot
dependencies in the Maven Settings File.
Transitive
Dependencies
If your
project depends on a dependency, say Dependency ABC, and Dependency ABC itself
depends on another dependency, say Dependency XYZ, then your project has
a transitive dependency on Dependency XYZ.
Exclude
Dependency
Sometimes
the direct dependencies of your project may clash with the transitive
dependencies of the direct dependencies. For instance, you may be using a
JAX-RS implementation which internally uses an older version of the Jackson JSON Toolkit.
However, your application may be using a newer version of the Jackson JSON
Toolkit. How do you know which of the two versions will be used?
A solution
is to specify for the JAX-RS dependency that its dependency on the older
version of the Jackson JSON Toolkit should be excluded. This is also referred
to as dependency exclusion.
You specify
a dependency exclusion inside the declaration of the dependency which
transitive dependency you want to exclude.
Here is an example of declaring a
Maven dependency exclusion:
<dependency>
<groupId>example.jaxrs</groupId>
<artifactId>JAX-RS-TOOLKIT</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
With this
dependency exclusion declaration in place, whatever version of the excluded
dependency that the dependency containing the exclusion is using, will be
ignored during Maven's compilation of the project.
No comments:
Post a Comment