Java for Beginner
695 subscribers
603 photos
165 videos
12 files
937 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Встроенные плагины

Maven поставляется с набором встроенных плагинов, которые покрывают основные задачи сборки. Они определены в "super POM" — базовом POM-файле, который наследуется всеми проектами.

Рассмотрим ключевые встроенные плагины:

maven-compiler-plugin: Отвечает за компиляцию исходного и тестового кода. Цели:
compile: Компилирует исходный код в target/classes.
testCompile: Компилирует тестовый код в target/test-classes. В памяти плагин загружает исходные файлы, зависимости и настройки компилятора, создавая временные структуры данных для байт-кода.
maven-surefire-plugin: Выполняет модульные тесты. Основная цель:
test: Запускает тесты с использованием фреймворков, таких как JUnit или TestNG, и сохраняет результаты в target/surefire-reports. Плагин создает изолированную среду выполнения тестов, что требует дополнительной памяти для загрузки тестовых классов и их зависимостей.
maven-jar-plugin: Создает JAR-артефакты. Основная цель:
jar: Пакует скомпилированный код и ресурсы в JAR-файл в target. Плагин работает с файловой системой, минимизируя использование памяти, так как данные записываются непосредственно на диск.
maven-install-plugin: Устанавливает артефакты в локальный репозиторий. Цель:
install: Копирует артефакт в ~/.m2/repository. Плагин использует минимальный объем памяти, так как выполняет операции копирования файлов.
maven-deploy-plugin: Разворачивает артефакты в удаленный репозиторий. Цель:
deploy: Загружает артефакт в указанный репозиторий (например, Nexus или Artifactory). Плагин взаимодействует с сетью, что может замедлить выполнение, но не сильно нагружает память.
maven-site-plugin: Генерирует документацию проекта. Цели:
site: Создает HTML-документацию в target/site.
site-deploy: Разворачивает документацию на сервер. Плагин загружает в память шаблоны и данные проекта, что может быть ресурсоемким для крупных проектов.


Эти плагины автоматически привязаны к соответствующим фазам жизненного цикла (например, maven-compiler-plugin:compile к фазе compile), что определено в super POM. Их поведение можно переопределить или расширить в пользовательском POM-файле.


Конфигурация плагинов: <plugin>, <executions>, <configuration>


Конфигурация плагинов задается в POM-файле через элемент <plugin>.

Основные элементы конфигурации:
<plugin>: Определяет плагин, его groupId, artifactId и version.

Например:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
</plugin>


<configuration>: Задает параметры плагина, такие как версия Java или дополнительные опции.

Например:
```
<configuration>
<source>11</source>
<target>11</target>
<compilerArgs>
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>

Параметры загружаются в память как свойства объекта Mojo, что позволяет плагину адаптировать поведение.
```

<executions>: Позволяет привязать цели плагина к конкретным фазам жизненного цикла или настроить многократное выполнение цели.

Например:
<executions>
<execution>
<id>custom-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</execution>
</executions>

Каждая <execution> создает отдельный экземпляр Mojo в памяти, что может увеличить потребление ресурсов при сложных конфигурациях.


Конфигурация загружается в объектную модель POM во время инициализации проекта. Maven парсит XML, создавая структуры данных, которые хранятся в оперативной памяти. Для крупных проектов с множеством плагинов это может привести к значительному потреблению памяти, особенно если конфигурации содержат сложные параметры или большие списки зависимостей.

#Java #middle #Maven #Plugin #Goals
👍1
Наследование и управление версиями плагинов

Maven поддерживает наследование конфигураций плагинов через родительские POM-файлы.

В многомодульных проектах родительский POM может определять общие плагины и их версии в секции <pluginManagement>:

<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>


Дочерние модули наследуют эти настройки, но могут их переопределить. Это позволяет централизованно управлять версиями плагинов, минимизируя дублирование кода. В памяти Maven хранит только одну копию конфигурации из <pluginManagement>, которая копируется в дочерние модели POM при необходимости, оптимизируя использование ресурсов.

Управление версиями также осуществляется через локальный и удаленные репозитории. Maven загружает плагины из ~/.m2/repository или скачивает их из центрального репозитория (например, Maven Central). Кэширование плагинов снижает нагрузку на сеть, но требует места на диске.


Mojo (Maven plain Old Java Object)

Mojo — это Java-класс, реализующий интерфейс org.apache.maven.plugin.Mojo. Он определяет логику выполнения цели плагина.

Основные элементы Mojo:
Аннотации: Используются для указания имени цели, привязки к фазе и параметров.

Например:
```
@Mojo(name = "custom-goal", defaultPhase = LifecyclePhase.COMPILE)
public class CustomMojo extends AbstractMojo {
@Parameter(property = "customParam", defaultValue = "value")
private String customParam;

public void execute() throws MojoExecutionException {
getLog().info("Executing custom goal with param: " + customParam);
}
}

Аннотация @Parameter позволяет связать поле класса с параметром из POM-файла.
```

Метод execute(): Содержит логику выполнения цели. Может взаимодействовать с моделью POM, файловой системой и другими ресурсами.
Логирование: Используется метод getLog() для вывода сообщений в консоль
Maven.

В памяти каждый Mojo создается как отдельный объект, связанный с конкретной целью и фазой. Plexus управляет жизненным циклом Mojo, создавая и уничтожая их по мере выполнения фаз. Это может привести к фрагментации памяти, если плагин выполняет ресурсоемкие операции, такие как обработка больших файлов.


Сторонние плагины

Сторонние плагины расширяют функциональность Maven, добавляя поддержку задач, не покрытых встроенными плагинами.

Примеры популярных сторонних плагинов:
findbugs-maven-plugin: Выполняет статический анализ кода для поиска ошибок.
maven-shade-plugin: Создает "uber-JAR", включая зависимости.
docker-
maven-plugin: Интегрирует сборку Docker-образов в процесс Maven.

Сторонние плагины добавляются в POM-файл аналогично встроенным:
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.7.3.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>


Сторонние плагины загружаются из репозиториев, указанных в POM-файле, и могут увеличивать потребление памяти, особенно если они используют дополнительные библиотеки. Например, maven-shade-plugin загружает в память все зависимости артефакта для создания uber-JAR, что может быть ресурсоемким для крупных проектов.


#Java #middle #Maven #Plugin #Goals
Создание собственного плагина

Создание собственного плагина позволяет реализовать специфические задачи сборки.

Процесс включает следующие шаги:
Создание проекта Maven: Используйте архетип maven-archetype-mojo для генерации структуры:
mvn archetype:generate -DgroupId=com.example -DartifactId=custom-maven-plugin -DarchetypeArtifactId=maven-archetype-mojo

Реализация Mojo: Создайте Java-класс, реализующий AbstractMojo.

Например:
package com.example;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

@Mojo(name = "say-hello")
public class HelloMojo extends AbstractMojo {
@Parameter(property = "message", defaultValue = "Hello, Maven!")
private String message;

public void execute() throws MojoExecutionException {
getLog().info(message);
}
}


Конфигурация plugin.xml: Файл META-INF/maven/plugin.xml генерируется автоматически и содержит метаданные о целях и параметрах.

Сборка и установка:
mvn clean install


Использование плагина: Добавьте плагин в POM-файл другого проекта:
<plugin>
<groupId>com.example</groupId>
<artifactId>custom-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>say-hello</goal>
</goals>
</execution>
</executions>
</plugin>


Создание плагина требует загрузки дополнительных зависимостей, таких как maven-plugin-api и maven-plugin-annotations, в память. Плагин компилируется как обычный Java-проект, а его цели становятся доступны для привязки к фазам жизненного цикла. Важно оптимизировать логику Mojo, чтобы минимизировать потребление памяти, особенно если плагин обрабатывает большие объемы данных.


Нюансы и внутренние механизмы

Управление памятью:
Плагины загружаются как отдельные JAR-файлы, каждый со своим классовым загрузчиком. Это изолирует зависимости, но увеличивает фрагментацию памяти.
Mojo-объекты создаются для каждой цели в рамках <execution>. Многократное выполнение цели увеличивает потребление памяти.
Для оптимизации используйте флаги JVM, такие как -Xmx, и минимизируйте количество одновременно выполняемых плагинов.


