To give some of your own understanding of Maven’s aggregation and inheritance features, this article will separate out the general overview of Maven’s aggregation and inheritance features previously written

Feature relationship

First, it is important to point out that aggregation and inheritance under multi-module projects are two different concepts with completely different purposes. Aggregation is primarily to facilitate quick build projects, and inheritance is primarily to eliminate duplication of configuration. This means that projects can use aggregation, inheritance separately, or both.

For an aggregate POM, it needs to know which modules are aggregated, but those of the aggregated modules are not aware of the existence of the aggregate POM. Here is an example of an aggregated POM:

<project xmlns="...">
    <modelVersion>4.0.0</modelVersion>
    <groupId>xxx</groupId>
    <artifactId>xxx</artifactId>
    <packaging>pom</packaging>
    <name>xxx</name>
    <version>xxx</version>

    <modules>
        <module>a-module</module>
        <module>b-module</module>
        <module>c-module</module>
    </modules>
</project>
Copy the code

For an inherited POM, it does not know which submodules inherit from it, but those submodules must be aware of the existence of their parent POM. Here is an example of a submodule POM:

<project xmlns="...">
    <parent>
        <groupId>com.fingard.rh.rhf</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0 - the SNAPSHOT</version>
    </parent>

    <artifactId>xxx</artifactId>
    <name>xxx</name>
    <packaging>war</packaging>
</project>
Copy the code

In addition to these differences, the two have a few things in common, such as packing must be POM, and there is no actual content in the project folder other than POM.xml. Here’s what each of these features entails.

The aggregation

When there are multiple modules in a project and you need to build, without aggregation, you can only do the packaging command under each module. Otherwise, if there are dependencies between modules, you can only do the packaging in feature order.

Fortunately, Maven provides an aggregation feature that not only allows you to build an entire project in one click, but also automatically calculates dependencies between modules (build which first, reactor build order) at build time. It’s easy to use, just create a separate aggregation module, and build that module to build all the modules for the entire project.

<project xmlns="...">
    <modelVersion>4.0.0</modelVersion>
    <groupId>xxx</groupId>
    <artifactId>xxx</artifactId>
    <packaging>pom</packaging>
    <name>xxx</name>
    <version>xxx</version>

    <modules>
        <module>a-module</module>
        <module>b-module</module>
    </modules>
</project>
Copy the code

Add modules list elements whose values are the path of each module in the project relative to the current POM (note: the value is name, not artifactId). In the example above, an aggregation module is parent-child to the directory structures of other modules.

Root directory: aggregate modules folder | - a - module | b - module | pom aggregation module. The XMLCopy the code

It can also be parallel to other modules, as follows

Root directory: project name | -- - | aggregation module - a - module | b - the moduleCopy the code

The AGGREGATION module’s POM also needs to be modified accordingly

<modules>
    <module>../a-module</module>
    <module>../b-module</module>
</modules>
Copy the code

For simplicity and ease of building, aggregation modules are usually placed at the top of the directory, and other modules exist as subdirectories of aggregation modules.

inheritance

If there is a scenario where a-Module and B-Module are not interdependent and depend on Spring-Core at the same time, you must add the dependency coordinates to their respective POM. If you want to upgrade the dependency version number in the future, you must change the two projects. If either of them forgets to upgrade, It can also lead to unexpected bugs.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.1.5. RELEASE</version>
</dependency>
Copy the code

To solve this problem and eliminate duplication of configuration, inheritance features can be introduced. As with aggregation, a single Maven module needs to be created to act as a parent module for the entire project, placing other modules under its directory.

Root directory: the parent module folder | - a - module | b - module | pom. The parent module XMLCopy the code

Also, the parent module is packaged in the same way as the aggregation is poM, and must be.

<project xmlns="...">
    <modelVersion>4.0.0</modelVersion>
    <groupId>xxx</groupId>
    <artifactId>xxx</artifactId>
    <version>xxx</version>
    <packaging>pom</packaging>
    <name>xxx-parent</name>

    <dependencies>.</dependencies>

    <buid>
        <plugins>.</plugins>
    </build>
