Skip to content

Dependency Management

If our project depends on third-party jar packages, such as commons logging, the question arises: where can we download the commons logging jar?

If we also want to depend on log4j, which jar packages are needed for log4j?

Similar dependencies include JUnit, JavaMail, MySQL drivers, etc. A feasible method is to use a search engine to find the project's official website, manually download the zip packages, extract them, and add them to the classpath. However, this process is very tedious.

Maven solves the dependency management problem. For example, if our project depends on the abc jar package, and abc itself depends on the xyz jar package:

┌──────────────┐
│Sample Project│
└──────────────┘


┌──────────────┐
│     abc      │
└──────────────┘


┌──────────────┐
│     xyz      │
└──────────────┘

When we declare a dependency on abc, Maven automatically adds both abc and xyz to our project's dependencies. We don't need to manually determine whether abc depends on xyz.

Therefore, Maven's primary role is to solve dependency management. By declaring that our project requires abc, Maven automatically imports the abc jar package, then determines that abc depends on xyz, and automatically imports the xyz jar package. In the end, our project depends on both abc and xyz jar packages.

Complex Dependency Example

Let's look at a complex dependency example:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>1.4.2.RELEASE</version>
</dependency>

When we declare a dependency on spring-boot-starter-web, Maven will automatically resolve and determine that approximately twenty to thirty other dependencies are required:

spring-boot-starter-web
  spring-boot-starter
    spring-boot
    spring-boot-autoconfigure
    spring-boot-starter-logging
      logback-classic
        logback-core
        slf4j-api
      jcl-over-slf4j
        slf4j-api
      jul-to-slf4j
        slf4j-api
      log4j-over-slf4j
        slf4j-api
    spring-core
    snakeyaml
  spring-boot-starter-tomcat
    tomcat-embed-core
    tomcat-embed-el
    tomcat-embed-websocket
      tomcat-embed-core
  jackson-databind
  ...

Manually managing these dependencies would be extremely time-consuming and error-prone.

Dependency Scopes

Maven defines several dependency scopes: compile, test, runtime, and provided:

ScopeDescriptionExample
compileThe jar is required for compilation (default)commons-logging
testThe jar is only required for compiling testsjunit
runtimeThe jar is not needed for compilation but is required at runtimemysql
providedThe jar is needed for compilation but is provided by the JDK or a server at runtimeservlet-api
  • compile is the most commonly used scope. Maven will add dependencies with this scope directly to the classpath.

  • test indicates that the dependency is only used during testing and is not required during normal execution. The most common test dependency is JUnit:

    xml
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.2</version>
        <scope>test</scope>
    </dependency>
  • runtime indicates that the dependency is not needed for compilation but is required at runtime. A typical runtime dependency is the JDBC driver, such as the MySQL driver:

    xml
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.48</version>
        <scope>runtime</scope>
    </dependency>
  • provided indicates that the dependency is needed for compilation but is provided by the JDK or a server at runtime. A typical provided dependency is the Servlet API, which is required during compilation but is included in the Servlet server at runtime:

    xml
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>4.0.0</version>
        <scope>provided</scope>
    </dependency>

Unique Identifier

For a dependency, Maven only needs three variables to uniquely identify a jar package:

  • groupId: The name of the organization, similar to a Java package name.
  • artifactId: The name of the jar package itself, similar to a Java class name.
  • version: The version of the jar package.

With these three variables, Maven can uniquely identify a jar package. Maven ensures that any jar package, once published, cannot be modified by using PGP signatures. The only way to modify a published jar package is to release a new version.

Therefore, once a jar package has been downloaded by Maven, it can be safely cached locally indefinitely.

Note: Only versions ending with -SNAPSHOT are treated by Maven as development versions. SNAPSHOT versions are downloaded repeatedly and should only be used in internal private Maven repositories. Publicly released versions should not include SNAPSHOT.

Tip

When referring to Maven dependencies, use the shorthand format groupId:artifactId:version, for example, org.slf4j:slf4j-api:2.0.4.

Maven Mirrors

In addition to downloading from Maven's central repository, you can also download from Maven mirror repositories. If accessing Maven's central repository is very slow, you can choose a faster Maven mirror repository. Maven mirror repositories regularly synchronize with the central repository:

           slow    ┌───────────────────┐
    ┌─────────────▶│Maven Central Repo.│
    │              └───────────────────┘
    │                        │
    │                        │sync
    │                        ▼
┌───────┐  fast    ┌───────────────────┐
│ User  │─────────▶│Maven Mirror Repo. │
└───────┘          └───────────────────┘

Users in China can use the Maven mirror repository provided by Alibaba Cloud. To use a Maven mirror repository, configure it by creating a settings.xml file in the .m2 directory in the user's home directory with the following content:

xml
<settings>
    <mirrors>
        <mirror>
            <id>aliyun</id>
            <name>aliyun</name>
            <mirrorOf>central</mirrorOf>
            <!-- Recommended Alibaba Cloud Maven mirror for domestic users -->
            <url>https://maven.aliyun.com/repository/central</url>
        </mirror>
    </mirrors>
</settings>

After configuring the mirror repository, Maven's download speed will be significantly faster.

Searching for Third-Party Components

The final question: If we want to reference a third-party component, such as OkHttp, how do we obtain its groupId, artifactId, and version? The method is to search for keywords on search.maven.org. After finding the corresponding component, simply copy the details:

Command-Line Build

In the command line, navigate to the directory containing pom.xml and enter the following command:

sh
$ mvn clean package

If everything goes well, a compiled and automatically packaged jar will be available in the target directory.

Using Maven in IDE

Almost all IDEs have built-in support for Maven. In Eclipse, you can directly create or import Maven projects. If the imported Maven project has errors, try selecting the project, right-clicking, and choosing Maven -> Update Project... to update:

Exercise

Use Maven to compile the hello project.

Summary

  • Maven determines the required jar packages for a project by resolving dependency relationships. The four commonly used scopes are: compile (default), test, runtime, and provided.
  • Maven downloads the necessary jar packages from the central repository and caches them locally.
  • You can accelerate downloads by using mirror repositories.
Dependency Management has loaded