Конфликты зависимостей:
Разные плагины могут использовать разные версии одной и той же библиотеки. Maven решает это с помощью изолированных загрузчиков классов, но это может привести к увеличению памяти или ошибкам, если плагин неправильно настроен.

Кэширование:
Maven кэширует плагины и их зависимости в ~/.m2/repository, что снижает нагрузку на сеть. Однако при использовании устаревших версий плагинов могут возникнуть проблемы совместимости.

Параллельное выполнение:
В многомодульных проектах плагины могут выполняться параллельно с флагом -T. Это ускоряет сборку, но увеличивает пиковое потребление памяти из-за одновременной загрузки нескольких Mojo.

Отладка:
Для отладки плагинов используйте флаг -X или настройте логирование в Mojo через getLog(). Это помогает выявить проблемы, но увеличивает объем выводимых данных.


#Java #middle #Maven #Plugin #Goals
👍1
Управление зависимостями в Maven

Управление зависимостями — одна из ключевых возможностей Maven, которая позволяет автоматизировать загрузку, разрешение и использование библиотек в проекте. Maven обеспечивает централизованное управление зависимостями через локальный и удаленные репозитории, а также предоставляет механизмы для работы с транзитивными зависимостями, разрешения конфликтов и настройки специфичных сценариев.


Механизм разрешения зависимостей


Maven использует декларативный подход к управлению зависимостями, которые определяются в файле POM.xml в секции <dependencies>.

Каждая зависимость указывается через три ключевых атрибута:
groupId: Уникальный идентификатор организации или проекта.
artifactId: Имя артефакта.
version: Версия артефакта.


Пример:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>


Когда Maven выполняет сборку, он разрешает зависимости следующим образом:
Загрузка POM-модели: Maven парсит POM.xml, создавая объектную модель проекта (POM model) в оперативной памяти. Эта модель включает информацию о зависимостях, репозиториях и настройках.
Поиск зависимостей:
Maven сначала проверяет локальный репозиторий (~/.m2/repository). Если зависимость отсутствует, он обращается к удаленным репозиториям, указанным в <repositories> или унаследованным из super POM (по умолчанию Maven Central).
Загрузка артефактов:
Maven скачивает JAR-файлы и их POM-файлы, сохраняя их в локальном репозитории. В памяти создаются структуры данных, представляющие зависимости, включая их метаданные (groupId, artifactId, version).
Разрешение транзитивных зависимостей:
Maven анализирует POM-файлы загруженных зависимостей, чтобы определить их собственные зависимости (см. ниже).

В памяти Maven хранит граф зависимостей — направленный ациклический граф (DAG), где узлы представляют зависимости, а ребра — их взаимосвязи. Этот граф используется для определения порядка загрузки и разрешения конфликтов. Размер графа зависит от количества зависимостей и их транзитивных связей, что может значительно увеличивать потребление памяти в крупных проектах.


Транзитивные зависимости

Транзитивные зависимости — это зависимости, которые требуются другим зависимостям. Например, если проект зависит от spring-core, а spring-core требует commons-logging, то commons-logging становится транзитивной зависимостью.


Maven автоматически включает транзитивные зависимости в сборку, что упрощает управление, но может привести к конфликтам или ненужным библиотекам.

Процесс разрешения транзитивных зависимостей:
Maven загружает POM-файл каждой зависимости и рекурсивно анализирует их <dependencies>.
Все найденные зависимости добавляются в граф зависимостей, который хранится в памяти.
Maven применяет правила разрешения конфликтов (см. ниже) для выбора подходящих версий.

Транзитивные зависимости увеличивают объем данных в памяти, так как Maven должен загрузить и обработать все связанные POM-файлы. Для оптимизации Maven кэширует зависимости в локальном репозитории, но при первом разрешении или при использовании флага --update-snapshots может происходить интенсивная сетевая активность.


Dependency Mediation и Nearest-Wins Strategy

Когда разные зависимости требуют одну и ту же библиотеку, но с разными версиями, возникает конфликт.

Maven использует стратегию dependency mediation с правилом nearest-wins (ближайший побеждает):
Nearest-wins strategy: Maven выбирает версию зависимости, которая находится ближе к корню графа зависимостей (т.е. имеет меньшую глубину в цепочке транзитивных зависимостей).
Пример: Если проект напрямую зависит от commons-logging:1.2, а другая зависимость требует commons-logging:1.1, то
Maven выберет 1.2, так как она указана в корневом POM-файле (глубина 1). Если обе версии находятся на одинаковой глубине, Maven выберет ту, что встретилась первой в порядке парсинга.

#Java #middle #Maven #Dependencies
👍3
В памяти Maven строит граф зависимостей, где каждая версионная коллизия разрешается путем выбора ближайшей версии. Это требует хранения временных структур данных для сравнения версий, что может быть ресурсоемким для проектов с большим количеством зависимостей.

Для явного контроля версий можно использовать секцию <dependencyManagement> в POM-файле:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>


Зависимости, указанные в <dependencyManagement>, имеют приоритет над транзитивными, что позволяет избежать конфликтов. Эти данные загружаются в память как часть POM-модели и применяются во время разрешения графа.


Dependency Convergence

Dependency convergence — это концепция, которая требует, чтобы в графе зависимостей использовалась только одна версия каждой библиотеки. Нарушение конвергенции (например, использование двух версий одной библиотеки) может привести к ошибкам, таким как ClassNotFoundException или несовместимость API.


Для обеспечения конвергенции используется плагин maven-enforcer-plugin с правилом dependencyConvergence:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
</execution>
</executions>
</plugin>


Если плагин обнаруживает конфликт версий, сборка завершается с ошибкой. В памяти maven-enforcer-plugin загружает полный граф зависимостей для анализа, что может значительно увеличить потребление ресурсов в крупных проектах.


Optional Dependencies

Опциональные зависимости (<optional>true</optional>) — это зависимости, которые не включаются в транзитивный граф проектов, использующих данный артефакт. Они полезны, когда библиотека предоставляет дополнительные функции, которые не требуются всем потребителям.


Пример:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<optional>true</optional>
</dependency>


Если проект A включает slf4j-api как опциональную зависимость, то проект B, зависящий от A, не унаследует slf4j-api, пока не объявит его явно. Это уменьшает размер графа зависимостей, снижая потребление памяти и вероятность конфликтов.

В памяти Maven отмечает опциональные зависимости в POM-модели, исключая их из транзитивного разрешения, что оптимизирует обработку графа.


BOM (Bill of Materials)

BOM-файл — это специальный POM-файл, который определяет версии зависимостей для согласованного управления ими в проекте или группе проектов. BOM используется через <dependencyManagement> с областью видимости (scope) import.

Пример использования BOM от Spring Boot:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.18</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>


BOM-файл загружается в память как часть POM-модели и предоставляет централизованный список версий, которые применяются ко всем зависимостям в проекте. Это упрощает управление версиями и обеспечивает согласованность, особенно в многомодульных проектах. В памяти BOM увеличивает объем данных, так как Maven должен загрузить и обработать дополнительный POM-файл.

#Java #middle #Maven #Dependencies
👍3
Использование import scope

Область видимости import используется исключительно в <dependencyManagement> для импорта BOM-файлов. Она позволяет включить конфигурацию зависимостей из внешнего POM-файла, не добавляя сам артефакт в сборку.

Пример:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>custom-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>


В памяти
Maven загружает импортированный POM-файл как часть модели проекта, добавляя его зависимости в структуру <dependencyManagement>. Это увеличивает потребление памяти, но упрощает управление версиями, так как все модули проекта используют единый набор версий.


Dependency Tree (mvn dependency:tree) и анализ конфликтов

Плагин maven-dependency-plugin с целью tree позволяет визуализировать граф зависимостей:
mvn dependency:tree


