Knowledge Transfer

Ethickfox kb page with all notes


Project maintained by ethickfox Hosted on GitHub Pages — Theme by mattgraham

Maven

Фреймворк для автоматизации сборки проектов на основе описания их структуры в файлах на языке POM,

Зависимости

В maven есть 2 типа зависимостей:

POM

Project Object Model - основной файл конфигурации в Maven. Он содержит всю необходимую для сборки проекта информацию.

Все pom файлы можно разделить на 3 типа:

Super POM

Основной файл, от которого наследуются все pom файлы(По аналогии с object в Java). Он задает дефолтные значения для таких элементов конфигурации как:

Simplest POM

Самый простой пом, который можно создать. Он должен состоять из версии мавена, groupId, artifactId, версии проекта

Effective POM

Является сочетанием дефолтных настроек из super POM и конфигурации заданной для приложения. Можно получить через mvn help:effective-pom

Жизненный цикл

BOM

BOM stands for Bill Of Materials. A BOM is a special kind of POM that is used to control the versions of a project’s dependencies and provide a central place to define and update those versions.

BOM provides the flexibility to add a dependency to our module without worrying about the version that we should depend on.

Артефакт

Результирующая программа, полученная сборкой с помощью maven. Хранится в репозитории

Репозиторий

Хранилище всех зависимостей(в порядке поиска зависимостей)

Scope

Archetype

Шаблон вашего будущего проекта или, цитируя официальную документацию: «архетип есть модель по которой делаются все остальные вещи такого рода

Dependency hell

Антипаттерн управления зависимостями на проекте, при котором усложняется граф зависимостей библиотек и возникает ситуация, когда библиотеки требуют разные версии одной и той же зависимости. Или одна библиотека может косвенно потребовать несколько версий одной и той же зависимости.

The conflict here comes when 2 dependencies refer to different versions of a specific artifact. Which one will be included by Maven?

The answer here is the “nearest definition”. This means that the version used will be the closest one to our project in the tree of dependencies. This is called dependency mediation.

Let's see the following example to clarify the dependency mediation:

A -> B -> C -> D 1.4  and  A -> E -> D 1.0

This example shows that project A depends on B and E. B and E have their own dependencies which encounter different versions of the D artifact. Artifact D 1.0 will be used in the build of A project because the path through E is shorter.

There are different techniques to determine which version of the artifacts should be included:

Как исправить?

DependencyManagement

Simply put, Dependency Management is a mechanism to centralize the dependency information.

When we have a set of projects that inherit a common parent, we can put all dependency information in a shared POM file called BOM.

<project ...>
	
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Baeldung-BOM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>BaelDung-BOM</name>
    <description>parent pom</description>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>test</groupId>
                <artifactId>a</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>test</groupId>
                <artifactId>b</artifactId>
                <version>1.0</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>test</groupId>
                <artifactId>c</artifactId>
                <version>1.0</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

As we can see, the BOM is a normal POM file with a dependencyManagement section where we can include all an artifact's information and versions.

There are 2 ways to use the previous BOM file in our project and then we will be ready to declare our dependencies without having to worry about version numbers.

We can inherit from the parent:

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    <parent>
        <groupId>baeldung</groupId>
        <artifactId>Baeldung-BOM</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
</project>

We can also import the BOM.

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>baeldung</groupId>
                <artifactId>Baeldung-BOM</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

The order of precedence of the artifact's version is:

  1. The version of the artifact's direct declaration in our project pom
  2. The version of the artifact in the parent project
  3. The version in the imported pom, taking into consideration the order of importing files
  4. dependency mediation

Dependency vs DependencyManagement