Adding a Dependency

You have a project with a single class which you've successfully compiled and executed. Next, you'll add a dependency to the project descriptor and start to use Maven to manage project dependencies. For the purposes of this lab, assume that you need to work with the Spring Framework. Add a dependency on two artifacts from the Spring Framework—spring-core-1.1.4.jar and spring-web-1.1.4.jar.

How do I do that?

First, you need to locate the JAR you need in Maven's default central repository, served from ibiblio.org at http://www.ibiblio.org/maven/. Load this URL in a web browser and you will see a series of directories; the directory we are interested in is springframework, and the structure of the subdirectories under springframework follows:

http://www.ibiblio.org/maven
    /springframework
        /jars
            spring-core-1.1.4.jar
            spring-dao-1.1.4.jar
            spring-web-1.1.4.jar

To depend on an artifact, you use three elements within dependency—groupId, artifactId, and version. You can add dependencies to both artifacts by replacing the dependencies element in test-application/project.xml with the following XML:

<dependencies>
  <dependency>
    <groupId>springframework</groupId>
               <artifactId>spring-core</artifactId>
    <version>1.1.4</version>
  </dependency>
  <dependency>
    <groupId>springframework</groupId>
               <artifactId>spring-web</artifactId>
    <version>1.1.4</version>
  </dependency>
</dependencies>

Now, run the jar goal and take a look at the output of Maven; it should contain something that looks like this:

Attempting to download spring-core-1.1.4.jar.
266K downloaded
Attempting to download spring-web-1.1.4.jar.
111K downloaded

Figure 1-1 shows the following series of events, triggered by the jar goal:

  1. Maven looked at the POM, as defined in project.xml, and saw the dependency on two artifacts in the springframework group. It then looked for spring-core-1.1.4.jar and spring-web-1.1.4.jar on your Maven local repository.

  2. When Maven didn't find these files, it went to http://www.ibiblio.org/maven/springframework/jars/ to retrieve the JARs. These JAR files were then downloaded and put in your Maven local repository. They were also added to your project's classpath. The next time your project asks for those files, Maven will serve them from your local repository.

The Maven local and remote repositories serving the spring JARs for the test application project

Figure 1-1. The Maven local and remote repositories serving the spring JARs for the test application project

What just happened?

Maven just saved you a serious amount of hassle and time. Prior to the arrival of Maven, dependencies were usually bundled with a project in a lib directory, or a project would have directions for adding the right JARs to your classpath. There are distinct advantages to managing dependencies with Maven; for starters, if your project depends on 30 external JAR files, there is no need to store multiple megabytes of JAR files in a source control repository. This means less storage space, and faster download times when you need to check a project out of source control. In addition, if you have multiple projects which depend on the same external dependency, Maven needs to download a dependency only once, and every project references a single copy of that dependency in your local Maven repository. When dependencies can be downloaded from the remote Maven repository, there is no compelling reason to store and version your project's dependencies.

When Maven downloads a dependency, it is copying a file from a remote Maven repository to a local Maven repository on your local machine. How does Maven locate a dependency? It uses the information from the dependency element in project.xml, as shown in Figure 1-2.

Mapping between POM and Maven repository

Figure 1-2. Mapping between POM and Maven repository

Specifying the groupId tells Maven to look in a specific directory—springframework. Specifying the type tells Maven to look in a specific subdirectory, such as jars or wars (notice the s that Maven is adding to the type element); in this case, type is omitted, as the JAR type is the default. When you specify an artifactId, you are telling Maven which file to download from the jars directory. The top-level directory, springframework, represents the group identifier, the first part of the JAR filename represents the artifact identifier, and the last part of the JAR filename, excluding the extension, represents the version identifier. Maven uses the following formula to resolve a dependency from a repository, where [REPO_ROOT] refers to the URL of your remote repository:

[REPO_ROOT]/<groupId>/<type>s/<artifactId>-<currentVersion>.<type>

Tip

With the introduction of Maven 2.0, the repository may start to resemble the structure of Java packages. Instead of springframework, a groupId in the proposed structure would be org.springframework. In addition, each version will have a separate directory to increase the efficiency of the Maven repository. For information on these proposed changes, see http://docs.codehaus.org/display/MAVEN/Repository+Layout+-+Final.

Maven handles dependencies by maintaining a local repository in your home directory. On a Unix machine, your Maven repository can be found in the ~/.maven/repository directory, and on a Windows machine your Maven repository is in your %USERPROFILE% directory. If you take a look at your local Maven repository, you will notice that it now contains a directory, springframework. The %USERPROFILE%\.maven\repository\springframework\jars directory contains two files for the spring-core dependency: the spring-core-1.1.4.jar file and the spring-core-1.1.4.jar.md5 file, which contains an MD5 hash used to verify the integrity of the spring-core JAR file. Maven 1 does not currently use MD5 to validate the integrity of the artifact, but future releases may use it to validate a downloaded artifact.

Tip

On a Windows machine, %USERPROFILE% usually resolves to a directory such as C:\Documents and Settings\vmassol. %USERPROFILE% is used in the spirit of the abbreviation for a Unix home directory.

What about...

...using the id element?

If you are working with an existing Maven project, you may have dependencies which use the id element. The following dependencies element demonstrates the use of a single id element to depend on version 1.0 of Jakarta Commons Math:

<dependencies>
  <dependency>
    <id>commons-math</id>
    <version>1.0</version>
  </dependency>
</dependencies>

Using the id element alone will work only if the groupId matches the artifactId, and if you browse the Maven repository, you will see the following directory structure:

/commons-math
    /jars
        commons-math-1.0.jar
        commons-math-1.1.jar

While a single id element will work, the use of the id tag alone is deprecated and will disappear in Maven 2. While you may see other Maven projects using this shorthand notation for dependencies, please try to use groupId and artifactId to identify your dependencies.

Get Maven: A Developer's Notebook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.