Пример вывода:
[INFO] com.example:my-project:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:5.3.20:compile
[INFO] | \- commons-logging:commons-logging:jar:1.2:compile
[INFO] \- org.junit.jupiter:junit-jupiter:jar:5.9.2:test


Команда dependency:tree загружает в память полный граф зависимостей, включая транзитивные зависимости, и выводит его в консоль. Это полезно для анализа конфликтов и выявления нежелательных зависимостей. Для более детального анализа можно использовать флаг -Dverbose для отображения исключенных или конфликтующих версий.


Для разрешения конфликтов можно:
Исключить зависимости:
```
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

Исключения уменьшают размер графа зависимостей, снижая потребление памяти.
Явно указать версию в <dependencyManagement> для принудительного выбора версии.

```

Использовать dependency:analyze для выявления неиспользуемых или необъявленных зависимостей:
mvn dependency:analyze


В памяти dependency:tree создает временные структуры для хранения графа, что может быть ресурсоемким для проектов с сотнями зависимостей. Оптимизация, такая как использование <exclusions> или BOM, помогает сократить объем данных.


Нюансы и внутренние механизмы

Управление памятью:
Граф зависимостей хранится в памяти как DAG, где каждый узел представляет артефакт, а ребра — зависимости. Размер графа пропорционален количеству зависимостей.
Maven использует Aether (библиотеку для работы с репозиториями), которая загружает метаданные зависимостей в память. Это может привести к пиковому потреблению памяти при первом разрешении.
Для оптимизации используйте флаг -o (offline) для работы с локальным кэшем или настройте JVM с помощью -Xmx.


Кэширование:
Локальный репозиторий (~/.m2/repository) кэширует JAR-файлы, POM-файлы и метаданные, что снижает сетевую нагрузку.
Maven хранит метаданные о версиях в файлах _remote.repositories, что ускоряет повторное разрешение.

Конфликты и Classpath:
Неправильное разрешение зависимостей может привести к включению двух версий одной библиотеки в classpath, вызывая ошибки вроде NoClassDefFoundError.
Используйте dependency:tree и
maven-enforcer-plugin для предотвращения таких проблем.

Параллельное разрешение:
В многомодульных проектах Maven разрешает зависимости для каждого модуля отдельно, но кэширует результаты в памяти. Параллельное выполнение (-T) увеличивает пиковое потребление памяти из-за одновременной обработки нескольких графов.

Сетевые проблемы:
Если удаленный репозиторий недоступен, Maven может завершиться с ошибкой. Настройка зеркал в settings.xml или использование --offline помогает избежать этого.


#Java #middle #Maven #Dependencies
👍4
Профили, настройки и переменные в Maven

Maven предоставляет мощные инструменты для адаптивной конфигурации проектов, включая профили, настройки в файле settings.xml и использование переменных. Эти механизмы позволяют гибко настраивать сборку в зависимости от окружения, операционной системы или пользовательских условий, а также безопасно управлять конфиденциальными данными.


Профили: структура, активация, условия

Профили в Maven позволяют определять альтернативные конфигурации сборки, которые активируются при выполнении определенных условий. Они задаются в файле POM.xml в секции <profiles> или в файле settings.xml. Профили используются для настройки зависимостей, плагинов, свойств или ресурсов в зависимости от окружения (например, разработка, тестирование, продакшен).


Структура профиля
Профиль определяется в <profile> и может включать те же элементы, что и основной POM-файл: <dependencies>, <plugins>, <properties>, <build> и т.д.

Пример:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>development</env>
</properties>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.7.1</version>
</dependency>
</dependencies>
</profile>
</profiles>


В памяти Maven загружает все профили из POM.xml и settings.xml в объектную модель проекта (POM model) во время инициализации. Активные профили объединяются с основной конфигурацией, создавая итоговую модель сборки. Это увеличивает потребление памяти, особенно если профили содержат сложные конфигурации или множество зависимостей.

Активация профилей

Профили активируются следующими способами:

Явная активация через командную строку:
mvn package -Pdev

Флаг -P указывает идентификатор профиля (id). Можно активировать несколько профилей: -Pdev,test.


Автоматическая активация по условиям:
Профили могут активироваться автоматически на основе условий, заданных в секции <activation>. Maven проверяет эти условия во время загрузки POM-файла, что требует дополнительных вычислений и памяти для оценки.


Активация по системным переменным
Профиль активируется, если указанная системная переменная (-Dkey=value) присутствует или имеет определенное значение:
<profile>
<id>prod</id>
<activation>
<property>
<name>env</name>
<value>production</value>
</property>
</activation>
</profile>


Запуск:
mvn package -Denv=production

Maven загружает системные свойства в память через System.getProperties() и сравнивает их с условиями активации. Это минимально нагружает память, так как свойства уже доступны в JVM.


Активация по операционной системе
Профиль активируется в зависимости от операционной системы, определенной через параметры os.name, os.family, os.arch или os.version:
<profile>
<id>windows</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
</profile>


Maven использует API System.getProperty("os.name") для проверки ОС, что не требует значительных ресурсов памяти, так как информация об ОС уже доступна JVM.


#Java #middle #Maven #Profiles #Settings #m2
👍3
Активация по наличию файла
Профиль активируется, если указанный файл существует (или отсутствует):
<profile>
<id>local-config</id>
<activation>
<file>
<exists>${basedir}/local-config.properties</exists>
</file>
</activation>
</profile>


Maven выполняет файловую проверку через API java.io.File, что требует минимальных ресурсов, но может замедлить инициализацию при большом количестве профилей с проверками файлов.

Другие условия
JDK: Активация по версии Java (<jdk>).
Property absence: Активация, если свойство отсутствует (<property><name>!key</name></property>).
Default activation: Профиль может быть активен по умолчанию (<activation><activeByDefault>true</activeByDefault></activation>).


В памяти
Maven хранит список всех профилей и их условия. При загрузке проекта Maven оценивает условия для каждого профиля, создавая временные объекты для хранения результатов проверки. Если профиль активируется, его конфигурация объединяется с основной POM-моделью, что может увеличить объем памяти, особенно в многомодульных проектах.


settings.xml: Локальный и глобальный

Файл settings.xml определяет глобальные или пользовательские настройки Maven, такие как репозитории, прокси, серверы и профили.

Существует два уровня settings.xml:
Глобальный: Расположен в $MAVEN_HOME/conf/settings.xml (обычно в директории установки Maven). Применяется ко всем пользователям системы.
Локальный: Расположен в ~/.m2/settings.xml. Применяется только к текущему пользователю и имеет приоритет над глобальным.


Maven загружает оба файла в память во время инициализации, создавая объектную модель настроек (Settings object). Локальный settings.xml переопределяет глобальный. Если файл отсутствует, Maven использует значения по умолчанию (например, Maven Central в качестве репозитория).


Основные элементы settings.xml
<mirrors>: Позволяет перенаправлять запросы к репозиториям на зеркала для ускорения загрузки или обхода ограничений. Пример:
<mirrors>
<mirror>
<id>central-mirror</id>
<url>https://repo.example.com/maven2</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>

Maven загружает конфигурацию зеркал в память и использует ее при разрешении зависимостей, что минимально влияет на потребление ресурсов.


<proxies>: Настраивает прокси для доступа к удаленным репозиториям. Пример:
<proxies>
<proxy>
<id>example-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy.example.com</host>
<port>8080</port>
</proxy>
</proxies>

Конфигурация прокси загружается в память как часть объекта Settings, что не требует значительных ресурсов.


<servers>: Хранит учетные данные для доступа к защищенным репозиториям. Пример:
<servers>
<server>
<id>nexus</id>
<username>user</username>
<password>pass</password>
</server>
</servers>

Maven загружает учетные данные в память, но они могут быть зашифрованы для безопасности (см. ниже).


<profiles>: Определяет профили, аналогичные профилям в POM.xml, но на уровне настроек. Они применяются ко всем проектам пользователя. Пример:
<profiles>
<profile>
<id>custom-repo</id>
<repositories>
<repository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-public/</url>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>custom-repo</activeProfile>
</activeProfiles>


