scope

scope is used to confine the scope of dependencies. It affects the state of maven project importing different packages under different stages of lifecycle.

There’re 6 kinds of scope: compile, provided, runtime, test, system, import.

  1. compile: default scope; scope towards project compile, test, runtime. A profound dependency. Usually included when packaging.
  2. provided: This scope assumes the dependency would be provided by the JDK or containers of this application, e.g. servletAPI:
    1
    2
    3
    4
    5
    6
    <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.1</version>
    <scope>provided</scope>
    </dependency>

This dependency can affect compile, test, runtime lifecycle, but not packaged in final artifact.

  1. runtime: scope only in test and runtime; skipped compile. E.g. JDBC driver. It’s for runtime and test phases. Say there’s a web app that would need to access MySQL database in runtime. Code is based only on JDBC API, i.e. only JDBC API Jar is needed in compile time, and JDBC driver is needed only in runtime.
  2. test: scope only in testing. e.g. JUnit. This dependency would not be packaged in final artifact.
    1
    2
    3
    4
    5
    6
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
    </dependency>

execution has to be defined under test scope.

  1. system: ~ provided scope. Different: you should tell maven how to find this dependency by specifying systemPath property. It’s purely based on local machine system. If you’re going to use a dependency that is not in maven repository, you can use this scope. Since systemPath would vary on different machines, systemPath is poorly transplantable. It’s not recommended.

    1
    2
    3
    4
    5
    6
    7
    <dependency>
      <groupId>javax.sql</groupId>
      <artifactId>jdbc-stdext</artifactId>
      <version>2.0</version>
      <scope>system</scope>
      <systemPath>${java.home}/lib/rt.jar</systemPath>
    </dependency>
  2. import: import dependency config from other pom.xml. It’s used only under <dependencyManagement>.

transitive dependencies

e.g.

1
maven-01 --> spring-test --> spring-core

then maven-01 transitively depend on spring-core.

Transitive dependency would automatically download transitive dependencies to rid further jar dependencies problems. But it could cause dependency conflicts, e.g. different version dependencies.

exclusions

exclusion under exclusions is a way to rid dependency conflicts, reducing unnecessary transitive dependencies. e.g.

1
2
3
project --> ehcache --> (exclusion ❌) slf4j-api-1.2
|
----> slf4j-api-1.2

conflicts

Transitive dependency property would implicitly cause many jar dependencies version conflicts.

To solve this problem, read pom.xml explicit and implicit dependency jar files. Find undesired dependencies and delete them.

2 Rules in conflicts:

  1. shortest path
  2. first declarence

Shortest path:

1
2
3
maven-01 -> spring-test -> spring-core -> commons-loggings-1.2 (d:3)

maven-01 -> maven-02 -> commons-loggings-1.1.1 (d:2) ✅

first declarence

1
2
3
4
5
maven-01->spring-test->spring-core

maven-01->maven-02->commons-logging-1.1.1 ✅

maven-01->maven-03->commons-logging-1.1.3