Maven Best Practices: Managing Dependencies

Source: Internet
Author: User
Tags repetition versions sonatype testng

"If I have seen further it was by standing on the shoulders of giants"--ISAAC Newton (1642-1727)

Some people think that Maven is a dependency management tool and of course this idea is wrong (to be sure, MAVEN is a project management tool that runs through the entire project lifecycle, compiling, testing, packaging, publishing ...). , but there's a reason for Maven's perception of this error, because MAVEN relies on management to be very powerful, and with Maven, you no longer have to face a lot of jars to feel head-on, conflict-dependent, useless dependencies and other issues that can be effectively prevented and resolved. This section describes how to use Maven's dependency management.

The simplest of dependencies

Dependencies are located using MAVEN coordinates, and MAVEN coordinates are mainly composed of Gav (GroupId, Artifactid, version). So, between using any one dependency, you need to know its MAVEN coordinates, about how to find MAVEN coordinates, and the article "Search maven repositories" can help you.

The simplest dependencies are as follows:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.4</version>
</dependency>


In the example above we declare a dependency on JUnit, which is GroupID JUnit, Artifactid is JUnit, and version is 4.4. This set of Gav makes up a maven coordinate, based on which Maven can find the corresponding Junit-4.4.jar file in a local or remote repository.

Dependency Collation

As the project grows, you rely more and more, for example, you rely on a bunch of spring jars, Org.spring.framework:spring-core, Org.spring.framework:beans, Org.spring.framework:spring-web, Org.spring.framework:spring-mock. Their groupid are the same, Artifactid different. In order to manage their versions, you have made a unified upgrade to them, changing version to the latest version. However, obviously, when the POM is very large you may make mistakes, and when the version is inconsistent, some strange compatibility problems may arise.

MAVEN has a solution for this:

<dependencies> <dependency> <groupId>org.spring.framework</groupId> &L T;artifactid>spring-core</artifactid> <version>${spring.version}</version> </dependency > <dependency> <groupId>org.spring.framework</groupId> <artifactid>spring-beans</a rtifactid> <version>${spring.version}</version> </dependency> <dependency> <grou Pid>org.spring.framework</groupid> <artifactId>spring-web</artifactId> <version>${ spring.version}</version> </dependency> <dependency> <groupid>org.spring.framework</gr Oupid> <artifactId>spring-mock</artifactId> <version>${spring.version}</version> < /dependency> </dependencies> <properties> <spring.version>2.5</spring.version> </ Properties> 


Here we define a Maven property whose name is Spring.version and the value is 2.5. In this pom, we can refer to this property in the same way as ${spring.version}. We see that all spring-dependent version elements are now ${spring.version}, and when Maven runs, it automatically replaces the reference with the value 2.5来.

When we need to upgrade spring, just change one place, and you can now make sure that all spring dependent packages are the same version.

range of Dependencies (scope)

The first example in this article is actually flawed, and for junit, generally you only need it when you run the test, that is, it doesn't make sense for Src/main/java's classpath, and it's not a good thing to get junit jar files into the final release package. This needlessly increases the size of the release package.

In fact, we should do this:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.4</version>
  <scope>test</test>
</dependency>


As a result, JUnit is not available for the main source Classpath and is not packaged for test source classpath.

For example, in the development of Java EE application, we will use SERVLET-API, it is necessary for the main source code and test source, because our code will introduce SERVLET-API package. However, it is problematic to put it into the war package when it is packaged, because the Web container will provide SERVLET-API, and if we package it again it will cause a dependency conflict, the solution is as follows:

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactid>servlet-api</ artifactid>
  <version>2.4</version>
  <scope>provided</scope>
</ Dependency>


Setting the dependency scope to provided means that the dependency is available for the main source Classpath, as well as the test classpath, but will not be packaged. This is exactly what Servlet-api needs.

Here is a summary of the main areas of dependence and role:

Range of dependencies (scope) Main source Classpath available Test source Classpath Available will be packaged
Compile default value TRUE TRUE TRUE
Test FALSE TRUE FALSE
Runtime FALSE TRUE TRUE
Provided TRUE TRUE FALSE

It is important to note that when we do not declare a dependency scope, its default dependency is compile.

classifier (classifer)

Gav is the most basic and important part of MAVEN coordinates, but Gav is not all. There is also an element called the classifier (classifier), 90% of which you will not use it, but in some cases the classifier is very indispensable.

As a simple example, when we need to rely on testng, a simple declaration of Gav will go wrong, because testng forces you to provide the classifier to differentiate Jdk14 and jdk15, and we need to declare this dependency on testng:

<dependency>
  <groupId>org.testng</groupId>
  <artifactid>testng</artifactid >
  <version>5.7</version>
  <classifier>jdk15</classifier>
</dependency >


You will notice that MAVEN has downloaded a file named Testng-5.7-jdk15.jar. Its naming pattern is actually <artifactId>-<version>-<classifier>.<packaging>. Once you understand this pattern, you will find that many files are actually the default component classifier extensions, such as Myapp-1.0-test.jar, Myapp-1.0-sources.jar.

The classifier also has a very useful purpose: we can use it to declare a dependency on the test component, for example, we declare some basic classes in the Src/test/java of a core module, and then we find that these test base classes are useful for testing classes in many other modules. Without classifiers, there is no way to rely on content in Src/test/java, because the content is not packaged into the main component, and they are individually packaged into a pattern of <artifactid>-<version>- The Test.jar file.

We can use classifiers to rely on such test artifacts:

<dependency>
  <groupId>org.myorg.myapp</groupId>
  <artifactid>core</ artifactid>
  <version>${project.version}</version>
  <classifier>test</classifier >
</dependency>


By understanding the classifiers, the resources that are available for dependency become richer.

Dependency Management (dependencymanagement)

When you have only one MAVEN module, you don't have to look at this part at all. But you should be aware that only one MAVEN module project is basically just a toy.

In the actual project, you will have a large number of MAVEN modules, and you often find that these modules have a lot of dependencies are full projects, a module has a dependency on spring, B module also has, their dependency configuration is identical, the same groupid, Artifactid, version, or exclusions, Classifer. The attentive branch found that this was a repetition, and repetition meant a potential problem, and Maven provided the dependencymanagement to eliminate this repetition.

The correct approach is to:

1. Configuring dependencies in the parent module using Dependencymanagement

2. Use dependencies to add dependencies in sub-modules

Dependencymanagement actually does not really introduce any dependencies, dependencies will. However, when a dependency is configured in the parent module, the submodule can automatically inherit the corresponding parent module dependency configuration by simply using simple GroupID and Artifactid.

Here is an example from the Maven authoritative guide:

This is stated in the parent module:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupid>org.sonatype.mavenbook </groupId>
  <artifactId>a-parent</artifactId>
  <version>1.0.0</version>
  ...
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupid>mysql</ groupid>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.2</ Version>
      </dependency> ...
    <dependencies>
  </dependencyManagement>


This is stated in the sub-module:

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId> org.sonatype.mavenbook</groupid>
    <artifactId>a-parent</artifactId>
    <version> 1.0.0</version>
  </parent>
  <artifactId>project-a</artifactId> ...
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId> mysql-connector-java</artifactid>
    </dependency>
  </dependencies>
</project >


The more complex you rely on configuration, the greater the role of dependency management, which not only helps you simplify configuration, it can also help you to consolidate dependencies, which means that there is only one dependency configuration for a component (such as MySQL) throughout the project, which avoids the introduction of different versions of dependencies and avoids dependency conflicts.

Summary

This article describes some of the important concepts in MAVEN dependencies and provides some best practices through the sample, such as dependency collations, dependency scopes, classifiers, and dependency management. My goal is to tell you about 80% of what you will need to know in your actual work, and if you need a deeper understanding, please refer to the MAVEN authoritative guide.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.