В памяти Maven объединяет настройки из settings.xml с моделью POM, создавая единую конфигурацию. Это увеличивает объем памяти, особенно если settings.xml содержит множество профилей или репозиториев.


#Java #middle #Maven #Profiles #Settings #m2
👍3
Переменные

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

User-defined ${} переменные
Пользовательские переменные определяются в <properties> в POM.xml или settings.xml.
<properties>
<java.version>11</java.version>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>

Переменные загружаются в память как часть POM-модели или объекта Settings. Maven заменяет ${} на значения во время парсинга, что требует минимальных ресурсов, так как это операция на уровне строк.


Environment variables

Переменные окружения (например, JAVA_HOME, PATH) доступны через ${env.VARIABLE_NAME}.
<properties>
<java.home>${env.JAVA_HOME}</java.home>
</properties>

Maven получает переменные окружения через System.getenv(), что не нагружает память, так как данные уже доступны JVM.


System properties (-D)

Системные свойства задаются через флаг -D в командной строке:

mvn package -Denv=production


Они доступны в POM.xml через ${propertyName}.
<properties>
<env>${env}</env>
</properties>

Системные свойства загружаются в память через System.getProperties(). Они имеют приоритет над переменными из POM.xml или settings.xml.


Переменные из settings.xml и POM
settings.xml: Переменные задаются в <properties> внутри профилей или глобально. Они применяются ко всем проектам.
POM.xml: Переменные в <properties> применяются только к текущему проекту или наследуются дочерними модулями.


Maven объединяет все переменные в единую модель свойств в памяти. Порядок приоритета: системные свойства (-D) > переменные окружения > свойства из POM.xml > свойства из settings.xml. Это требует дополнительных вычислений для разрешения конфликтов имен переменных.


#Java #middle #Maven #Profiles #Settings #m2
👍3
Secure settings: хранение credentials

Для безопасного хранения учетных данных (например, паролей для репозиториев) Maven поддерживает шифрование в settings.xml.

Процесс:

Создание мастер-пароля:

mvn --encrypt-master-password


Создает зашифрованный мастер-пароль, который сохраняется в ~/.m2/settings-security.xml:

<settingsSecurity>
<master>{encryptedMasterPassword}</master>
</settingsSecurity>


Шифрование пароля сервера:

mvn --encrypt-password


Создает зашифрованный пароль для <server> в settings.xml:
<server>
<id>nexus</id>
<username>user</username>
<password>{encryptedPassword}</password>
</server>


Maven использует библиотеку Plexus Cipher для шифрования и дешифрования. Зашифрованные данные загружаются в память как строки, а дешифрование происходит во время обращения к репозиториям. Это минимально влияет на память, но требует правильной настройки settings-security.xml.


.m2 директория

Директория ~/.m2 — это локальный репозиторий и хранилище пользовательских настроек Maven.

Основные компоненты:
repository/: Хранит кэшированные зависимости, плагины и их POM-файлы. Структура: groupId/artifactId/version/. Это снижает потребность в сетевых запросах, но увеличивает использование диска.
settings.xml: Локальный файл настроек пользователя.
settings-security.xml: Хранит зашифрованный мастер-пароль.
toolchains.xml: Определяет альтернативные JDK для сборки (например, для кросс-компиляции).


Maven загружает содержимое ~/.m2/settings.xml и settings-security.xml в память при старте. Локальный репозиторий не загружается полностью, но Maven читает метаданные (POM-файлы) по мере необходимости, что оптимизирует использование памяти. Однако при большом количестве зависимостей или устаревших артефактов в ~/.m2/repository может потребоваться очистка для освобождения места на диске.
Нюансы и внутренние механизмы


Управление памятью:
Maven загружает POM.xml, settings.xml и профили в память как объектные модели (POM model и Settings). Это увеличивает потребление памяти в многомодульных проектах или при большом количестве профилей.
Активация профилей требует проверки условий, что создает временные объекты в памяти для хранения результатов.
Для оптимизации используйте минимальное количество профилей и избегайте сложных условий активации.


Конфликты переменных:

Переменные с одинаковыми именами из разных источников (системные, окружения, POM, settings.xml) могут конфликтовать. Maven разрешает их по приоритету, но это требует дополнительных вычислений.
Используйте уникальные имена для пользовательских переменных, чтобы избежать путаницы.


Безопасность:

Хранение паролей в открытом виде в settings.xml небезопасно. Всегда используйте шифрование с --encrypt-password.
Убедитесь, что settings-security.xml имеет ограниченные права доступа (например, chmod 600).


Многомодульные проекты:

Профили из родительского POM.xml наследуются дочерними модулями, но могут быть переопределены. Это увеличивает сложность объединения конфигураций в памяти.
Используйте <pluginManagement> и <dependencyManagement> для централизованного управления.


Параллельное выполнение:

При использовании флага -T
Maven загружает конфигурации для каждого модуля параллельно, что увеличивает пиковое потребление памяти из-за одновременной обработки нескольких POM-моделей и профилей.

Кэширование:

Локальный репозиторий (~/.m2/repository) кэширует зависимости, что снижает сетевые запросы, но требует периодической очистки для удаления устаревших SNAPSHOT-версий.
Maven кэширует результаты проверки условий активации профилей в рамках одной сессии, что ускоряет повторные сборки.

Отладка:

Используйте флаг -X для вывода подробной информации о загрузке профилей, переменных и настроек.
Плагин help:effective-settings показывает итоговую конфигурацию settings.xml:mvn help:effective-settings

Плагин help:effective-pom показывает объединенную модель POM с учетом активных профилей:mvn help:effective-pom


#Java #middle #Maven #Profiles #Settings #m2
👍3
Модульность и многомодульные проекты в Maven

Многомодульный проект в Maven — это проект, состоящий из нескольких подмодулей (submodules), каждый из которых является самостоятельным Maven-проектом со своим POM.xml. Все модули объединяются под общим родительским (parent) или агрегирующим (aggregator) POM.xml, который определяет общую конфигурацию и координирует сборку.

Основные характеристики:
Каждый модуль имеет собственный жизненный цикл, артефакты (JAR, WAR и т.д.) и зависимости.
Родительский POM задает общие настройки, такие как версии плагинов, зависимости и свойства.
Модули могут зависеть друг от друга, образуя граф зависимостей.
Сборка выполняется централизованно через родительский POM или выборочно для отдельных модулей.


В памяти Maven загружает модель POM для каждого модуля, создавая объединенную объектную модель проекта. Это увеличивает потребление памяти пропорционально количеству модулей, так как каждый POM.xml парсится и хранится как отдельная структура данных.


Структура: Aggregator (Parent POM) vs Parent Project

Многомодульный проект может использовать два подхода к организации: aggregator POM и parent POM. Хотя термины часто пересекаются, их роли различаются.

Aggregator POM

Агрегирующий POM — это файл, который перечисляет модули проекта в секции <modules> и координирует их сборку. Он не обязательно содержит конфигурацию, а служит для запуска сборки всех модулей.

Пример:
<project>
<groupId>com.example</groupId>
<artifactId>aggregator</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>module-api</module>
<module>module-core</module>
<module>module-web</module>
</modules>
</project>


Упаковка: <packaging>pom</packaging> указывает, что проект не создает артефакт (JAR/WAR), а только управляет модулями.
Сборка: Команда mvn package в директории aggregator вызывает сборку всех модулей в порядке, определенном реактором (см. ниже).


Parent POM

Родительский POM определяет общую конфигурацию, которая наследуется модулями. Он может быть одновременно агрегирующим POM.

Пример:
<project>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<java.version>11</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>module-api</module>
<module>module-core</module>
</modules>
</project>


Модуль наследует настройки из родительского POM:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module-api</artifactId>
</project>


Наследование: Модули наследуют <groupId>, <version>, <properties>, <dependencyManagement>, <pluginManagement> и другие настройки.
Отличие: Родительский POM может существовать отдельно от агрегирующего, например, в другом проекте. Модули ссылаются на него через <parent>, но могут не быть перечислены в <modules>.