</project>
Copy the code

Now how does the a-module inherit from the parent

<project xmlns="...">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>xxx</groupId>
        <artifactId>xxx</artifactId>
        <version>xxx</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>a-module</artifactId>
    <name>a-module</name>
</project>
Copy the code

Note that the parent>relativePath tag defaults to.. /pom.xml, where the child project is located under the parent project folder, can be omitted if the file structure is the same as described above.

The

and

tags can be omitted if they are omitted from the parent POM, but the

tag cannot be omitted. If they are inherited, the coordinates will be confused. In addition to the inheritable elements mentioned above, the elements listed below are inheritable


> groupId, project ID; > version, project version; > description, project description information; > Organazation, organization information for the project; > inceptionYear, the project's founding year; > developers; > Ficolin-3, contributor information for projects; > distributionManagement, deployment information for the project; > issueManagement, defect tracking system information of the project Cima Management, continuous integration system information for the project; > SCM, version control system information for the project; > mailingLists, the mailing list information of the project; > properties, custom Maven properties; > < span style = "box-sizing: border-box; > dependencyManagement, project dependencyManagement configuration > Repositories, project repository configuration; Build, including project source directory configuration, output directory configuration, plug-in configuration, plug-in management configuration, etc. > Reporting, including report output directory configuration for the project, report plug-in configuration.Copy the code

Using these inheritable elements, you can do some unified management in the parent module, such as dependency management, plug-in management. For example, solving the uniform dependencies of the Spring-core package in the first place.

Declare tri-party dependencies for unified management in the parent POM

TAB

<! Pom - father -- -- >
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.5. RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>
Copy the code

The submodule that inherits the POM does not depend on Spring-Core, but needs to re-declare the dependency in the child POM (equivalent to overwriting the superclass method in Java).

<project xmlns="...">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>xxx</groupId>.</parent>

    <artifactId>a-module</artifactId>
    <name>a-module</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
    </dependencies>
</project>
Copy the code

As you can see, although the dependency is declared again in the child POM, unlike usual, the

version number is not added, which means the version number declared in the parent POM is used. Similarly, other modules that inherit from the parent POM can declare dependencies in this way. This way, when common dependencies need to be upgraded, all child modules can be upgraded by simply changing the version number in the parent POM.

But again, you might ask, what if I don’t want to duplicate the statement twice about these co-dependencies? Do all right! See

for other tags that support inheritance. Add a

tag to the

tag, and all submodules that inherit from the poM automatically inherit the dependencies.


<! Pom - father -- -- >
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.1.5. RELEASE</version>
    </dependency>
</dependencies>
Copy the code

In addition to the two tags mentioned above, the

tag can also be inherited. Here is an example declaring a resource packaging plug-in with some filtering parameters. When the submodule inherits the POM, it is also configured with the plug-in.

<! Pom - father -- -- >
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <encoding>UTF-8</encoding>
                <! Maven files with the suffix pem and PFX will be compiled and cannot be loaded.
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>key</nonFilteredFileExtension>
                    <nonFilteredFileExtension>cer</nonFilteredFileExtension>
                    <nonFilteredFileExtension>pem</nonFilteredFileExtension>
                    <nonFilteredFileExtension>pfx</nonFilteredFileExtension>
                    <nonFilteredFileExtension>p12</nonFilteredFileExtension>
                    <nonFilteredFileExtension>truststore</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>
    </plugins>
</build>
Copy the code

summary

In enterprise development, two features are typically applied in a SINGLE POM, where the root poM is both an aggregation module and a parent module.

As an aggregation module, when packaged, the entire project can be built with just one maven command in the poM of the root directory, while keeping the project structure intuitive.

As the parent module of a Common package such as JUint and Apache Common, declare it in the parent POM

. Also, all packages are declared in

. If submodules need to rely on this package, the package will be overwritten. Also, some common plug-ins can and should be declared in the parent POM.

In general, the two features are not hard to understand, and are somewhat similar to the design patterns used to write code. Aggregation applies the idea of unified scheduling, and inheritance applies the idea of reuse.

reference

  • Maven in Action