CHAPTER 3

image

Maven Dependency Management

Enterprise-level projects typically depend on a variety of open source libraries. Consider the scenario where you want to use Log4J for your application logging. To accomplish this, you would go to the Log4J download page, download the JAR file, and put it in your project’s lib folder or add it to the project’s class path. As you may know already, there are a couple of problems with this approach:

  1. You need to check JAR files into SVN so that your projects can be built on a computer other than your own.
  2. The JAR file you downloaded might depend on a few other libraries. You would now have to hunt down all of those dependencies and add them to your project.
  3. When the time comes to upgrade the JAR file, you need to start the process all over again.
  4. It becomes difficult to share JAR files across teams within your organization.

To address these problems, Maven provides declarative dependency management. With this approach, you declare your project’s dependencies in an external file called pom.xml. Maven will automatically download those dependencies and hand them over to your project for the purpose of building, testing, or packaging.

Figure 3-1 shows a high-level view of Maven’s dependency management. As you can see, Maven interacts with repositories that hold artifacts and related metadata. Repositories that are typically accessed over the web are considered remote and are maintained by a third party. The default remote repository with which Maven interacts is called Maven Central, and it is located at repo.maven.apache.org and uk.maven.org. Maven places the downloaded artifacts in the local repository.

9781484208427_Fig03-01.jpg

Figure 3-1. Maven dependency management

Although the architecture shown in Figure 3-1 works in the majority of cases, it poses a few problems in an enterprise environment. The first problem is that sharing company-related artifacts between teams is not possible. Because of security and intellectual property concerns, you wouldn’t want to publish your enterprise’s artifacts on Maven Central. Another problem concerns legal and licensing issues. Your company might want the teams only to use officially approved open source software, and this architecture would not fit in that model. The final issue concerns bandwidth and download speeds. In times of heavy load on Maven Central, the download speeds of Maven artifacts are reduced, and this might have a negative impact on your builds. Hence, most enterprises employ the architecture shown in Figure 3-2.

9781484208427_Fig03-02.jpg

Figure 3-2. Enterprise Maven repository architecture

The internal repository manager acts as a proxy to remote repositories. Because you have full control over the internal repository, you can regulate the types of artifacts allowed in your company. Additionally, you can also push your organization’s artifacts onto the server, thereby enabling collaboration. There are several open source repository managers. Table 3-1 lists just some of them.

Table 3-1. Open Source Repository Managers

Repository Manager

URL

Sonatype Nexus

www.sonatype.com/nexus

Apache Archiva

http://archiva.apache.org/

Artifactory

www.jfrog.com/open-source/

Using Repositories

In order to use a new repository, you need to modify the settings.xml file. Listing 3-1 shows Spring and JBoss repositories added to the settings.xml file. In this same way, you can add to your company’s repository manager.

Listing 3-1. Adding Repositories in settings.xml

<?xml version="1.0" encoding="UTF-8" ?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  .......

        <profiles>
            <profile>
              <id>your_company</id>
              <repositories>
                        <repository>
                          <id>spring_repo</id>
                          <url>http://repo.spring.io/release/</url>
                        </repository>
                        <repository>
                          <id>jboss_repo</id>
                          <url>https://repository.jboss.org/</url>
                        </repository>
                  </repositories>
                </profile>
        </profiles>
        <activeProfiles>
            <activeProfile>your_company</activeProfile>
        </activeProfiles>
  .......

</settings>

Image Note  Information regarding repositories can be provided in the settings.xml or the pom.xml file. There are pros and cons to each approach. Putting repository information in the pom.xml file can make your builds portable. It enables developers to download projects and simply build them without any further modifications to their local settings.xml file. The problem with this approach is that when artifacts are released, the corresponding pom.xml files will have the repository information hard coded in them. If the repository URLs were ever to change, consumers of these artifacts will run into errors due to broken repository paths. Putting repository information in the settings.xml file addresses this problem, and because of the flexibility it provides, the settings.xml approach is typically recommended in an enterprise setting.

Dependency Identification

Maven dependencies are typically archives such as JAR, WAR, enterprise archive (EAR), and ZIP. Each Maven dependency is uniquely identified using the following group, artifact, and version (GAV) coordinates:

  • groupId: Identifier of the organization or group that is responsible for this project. Examples include org.hibernate, log4j, and org.springframework.boot.
  • artifactId: Identifier of the artifact being generated by the project. This must be unique among the projects using the same groupId. Examples include hibernate-tools, log4j, spring-core, and so on.
  • version: Indicates the version number of the project. Examples include 1.0.0, 2.3.1-SNAPSHOT, and 4.3.6.Final.
  • type: Indicates the packing of the generated artifact. Examples include JAR, WAR, and EAR.

Transitive Dependencies