В памяти Maven загружает родительский POM первым, создавая базовую модель, которая затем дополняется конфигурацией каждого модуля. Если родительский POM находится в удаленном репозитории, Maven загружает его из ~/.m2/repository или скачивает, что добавляет сетевые операции и временное использование памяти.

Aggregator vs Parent

Aggregator: Управляет сборкой модулей через <modules>. Не обязательно является родительским.
Parent: Определяет наследуемую конфигурацию через <parent>. Может не быть агрегирующим.
Комбинация: Часто один POM выполняет обе роли, что упрощает структуру.


#Java #middle #Maven #Profiles #Parent_POM #MultiModule #Module_Inheritance
👍3
Module Inheritance

Наследование в многомодульных проектах позволяет централизовать конфигурацию.

Модули наследуют от родительского POM:

Метаданные: <groupId>, <version> (если не переопределены в модуле).
Свойства: <properties> для общих настроек, таких как версии Java или библиотек.
Управление зависимостями: <dependencyManagement> задает версии зависимостей, которые модули могут использовать без указания версии.
Управление плагинами: <pluginManagement> определяет версии и конфигурации плагинов.
Репозитории: <repositories> и <pluginRepositories> для загрузки артефактов.


Пример наследования зависимостей:
<!-- parent POM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

<!-- module POM -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>


В памяти Maven объединяет родительскую и модульную модели POM, создавая эффективную модель (effective POM) для каждого модуля. Это требует дополнительных ресурсов, так как каждый модуль хранит свою копию модели, частично дублируя родительские данные.


Нюансы наследования

Переопределение: Модуль может переопределить унаследованные настройки, например, указав собственный <version> или <properties>.
Глубокое наследование: Если родительский POM сам наследуется от другого POM,
Maven рекурсивно загружает все родительские модели, что увеличивает потребление памяти.
Конфликты: Неправильное переопределение (например, дублирование плагинов) может вызвать ошибки. Используйте mvn help:effective-pom для анализа итоговой конфигурации.



Разделение по слоям: API, Core, Impl, Web


Многомодульные проекты часто структурируются по слоям для разделения ответственности.


Типичная структура:
API: Содержит интерфейсы, DTO и публичные контракты. Упаковка — JAR. Пример: module-api.
Core: Реализует бизнес-логику, зависящую от API. Упаковка — JAR. Пример: module-core.
Impl: Конкретные реализации, например, интеграция с базами данных. Упаковка — JAR. Пример: module-impl.
Web: Веб-приложение, зависящее от Core или Impl. Упаковка — WAR. Пример: module-web.


Пример структуры:
project-root/
├── pom.xml (parent/aggregator)
├── module-api/
│ └── pom.xml
├── module-core/
│ └── pom.xml
├── module-impl/
│ └── pom.xml
├── module-web/
│ └── pom.xml


Зависимости между модулями:
<!-- module-core POM -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<!-- module-web POM -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>


В памяти Maven строит граф зависимостей, где модули являются узлами. Реактор (см. ниже) определяет порядок сборки, чтобы гарантировать, что module-api собирается до module-core, а module-core — до module-web. Это увеличивает объем памяти, так как Maven хранит метаданные всех модулей и их взаимосвязи.


Преимущества разделения

Модульность: Упрощает тестирование и повторное использование.
Четкие границы: Снижает связанность между компонентами.
Параллельная разработка: Команды могут работать над разными модулями независимо.


Нюансы

Циклические зависимости:
Maven не допускает циклических зависимостей между модулями (например, module-api зависит от module-core, а module-core — от module-api). Это проверяется реактором, и при обнаружении цикла сборка завершается с ошибкой.
Размер графа: Большое количество модулей увеличивает сложность графа зависимостей, что требует больше памяти для хранения и обработки.



#Java #middle #Maven #Profiles #Parent_POM #MultiModule #Module_Inheritance
👍3
Best Practices

Versioning и dependencyManagement

Единая версия: Используйте одинаковую версию для всех модулей, унаследованную от родительского POM (${project.version}). Это упрощает управление и предотвращает несовместимость.
dependencyManagement: Централизуйте версии зависимостей в родительском POM:<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>
</dependencies>
</dependencyManagement>


Это снижает дублирование и обеспечивает согласованность версий.
pluginManagement: Аналогично управляйте версиями плагинов:<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>


В памяти dependencyManagement и pluginManagement хранятся как часть родительской POM-модели, минимизируя дублирование данных в модулях.


CI/CD подходы с модулями

Полная сборка: Настройте CI/CD (например, Jenkins, GitHub Actions) для выполнения полной сборки через mvn clean install в корне проекта. Это гарантирует, что все модули совместимы.
Инкрементальная сборка: Для ускорения используйте флаг --also-make (-am) или --projects (-pl) для сборки только измененных модулей (см. ниже).


Публикация артефактов: Используйте mvn deploy для загрузки артефактов в репозиторий (например, Nexus).
Настройте <distributionManagement> в родительском POM:<distributionManagement>
<repository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-releases/</url>
</repository>
</distributionManagement>


Параллельная сборка: Используйте флаг -T (например, -T 4) для параллельного выполнения модулей. Это ускоряет сборку, но увеличивает пиковое потребление памяти из-за одновременной обработки нескольких POM-моделей.


Сборка части дерева

Maven позволяет собирать отдельные модули или их поддерево с помощью опций реактора:
Выбор модуля: Собрать только указанный модуль:mvn package -pl module-web
Включение зависимостей: Собрать модуль и все его зависимости:mvn package -pl module-web -am
Исключение модулей: Пропустить модуль:mvn package -pl !module-api


В памяти Maven загружает только модели POM для выбранных модулей и их зависимостей, что снижает потребление ресурсов по сравнению с полной сборкой. Реактор определяет минимальное поддерево графа модулей для выполнения.


Работа с реактором

Реактор (Reactor) — это внутренний механизм
Maven, который управляет порядком сборки модулей в многомодульном проекте.

Реактор:
Строит граф модулей: Анализирует <modules> в агрегирующем POM и зависимости между модулями (через <dependencies>).
Определяет порядок: Выполняет топологическую сортировку графа, чтобы модули, от которых зависят другие, собирались первыми.
Координирует сборку: Запускает жизненный цикл для каждого модуля в рассчитанном порядке.


В памяти реактор хранит граф модулей как направленный ациклический граф (DAG), где узлы — модули, а ребра — зависимости. Размер графа пропорционален количеству модулей, что увеличивает потребление памяти в крупных проектах. Реактор также кэширует промежуточные артефакты в ~/.m2/repository, чтобы избежать повторной сборки неизмененных модулей.

Нюансы реактора

Циклические зависимости: Реактор обнаруживает циклы и завершает сборку с ошибкой. Используйте mvn dependency:tree для анализа.
Пропуск модулей: Флаг -pl или -am изменяет граф, который обрабатывает реактор, уменьшая объем памяти.
Ошибки: Если модуль завершает сборку с ошибкой, реактор останавливает процесс, но промежуточные артефакты сохраняются в target.


#Java #middle #Maven #Profiles #Parent_POM #MultiModule #Module_Inheritance
👍3
Жизненный цикл в многомодульных проектах

Жизненный цикл в многомодульных проектах аналогичен одномодульному, но применяется к каждому модулю индивидуально. Основные фазы (Clean, Default, Site) выполняются в порядке, определенном реактором.

Последовательность: Реактор вызывает фазы жизненного цикла (например, validate, compile, package) для каждого модуля по очереди. Например, mvn package сначала выполнит package для module-api, затем для module-core и так далее.
Параллельность: С флагом -T
Maven выполняет фазы для независимых модулей параллельно, что ускоряет сборку, но увеличивает потребление памяти из-за одновременной загрузки нескольких POM-моделей и плагинов.
Общие ресурсы: Родительский POM задает общие плагины и зависимости, которые загружаются в память один раз и используются всеми модулями, оптимизируя ресурсы.
Пропуск фаз: Флаги, такие как -DskipTests, применяются ко всем модулям, что снижает нагрузку на память.


