In the process of sorting out the project, I found that many developers were not familiar with the configuration of Maven dependency files, especially the use of Maven optional elements and scope elements. This results in publishing jars or war packages that are “fat,” slow to compile, and prone to jar collisions. This article starts with optional and scope usage scenarios to achieve a wave of project slimming.

Optional elements

For example, the hot deployment component Spring-boot-devtools that we often use in the project can be defined with the optional element. The corresponding POM file is configured as follows:

<! <dependency> <groupId>org.springframework.boot</groupId> <artifactId> Spring-boot-devtools </artifactId>  <optional>true</optional> </dependency>Copy the code

So what does it mean to set the optional element to true? Optional is an option when Maven relies on jars, indicating that the dependency is optional and not passed between projects. Optional is not set (default) or optional is false to pass dependencies.

The text description may be abstract, but A concrete example scenario is used for A more intuitive description. Assume that there are two projects A and B, where A is the parent project and B is the child project. Unit test dependencies are introduced in the parent project:

<dependency> <groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>Copy the code

Here’s a look at the different values of the optional element.

Optional element default (false)

When the parent project adds the junit dependency, the optional option is not added, so the default optional element is false.

At this point, when the child project depends on the parent project, the relationship between the parent project A and the child project B is as follows:

The parent project does not set the optional element to true, so it is dependent-transitive. At this point, the Junit JAR package introduced in parent project A is directly imported into child project B. This means that when the B project is packaged, the JAR/WAR package contains junit’s JAR package.

The optional element is true

Set the optional element to true when the parent project introduces junit dependencies. Subproject B then has more options.

If project B does not need the Junit JAR package, then no processing is required in its POM files. If project B also requires A jar dependency, there are two options: 1. Set the optional dependency in project A to false or remove it. Second, project B directly introduces the required dependency.

Parent inheritance

We often configure uniform dependent versioning in parent projects as follows:

<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <optional>true</optional> </dependency> </dependencies> </dependencies>Copy the code

If the project B needs the Junit JAR package, it can be imported directly into the project. The optional configuration in the parent project has no effect on the child project.

In Maven projects, the proper use of optional configuration can significantly reduce jar size and speed up compilation and publishing.

The scope elements

Now that we’re done with the optional element, let’s look at scope.

The scope element is primarily used to control the scope of dependencies, specifying the scope and transitivity of dependencies for the current package, which dependencies are available in which classpath. Common optional values are compile, provided, Runtime, test, system, and so on.

Compile

The default value. Compile indicates that the corresponding dependency will participate in the compilation, testing, and running of the current project, which is a relatively strong dependency. This dependency is usually included when packaged and packaged into the lib directory when deployed. For example, spring-core is the core JAR package.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Copy the code

Test (n.)

Scope as test indicates that dependent projects only participate in the test process and will not be used during compilation, running, and packaging. The most common use is the unit test class:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
Copy the code

Dependencies such as unit tests, if not set to scope test, will obviously be packaged and published, but will have no effect in the real environment.

Runntime (runtime)

Runntime is only for run and test purposes and will not be used in a build environment. For example, only the JAR of the JDBC API is required at compile time, and only the JDBC driver implementation is required at run time.

< the dependency > < groupId > mysql < / groupId > < artifactId > mysql connector - Java < / artifactId > < version > 8.0.20 < / version > <scope>runtime</scope> </dependency>Copy the code

Provided (= provided)

Provided is suitable for compilation and testing environments and is similar to compile, but provide only works during compilation and testing. Provide is not packaged and is not transitive.

For example, spring-boot-Devtools and servlet-API mentioned above do not need to be hot deployed in production, while the latter is provided by the container and does not need to be introduced repeatedly.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <scope>provided</scope>
</dependency>
Copy the code

system

System scoped dependencies are similar to provided, except that the dependencies are not fetched from the Maven repository and need to be supplied from the local file system. Be sure to use it with the systemPath attribute. It is not recommended. Try to reference dependencies from Maven libraries.

<dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>1.5.0</version> <scope>system</scope> <systemPath>${java.home}/.. /lib/tools.jar</systemPath> </dependency>Copy the code

Transitivity of scope dependencies

The different parameter values of scope are explained above. For these parameter values, the dependency transitivity in multiple projects is as follows:

Where B depends on A and C depends on B. The key to transitivity is the scope value set when B depends on A. When B uses different values, the corresponding dependency relationship is as follows: When B depends on A through test or provided, C does not depend on A. When B depends on A via runtime or compile, C depends on A;

summary

With Maven’s Optional and Scope elements outlined above, you should be able to check the configuration of your projects to make sure that you are using project-to-project dependencies accurately, rather than introducing large dependency files for each project, resulting in bloated projects, slow compilations, and conflicts.

Do you understand the optional and scope elements used in Maven?


Program new horizon

\

The public account “program new vision”, a platform for simultaneous improvement of soft power and hard technology, provides massive information

\