Dependencies declared in your project’s pom.xml file often have their own dependencies. Such dependencies are called transitive dependencies. Take the example of Hibernate Core. For it to function properly, it requires JBoss Logging, dom4j, javaassist, and so forth. The Hibernate Core declared in your pom.xml file is considered a direct dependency, and dependencies such as dom4j and javaassist are considered your project’s transitive dependencies. A key benefit of Maven is that it automatically deals with transitive dependencies and includes them in your project.

Figure 3-3 provides an example of transitive dependencies. Notice that transitive dependencies can have their own dependencies. As you might imagine, this can quickly get complex, especially when multiple direct dependencies pull different versions of the same JAR file.

9781484208427_Fig03-03.jpg

Figure 3-3. Transitive dependencies

Maven uses a technique known as dependency mediation to resolve version conflicts. Simply stated, dependency mediation allows Maven to pull the dependency that is closest to the project in the tree. In Figure 3-3, there are two versions of dependency B: 0.0.8 and 1.0.0. In this scenario, version 0.0.8 of dependency B is included in the project, because it is a direct dependency and closest to the tree. Now look at the three versions of dependency F: 0.1.3, 1.0.0, and 2.2.0. All three dependencies are at the same depth. In this scenario, Maven will use the first-found dependency, which would be 0.1.3, and not the latest 2.2.0 version.

Image Note  Although highly useful, transitive dependencies can cause problems and unpredictable side effects, as you might end up including unwanted JAR files or older versions of JAR files. Always analyze your dependency tree and make sure you are bundling the dependencies you need and excluding the ones you don’t require.

Dependency Scope

Consider a project that uses JUnit for its unit testing. The JUnit JAR file you included in your project is only needed during testing. You really don’t need to bundle the JUnit JAR in your final production archive. Similarly, consider the MySQL database driver, mysql-connector-java.jar file. You need the dependency when you are running the application inside a container such as Tomcat. Maven uses the concept of scope, which allows you to specify when and where you need a particular dependency.

Maven provides the following six scopes:

  • compile: Dependencies with the compile scope are available in the class path in all phases on a project build, test, and run. This is the default scope.
  • provided: Dependencies with the provided scope are available in the class path during the build and test phases. They don’t get bundled within the generated artifact. Examples of dependencies that use this scope include Servlet api, JSP api, and so on.
  • runtime: Dependencies with the runtime scope are not available in the class path during the build phase. Instead they get bundled in the generated artifact and are available during runtime.
  • test: Dependencies with the test scope are available during the test phase. JUnit and TestNG are good examples of dependencies with the test scope.
  • system: Dependencies with the system scope are similar to dependencies with the provided scope, except that these dependencies are not retrieved from the repository. Instead, a hard-coded path to the file system is specified from which the dependencies are used.
  • import: The import scope is applicable for .pom file dependencies only. It allows you to include dependency management information from a remote .pom file. The import scope is available only in Maven 2.0.9 or later.

Manual Dependency Installation

Ideally, you will be pulling dependencies in your projects from public repositories or your enterprise repository manager. However, there will be times where you need an archive available in your local repository so that you can continue your development. For example, you might be waiting on your system administrators to add the required JAR file to your enterprise repository manager.

Maven provides a handy way of installing an archive into your local repository with the install plug-in. Listing 3-2 installs a test.jar file located in the c:apressgswm-bookchapter3 folder.

Listing 3-2. Installing Dependency Manually

C:apressgswm-bookchapter3>mvn install:install-file -DgroupId=com.apress.gswmbook -DartifactId=test -Dversion=1.0.0 -Dfile=C:apressgswm-bookchapter3	est.jar -Dpackaging=jar -DgeneratePom=true
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom---
[INFO] Installing C:apressgswm-bookchapter3 est.jar to C:Users<<USER_NAME>>.m2 epositorycomapressgswmbook est1.0.0 est-1.0.0.jar
[INFO] Installing C:Users<<USER_NAME>>AppDataLocalTempmvninstall2668943665146984418.pom to C:Users<<USER_NAME>>.m2 epositorycomapressgswmbook est1.0.0 est-1.0.0.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.470 s
[INFO] Finished at: 2014-10-24T20:23:36-06:00
[INFO] Final Memory: 4M/15M

After seeing the BUILD SUCCESS message, you can verify the installation by going to your local Maven repository, as shown in Figure 3-4.

9781484208427_Fig03-04.jpg

Figure 3-4. Dependency added to repository

Summary

Dependency management is at the heart of Maven. Every nontrivial Java project relies on open source or external artifacts, and Maven’s dependency management automates the process of retrieving those artifacts and including them at the right stages of the build process. You also learned that Maven uses GAV coordinates to identify its artifacts.

In the next chapter, you will learn about the organization of a basic Maven project.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.21.158