В памяти Maven хранит модель жизненного цикла для каждого модуля, включая привязки плагинов к фазам. Для крупных проектов это может привести к значительному потреблению памяти, особенно на фазах, таких как compile или test, где загружаются исходные файлы, зависимости и результаты тестов.

Нюансы

Инкрементальная сборка: Maven использует временные метки файлов в target, чтобы пропускать неизмененные модули. Это снижает нагрузку на память и процессор.
Ошибки в модуле: Если одна фаза завершается с ошибкой в модуле,
Maven останавливает сборку, но уже созданные артефакты сохраняются.
Кэширование артефактов: Модули, установленные в ~/.m2/repository (через mvn install), не пересобираются при повторных запусках, что оптимизирует производительность.



Нюансы и внутренние механизмы

Управление памятью:
Maven загружает модель POM для каждого модуля, создавая объединенную модель проекта. Это увеличивает потребление памяти пропорционально количеству модулей.
Реактор строит граф модулей в памяти, что требует дополнительных ресурсов для хранения и сортировки.
Параллельная сборка (-T) увеличивает пиковое потребление памяти из-за одновременной обработки нескольких модулей.
Для оптимизации используйте -pl для выборочной сборки и настройте JVM с помощью -Xmx.


Кэширование:
Локальный репозиторий (~/.m2/repository) кэширует артефакты модулей, что снижает необходимость повторной сборки.
Maven использует файлы _remote.repositories для отслеживания происхождения артефактов, минимизируя сетевые запросы.

Конфликты зависимостей:
Модули могут использовать разные версии одной библиотеки, что приводит к конфликтам. Используйте <dependencyManagement> для согласованности.
Плагин
maven-enforcer-plugin с правилом dependencyConvergence помогает выявить конфликты.

Производительность:
Инкрементальная сборка и кэширование ускоряют процесс, но первый запуск или полная сборка (mvn clean) могут быть медленными.
Параллельная сборка сокращает время, но требует мощного оборудования из-за высокой нагрузки на память и процессор.


Отладка:
Используйте mvn -X для вывода подробной информации о порядке сборки и загрузке модулей.
Команда mvn dependency:tree -pl module-name помогает анализировать зависимости конкретного модуля.
Плагин help:effective-pom показывает итоговую конфигурацию модуля с учетом наследования.


CI/CD интеграция:
Настройте CI/CD для выполнения mvn clean install на каждое изменение, чтобы гарантировать целостность всех модулей.
Используйте матричные сборки для тестирования модулей в разных окружениях (например, разные версии Java).
Храните SNAPSHOT-версии в репозитории (например, Nexus) для промежуточных сборок, а релизные версии — в отдельном репозитории.


#Java #middle #Maven #Profiles #Parent_POM #MultiModule #Module_Inheritance
👍3
Расширенные темы и интеграции Maven

CI/CD интеграция

Maven широко используется в CI/CD-пайплайнах для автоматизации сборки, тестирования и развертывания. Рассмотрим интеграцию с популярными системами и связанные процессы, такие как GPG-подпись и развертывание артефактов.

Jenkins, GitLab CI, GitHub Actions с Maven

Jenkins:

Конфигурация: Создайте задачу (Job) типа "Freestyle" или "Pipeline". В Freestyle добавьте шаг "Invoke top-level Maven targets":mvn clean install

В Pipeline используйте Jenkinsfile:
pipeline {
agent any
tools {
maven 'Maven 3.8.6'
jdk 'JDK11'
}
stages {
stage('Build') {
steps {
sh 'mvn clean install'
}
}
}
}


Параллельность: Используйте флаг -T для параллельной сборки модулей, например, -T 4.
Плагины: Используйте
maven-release-plugin для автоматизации релизов:mvn release:prepare release:perform

GitLab CI:

Конфигурация: Определите .gitlab-ci.yml:

stages:
- build
build:
stage: build
image: maven:3.8.6-openjdk-11
script:
- mvn clean install
artifacts:
paths:
- target/*.jar


Кэширование: Кэшируйте ~/.m2/repository для ускорения:
cache:
paths:
- ~/.m2/repository


GitHub Actions:

Конфигурация: Создайте .github/workflows/maven.yml:name:
Maven Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean install
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}


Артефакты: Используйте действие actions/upload-artifact для сохранения JAR/WAR.

В памяти: CI/CD-системы запускают Maven как Java-процесс, загружая POM-модель, зависимости и плагины в оперативную память. Параллельная сборка (-T) увеличивает пиковое потребление памяти, так как одновременно обрабатываются несколько модулей. Кэширование ~/.m2/repository снижает сетевые запросы, но требует места на диске.


Работа с GPG Signing, Artifact Deployment

GPG Signing:GPG-подпись артефактов необходима для публикации в Maven Central. Используется maven-gpg-plugin.

Настройка в POM.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>


Шаги:
Установите GPG и создайте ключ: gpg --gen-key.
Опубликуйте публичный ключ: gpg --keyserver
keyserver.ubuntu.com --send-keys <key-id>.

Настройте ~/.m2/settings.xml с GPG-паролем:
<server>
<id>gpg.passphrase</id>
<passphrase>{encrypted-passphrase}</passphrase>
</server>


Подпишите артефакты:
mvn clean deploy -Dgpg.passphrase=<passphrase>.


В памяти: Плагин maven-gpg-plugin загружает GPG-ключи и артефакты в память для подписи, что увеличивает потребление ресурсов, особенно для крупных JAR/WAR.

Artifact Deployment:Развертывание артефактов в репозиторий (например, Nexus, Maven Central) выполняется через maven-deploy-plugin:
<distributionManagement>
<repository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>


Запуск: mvn deploy.
SNAPSHOT vs Release: SNAPSHOT-версии (1.0.0-SNAPSHOT) обновляются в репозитории, релизные версии (1.0.0) публикуются однократно.
В памяти: Плагин maven-deploy-plugin загружает артефакт и его метаданные в память перед отправкой в репозиторий. Сетевые операции могут замедлить процесс, но потребление памяти минимально.

#Java #middle #Maven #Best_practics
👍1
Archetypes

Архетипы — это шаблоны проектов, которые позволяют быстро создавать структуру с предопределенными файлами, зависимостями и конфигурацией. Maven предоставляет встроенные архетипы, такие как maven-archetype-quickstart.

Использование:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

Пользователь вводит groupId, artifactId, version, и Maven генерирует проект.


Создание собственного архетипа

Создайте проект с желаемой структурой:
my-archetype/
├── src/
│ └── main/
│ └── resources/
│ ├── archetype-resources/
│ │ ├── src/main/java/App.java
│ │ └── pom.xml
│ └── META-INF/maven/
│ └── archetype-metadata.xml
└── pom.xml


В archetype-metadata.xml опишите структуру:
<archetype-descriptor>
<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>


Сгенерируйте архетип:
mvn archetype:create-from-project

Результат появится в target/generated-sources/archetype.


Установите архетип:
cd target/generated-sources/archetype
mvn install


Используйте архетип:
mvn archetype:generate -DarchetypeGroupId=com.example -DarchetypeArtifactId=my-archetype -DarchetypeVersion=1.0


В памяти: Архетипы загружают шаблонные файлы и их метаданные в память. Плагин maven-archetype-plugin парсит archetype-metadata.xml и заменяет переменные (например, ${groupId}), что требует минимальных ресурсов, но может быть затратным для сложных архетипов с большим количеством файлов.


Использование Maven Wrapper (mvnw)

Maven Wrapper (mvnw) — это скрипт, который обеспечивает использование конкретной версии Maven, независимо от установленной на машине. Он включает файлы mvnw (или mvnw.cmd для Windows), .mvn/wrapper/maven-wrapper.jar и .mvn/wrapper/maven-wrapper.properties.

Установка:
mvn -N wrapper:wrapper -Dmaven=3.8.6

Создает mvnw, который загружает указанную версию Maven.


Использование:
./mvnw clean install

Скрипт проверяет .mvn/wrapper/maven-wrapper.properties, загружает нужную версию Maven и выполняет команду.


В памяти: mvnw запускает Maven как отдельный Java-процесс, загружая maven-wrapper.jar в память. Это добавляет небольшой overhead, но гарантирует согласованность сборки. Кэширование Maven в .m2/repository минимизирует сетевые запросы.

Нюансы:
Храните mvnw и .mvn в репозитории для обеспечения воспроизводимости.
Обновляйте версию
Maven в maven-wrapper.properties для поддержки новых функций.


Поддержка Java версий

Maven поддерживает проекты с разными версиями Java через maven-compiler-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>



Многомодульные проекты

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

Toolchains: Для кросс-компиляции используйте ~/.m2/toolchains.xml:
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>11</version>
</provides>
<configuration>
<jdkHome>/path/to/jdk11</jdkHome>
</configuration>
</toolchain>
</toolchains>


Укажите toolchain в POM.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>toolchain</goal>
</goals>
</execution>
</executions>
<configuration>
<toolchains>
<jdk>
<version>11</version>
</jdk>
</toolchains>
</configuration>
</plugin>


#Java #middle #Maven #Best_practics
👍2
Расширение Maven

Extensions

Расширения Maven — это JAR-файлы, которые добавляют функциональность, например, кастомные жизненные циклы или обработчики репозиториев.

Они указываются в .mvn/extensions.xml:
<extensions>
<extension>
<groupId>com.example</groupId>
<artifactId>custom-extension</artifactId>
<version>1.0</version>
</extension>
</extensions>


Создание:

Создайте проект с зависимостью maven-core.
Реализуйте интерфейс, например, org.apache.
maven.AbstractMavenLifecycleParticipant.
Упакуйте как JAR и установите в репозиторий.


В памяти: Расширения загружаются через Plexus, увеличивая потребление памяти из-за дополнительных классов и их зависимостей.


Интернальные API Maven

Maven предоставляет API (maven-core, maven-plugin-api) для создания плагинов и расширений.

Пример использования org.apache.maven.project.MavenProject для доступа к модели проекта:
@Mojo(name = "custom")
public class CustomMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}")
private MavenProject project;

public void execute() throws MojoExecutionException {
getLog().info("Project artifact: " + project.getArtifactId());
}
}


В памяти: Интернальные API загружают объекты POM-модели и контекста сборки, что может быть ресурсоемким для сложных операций, таких как анализ зависимостей.

Логирование и отладка:
 -X, -e


Флаг -X: Включает отладочный режим, выводя подробную информацию о сборке, плагинах, зависимостях и реакторе:
mvn package -X

Увеличивает объем логов, что может замедлить выполнение и потребовать больше памяти для буферизации вывода.


Флаг -e: Выводит стек вызовов при ошибках:
mvn package -e

Полезно для диагностики, минимально влияет на память.


Плагины для отладки:
mvn help:effective-pom: Показывает итоговую модель POM.
mvn dependency:tree: Анализирует зависимости.
mvn help:effective-settings: Показывает настройки settings.xml.


В памяти: Отладочные флаги создают дополнительные структуры данных для логов, увеличивая временное потребление памяти.


Сравнение и миграция с Ant/Gradle

Ant

Сравнение:
Ant: Императивный подход, где задачи определяются вручную в XML (build.xml). Нет встроенного управления зависимостями или жизненного цикла.
Maven: Декларативный подход с жизненным циклом и автоматическим разрешением зависимостей.

Миграция:
Перенесите задачи Ant в плагины Maven (например, maven-antrun-plugin для запуска Ant-скриптов).
Преобразуйте зависимости в POM.xml с помощью <dependency>.
Используйте mvn ant:ant для генерации build.xml из
Maven для обратной совместимости.


Gradle

Сравнение:
Gradle: Гибридный подход (декларативный + императивный), использует Groovy/Kotlin DSL. Более гибкий, но сложнее в освоении.
Maven: Стандартизированный XML, проще для новичков, но менее гибкий.
Gradle быстрее благодаря инкрементальной сборке и кэшированию.


Миграция:
Используйте build.gradle с плагином maven-publish для публикации артефактов в Maven-репозитории.
Конвертируйте POM.xml в build.gradle с помощью инструментов, таких как gradle init.
Перенесите зависимости из <dependencyManagement> в dependencies Gradle.


В памяти: Ant использует меньше памяти из-за отсутствия сложных моделей, но требует больше ручной работы. Gradle может потреблять больше памяти из-за Groovy/Kotlin и сложных скриптов. Maven занимает среднюю позицию, но его POM-модель и граф зависимостей требуют значительных ресурсов в крупных проектах.

#Java #middle #Maven #Best_practics
👍2
Maven Best Practices: от Apache и Spring

Apache Best Practices
Централизация конфигурации: Используйте <dependencyManagement> и <pluginManagement> в родительском POM.
Минимизация зависимостей: Исключайте ненужные транзитивные зависимости через <exclusions>.
Профили: Используйте профили для окружений (dev, prod).
Кэширование: Настройте CI/CD для кэширования ~/.m2/repository.
Плагины: Используйте последние версии плагинов и проверяйте их совместимость.

Spring Best Practices

Spring Boot BOM: Используйте spring-boot-starter-parent или spring-boot-dependencies для управления версиями:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>


Минимизация конфигурации: Полагайтесь на автоконфигурацию Spring Boot вместо ручной настройки плагинов.

Плагины: Используйте spring-boot-maven-plugin для создания исполняемых JAR:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>


В памяти: Spring Boot BOM увеличивает объем POM-модели из-за большого числа зависимостей, но упрощает управление версиями. Плагин spring-boot-maven-plugin загружает дополнительные данные для создания "fat JAR", что может быть ресурсоемким.


Нюансы и внутренние механизмы

Управление памятью:
Maven загружает POM-модели, настройки и зависимости в память, создавая графы для модулей и артефактов. Крупные проекты с сотнями зависимостей могут потреблять гигабайты памяти.
Параллельная сборка (-T) и отладка (-X) увеличивают пиковое потребление.
Оптимизируйте с помощью -pl, -am и JVM-флагов (-Xmx).


Кэширование:
Локальный репозиторий (~/.m2/repository) снижает сетевые запросы, но требует периодической очистки устаревших SNAPSHOT-версий.
CI/CD-кэширование ускоряет сборку, но увеличивает использование диска.


Безопасность:
Шифруйте пароли для репозиториев с помощью mvn --encrypt-password.
Ограничивайте доступ к ~/.m2/settings-security.xml (chmod 600).



Производительность:

Инкрементальная сборка минимизирует повторные компиляции, но требует точной настройки временных меток в target.
Gradle может быть быстрее для инкрементальных сборок, но
Maven проще для стандартизированных проектов.

Отладка:
Используйте -X для анализа реактора и зависимостей.
Проверяйте конфликты с mvn dependency:tree -Dverbose.
Анализируйте итоговую конфигурацию с mvn help:effective-pom.



#Java #middle #Maven #Best_practics
👍2
Maven в IntelliJ IDEA: Встроенный Maven и его роль


Как работает встроенный Maven

Расположение: IntelliJ IDEA включает Maven в свою установку (обычно в <IntelliJ IDEA installation>/plugins/maven/lib).
Версия: IDEA использует конкретную версию
Maven (например, 3.8.6 в последних версиях), которая обновляется с новыми релизами IDE.
Интеграция: IDEA вызывает
Maven через внутренний API, а не через командную строку. Это позволяет управлять сборкой, зависимостями и плагинами из интерфейса IDE.

Конфигурация: Настройки хранятся в File > Settings > Build, Execution, Deployment > Build Tools > Maven:

Maven home path: По умолчанию Bundled (Maven).
User settings file: Можно указать ~/.m2/settings.xml.
Local repository: По умолчанию ~/.m2/repository, но можно настроить.


В памяти: Встроенный Maven загружается в JVM IntelliJ IDEA, разделяя память с IDE. Это увеличивает общее потребление памяти, особенно при выполнении сложных сборок. IDEA кэширует зависимости в ~/.m2/repository, синхронизируя их с системным Maven.


Замена системного Maven

IntelliJ IDEA по умолчанию использует встроенный Maven, но позволяет переключиться на системный:

Переключение на системный Maven:
Откройте File > Settings > Build, Execution, Deployment > Build Tools > Maven.
В поле
Maven home path выберите путь к системной установке (например, C:\Program Files\Apache\maven-3.8.6 или /opt/apache-maven-3.8.6).
Перезапустите проект для применения изменений.



Почему встроенный
Maven заменяет системный:
Удобство: Встроенный Maven не требует установки, что упрощает начало работы.
Совместимость: IDEA гарантирует совместимость встроенного
Maven с функциями IDE (например, автодополнение в POM.xml, интеграция с dependency:tree).
Изоляция: Встроенный
Maven изолирован от системных изменений (например, обновления системного Maven), обеспечивая стабильность.
Кэширование: IDEA использует тот же локальный репозиторий (~/.m2/repository), что и системный
Maven, минимизируя дублирование данных.


Когда использовать системный Maven:
Для согласованности с CI/CD, где требуется конкретная версия Maven.
При использовании
Maven Wrapper (mvnw), который игнорирует встроенный Maven.
Для кастомных расширений или плагинов, требующих специфической версии
Maven.
При работе в терминале или на серверах без IDE.


В памяти: Системный Maven запускается как отдельный процесс, что изолирует его от памяти IDEA, но требует дополнительных ресурсов для запуска JVM. Встроенный Maven экономит ресурсы, так как работает в той же JVM, но может конфликтовать с другими задачами IDE.


Нюансы интеграции

Конфликты версий: Если системный и встроенный Maven используют разные версии, могут возникнуть несовместимости в поведении плагинов или разрешении зависимостей. Используйте mvnw или настройте IDEA на системный Maven.
Настройки: Встроенный
Maven использует ~/.m2/settings.xml, если он существует, но IDEA позволяет переопределить настройки через интерфейс.
Производительность: Встроенный
Maven может быть медленнее в IDE из-за конкуренции за ресурсы JVM. Для крупных проектов рекомендуется системный Maven с -T для параллельной сборки.
Отладка: IDEA предоставляет графический интерфейс для выполнения
Maven-целей (Run > Maven > Lifecycle), но для детальной отладки используйте терминал с -X или -e.

#Java #middle #Maven_In_IntelljIDEA
👍3
Нюансы и внутренние механизмы

Управление памятью:
Maven загружает модель POM, зависимости и плагины в память JVM. Для крупных проектов с сотнями зависимостей потребление памяти может достигать нескольких гигабайт.
Встроенный
Maven в IDEA разделяет память с IDE, что может привести к перегрузке при выполнении ресурсоемких задач (например, компиляция или тестирование).
Системный
Maven запускается отдельно, что изолирует его, но увеличивает общее потребление памяти системы.
Оптимизируйте с помощью JVM-флагов: -Xmx2048m для увеличения кучи.

Кэширование:
Локальный репозиторий (~/.m2/repository) используется обоими вариантами Maven, минимизируя дублирование артефактов.
Встроенный
Maven в IDEA кэширует результаты сборки в памяти IDE, что ускоряет повторные операции, но увеличивает нагрузку на JVM.

Совместимость:

Убедитесь, что версия JDK, указанная в JAVA_HOME, совместима с Maven (например, Maven 3.8.6 требует JDK 7+).
Разные версии
Maven могут по-разному интерпретировать POM.xml. Используйте mvnw для согласованности.

Безопасность:
Храните учетные данные для репозиториев в зашифрованном виде в ~/.m2/settings-security.xml.
Ограничьте доступ к ~/.m2 на Linux: chmod 700 ~/.m2.


Отладка:
Используйте mvn -X для вывода подробных логов о загрузке плагинов и зависимостей.
В IDEA откройте вкладку "Maven" для выполнения целей и анализа вывода.
Проверьте итоговую конфигурацию: mvn help:effective-pom или mvn help:effective-settings.

Производительность:
Системный Maven позволяет использовать флаг -T для параллельной сборки, что быстрее для многомодульных проектов.
Встроенный
Maven в IDEA может быть ограничен настройками JVM IDE. Настройте idea64.exe.vmoptions для увеличения памяти.

#Java #middle #Maven_In_IntelljIDEA
👍3
Подробная инструкция по установке Maven на Windows


Зачем устанавливать Maven

Установка Maven на систему необходима по следующим причинам:
Автоматизация сборки: Maven предоставляет стандартизированный жизненный цикл для компиляции, тестирования, упаковки и развертывания проектов.
Управление зависимостями:
Maven автоматически загружает библиотеки из репозиториев (например, Maven Central), упрощая управление зависимостями.
CI/CD-интеграция: CI/CD-системы (Jenkins, GitLab CI, GitHub Actions) требуют системной установки
Maven для выполнения сборок.
Независимость от IDE: Системный
Maven позволяет запускать команды (mvn clean install) из терминала, что полезно для серверов или скриптов.
Контроль версий: Системная установка позволяет использовать конкретную версию
Maven, обеспечивая воспроизводимость сборок.
Кастомизация: Системный
Maven дает полный контроль над настройками через settings.xml и поддерживает расширения.

В памяти Maven работает как Java-приложение, загружая модель POM, зависимости и плагины в оперативную память. Установка на систему минимизирует зависимость от IDE, но требует управления версиями и конфигурацией.


Установка Maven на Windows

Требования
JDK: Установленный Java Development Kit (версия 8 или выше, рекомендуется OpenJDK или Oracle JDK).
Интернет: Для загрузки
Maven и зависимостей.
Права администратора: Для настройки переменных окружения (опционально).


Шаги установки

Проверка JDK:

Убедитесь, что JDK установлен:
java -version

Вывод должен показать версию Java (например, openjdk 11.0.16). Если JDK отсутствует, скачайте и установите с Adoptium или Oracle.


Скачивание Maven:
Перейдите на официальный сайт Apache Maven.
Скачайте бинарный архив, например,
apache-maven-3.9.9-bin.zip.
Распакуйте архив в удобную директорию, например, C:\Program Files\Apache\
maven-3.9.9.

Настройка переменных окружения:
Откройте "Свойства системы".
Нажмите Win + R, введите sysdm.cpl и нажмите Enter.
Перейдите на вкладку "Дополнительно" → "Переменные среды".


Создайте переменную M2_HOME:
В разделе "Системные переменные" нажмите "Создать".
Имя: M2_HOME, Значение: C:\Program Files\Apache\
maven-3.9.9.

Добавьте Maven в PATH:
Найдите переменную Path в "Системных переменных" и добавьте %M2_HOME%\bin.

Проверьте переменную JAVA_HOME:
Убедитесь, что JAVA_HOME указывает на директорию JDK, например, C:\Program Files\Java\jdk-11.0.16.
Если отсутствует, создайте: Имя: JAVA_HOME, Значение: C:\Program Files\Java\jdk-11.0.16.

Проверка установки:
Откройте командную строку (Win + R → cmd).

Выполните:
mvn -version


Вывод должен показать версию Maven, Java и другие детали:
Apache Maven 3.8.6
Maven home: C:\Program Files\Apache\maven-3.8.6
Java version: 11.0.16, vendor: Adoptium



Настройка локального репозитория:
По умолчанию Maven использует ~/.m2/repository (например, C:\Users\<username>\.m2\repository) для кэширования зависимостей.

Опционально настройте settings.xml в C:\Users\<username>\.m2 для указания зеркал, прокси или профилей:
<settings>
<localRepository>C:/custom/m2/repository</localRepository>
</settings>

В памяти: При запуске Maven загружает mvn.bat (или mvn.cmd), который вызывает Java-процесс. JVM загружает Maven Core, плагины и зависимости в оперативную память. Локальный репозиторий минимизирует сетевые запросы, но может занимать значительное место на диске.


Нюансы:
Убедитесь, что JAVA_HOME указывает на JDK, а не JRE, иначе Maven не сможет компилировать код.
Если mvn не распознается, проверьте правильность PATH.
Используйте
Maven Wrapper (mvnw) в проектах для независимости от системной версии.

#Java #middle #Maven #Maven_install
👍6