Программирование

Maven: переопределить транзитивную зависимость плагина Spring Boot

Как переопределить версию commons-lang3 (3.20.0) в spring-boot-maven-plugin, чтобы избежать 403 ошибки в корпоративном репозитории. Рабочие примеры POM, dependencyManagement, exclusions и plugin dependencies для Maven.

Как переопределить версию транзитивной зависимости плагина в Maven (spring-boot-maven-plugin -> commons-compress -> commons-lang3)?

Контекст:

  • Spring Boot: 3.5.7
  • Корпоративный репозиторий запрещает org.apache.commons:commons-lang3:3.16.0 (возвращает 403), из-за чего сборка падает
  • Нужно, чтобы использовалась версия commons-lang3:3.20.0

Пробовал добавить в pluginManagement зависимости и исключение, например:

xml
<pluginManagement>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>3.5.7</version>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-buildpack-platform</artifactId>
 <version>3.5.7</version>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-compress</artifactId>
 <version>1.28.0</version>
 <exclusions>
 <exclusion>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
 </plugin>
 </plugins>
</pluginManagement>

Но при сборке получаю ошибку:

text
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:3.5.7:repackage (repackage) on project demo1: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:3.5.7:repackage failed: Plugin org.springframework.boot:spring-boot-maven-plugin:3.5.7 or one of its dependencies could not be resolved: Failed to collect dependencies at org.springframework.boot:spring-boot-maven-plugin:jar:3.5.7 -> org.springframework.boot:spring-boot-loader-tools:jar:3.5.7 -> org.apache.commons:commons-compress:jar:1.27.1 -> org.apache.commons:commons-lang3:jar:3.16.0: Failed to read artifact descriptor for org.apache.commons:commons-lang3:jar:3.16.0: The following artifacts could not be resolved: org.apache.commons:commons-lang3:pom:3.16.0 (absent): Could not transfer artifact org.apache.commons:commons-lang3:pom:3.16.0 from/to rt-central (https://company-repository.ru/repository/maven-repo.maven.apache.org): status code: 403, reason phrase: Forbidden (403) -> [Help 1]

Вопрос: как правильно переопределить (поднять) версию транзитивной зависимости commons-lang3, которую тянет плагин, чтобы сборка использовала версию 3.20.0? Какие варианты решения подходят в этой ситуации (dependencyManagement в родительском POM, plugin dependencies, exclusions, настройка зеркал/репозиториев, pluginRepositories) и можно ли привести пример рабочей конфигурации POM?

Чтобы переопределить версию транзитивной зависимости плагина spring-boot-maven-plugin (commons-compress -> commons-lang3), объявите плагин явно в и добавьте в него зависимость org.apache.commons:commons-lang3:3.20.0 (или подмените commons-compress на версию, которая тянет 3.20.0) — это заставит Maven использовать 3.20.0 для класса плагина и остановит попытки скачать запрещённую 3.16.0. Если же корпоративное зеркало всё равно блокирует загрузку POM/артефакта, потребуется правка настроек зеркал/pluginRepositories или вмешательство админов репозитория.


Содержание


Переопределение транзитивной зависимости Maven для spring-boot-maven-plugin

У вас типичная ситуация: spring-boot-maven-plugin (версия 3.5.7) опирается на spring-boot-loader-tools → commons-compress → commons-lang3:3.16.0, а корпоративный репозиторий возвращает 403 для этой версии и сборка падает. Попытка прописать зависимости в не сработала — часто причина в том, что конфигурация из pluginManagement не применяется там, где плагин автоматически запускается родительским POM/плагином, и/или в настройках зеркала (mirror) запросы на артефакты всё равно направляются в запрещённое место.

Суть решения — не «ловить» ошибку скачивания, а изменить класс-путь плагина: явно указать нужную версию commons-lang3 (или обновлённый commons-compress) в зависимостях самого плагина. Это стандартный подход для переопределения зависимостей плагина (см. пример и объяснение на Sonatype) — плагин будет использовать те артефакты, которые вы положили в его classpath https://www.sonatype.com/blog/2008/04/how-to-override-a-plugins-dependency-in-maven. Если же артефакт всё равно не скачивается из-за зеркала — тогда надо смотреть репозитории/настройки mirror в settings.xml или просить админов репозитория.


Короткий ответ — рабочая конфигурация (рекомендуется)

Самый надёжный и быстрый путь: в вашем POM явно объявить spring-boot-maven-plugin в разделе build/plugins и внутри него добавить зависимость на commons-lang3:3.20.0. Пример — минимальная рабочая конфигурация:

xml
<build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>3.5.7</version>
 <dependencies>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
 </plugin>
 </plugins>
</build>

После этого запустите сборку и проверьте, что Maven больше не пытается загрузить commons-lang3:3.16.0. Этот подход подтвержден практикой и обсуждениями (например, на StackOverflow и в статьях о переопределении зависимостей плагинов) https://stackoverflow.com/questions/6028534/how-to-exclude-dependency-in-a-maven-plugin, https://www.sonatype.com/blog/2008/04/how-to-override-a-plugins-dependency-in-maven.


Подробные варианты — что пробовать и почему

Вариант A — plugin (override)

Идея: указать в / нужную версию commons-lang3 (или новую commons-compress). Maven будет собирать classpath плагина с вашими зависимостями и брать 3.20.0 вместо 3.16.0.

Плюсы:

  • Работает локально и в CI без изменения глобальных mirrors (если артефакт доступен).
  • Локально контролируете версию, не трогая parent POM.

Минусы:

  • Если корпоративный mirror действительно блокирует скачивание POM/артефакта по крайнему уровню (перед тем как применится override), может всё ещё возникать 403 — тогда нужен вариант D или обращение к админам.

Ссылки: Sonatype, примеры на StackOverflow https://www.sonatype.com/blog/2008/04/how-to-override-a-plugins-dependency-in-maven, https://stackoverflow.com/questions/3937195/maven-how-to-override-the-dependency-added-by-a-library.


Вариант B — исключение и замена commons-compress в плагине

Если хотите точнее — можно явно добавить в плагин новую версию commons-compress (которая сама зависит от commons-lang3:3.20.0) и при необходимости исключить старую commons-lang3:

xml
<plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>3.5.7</version>
 <dependencies>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-compress</artifactId>
 <version>1.28.0</version> <!-- версия, которая тянет commons-lang3 3.20.0 -->
 <exclusions>
 <exclusion>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
</plugin>

Совет: используйте этот вариант, если вы хотите согласовать версии в плагине «сверху-вниз» — сначала заменить commons-compress на версию с нужной зависимостью, затем явно добавить commons-lang3.

Подробно про — в официальной документации Maven и на Baeldung https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html, https://www.baeldung.com/mvn-plugin-dependency-exclusion.


Вариант C — dependencyManagement / прямая зависимость проекта (ограничения)

Можно добавить в parent POM секцию dependencyManagement с нужной версией commons-lang3:

xml
<dependencyManagement>
 <dependencies>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
</dependencyManagement>

Но: dependencyManagement управляет версиями зависимостей проекта, а не зависимостями плагинов. Поэтому этот приём полезен для проектных (compile/runtime) зависимостей и может не предотвратить попытки загрузить 3.16.0 для classpath самого плагина. Об этом говорят и статьи по управлению версиями и конфликтам зависимостей https://spring.io/blog/2016/04/13/overriding-dependency-versions-with-spring-boot, https://www.baeldung.com/maven-version-collision.

Иногда добавление direct dependency на commons-lang3 в зависимости проекта (не в dependencyManagement) помогает, потому что артефакт уже есть в локальном репозитории и Maven не пытается тянуть 3.16.0 из удалённого зеркала — но это ненадёжный хак для CI.


Вариант D — pluginRepositories / settings.xml / зеркала (если плагин не разрешается)

Если даже с plugin Maven вынужден читать POM 3.16.0 через корпоративное зеркало (и получает 403), значит на уровне настроек (settings.xml) или самого зеркала стоит правило, которое блокирует этот артефакт. Что делать?

  • Проверьте settings.xml и зеркала (mirror) — возможно, mirror настроен как mirrorOf=“*” и перенаправляет всё в корпоративный репозиторий. Тогда добавление в POM не поможет — mirror перебьёт POM.
  • Решения: временно разрешить прямой доступ к central для плагинов/артефактов, настроить исключение в mirrors, либо попросить админов скопировать/выгрузить нужную версию (3.20.0) в корпоративный репозиторий.
  • В POM можно попробовать добавить pluginRepositories с указанием central:
xml
<pluginRepositories>
 <pluginRepository>
 <id>central</id>
 <url>https://repo.maven.apache.org/maven2</url>
 </pluginRepository>
</pluginRepositories>

Но повторюсь: если mirror в settings.xml направляет запросы на корпоративный прокси — админов править всё равно придётся.

Практические заметки и обсуждение корпоративных зеркал встречаются в обсуждениях по проблемам загрузки артефактов (см. обсуждения на StackOverflow и рекомендации по mirror/plug-in репозиториям).


Вариант E — крайние меры: локальная установка / администраторы репозитория

Если ничего не помогает:

  • Попросите администраторов репозитория добавить org.apache.commons:commons-lang3:3.20.0 в корпоративный прокси; это наилучший и чистый вариант для CI.
  • Как временную меру для локальной разработки — скачайте нужный JAR и установите в локальный репозиторий через mvn install:install-file (но это не решит проблему в CI).
  • Ещё один крайний и нежелательный вариант — попросить админов «замаппить» 3.16.0 на содержимое 3.20.0 в прокси — делать так не рекомендую из-за возможной несовместимости.

Проверка и отладка: как убедиться, что используется commons-lang3:3.20.0

Как проверить, что override сработал:

  • mvn help:effective-pom — покажет итоговую конфигурацию плагина в effective POM; в секции spring-boot-maven-plugin должны быть ваши .
  • mvn -X package (или mvn -X verify) — включите debug-лог: в логе вы увидите, какие артефакты Maven пытается скачать (по URL) и какие версии используются в classpath плагина.
  • mvn dependency:tree -Dincludes=org.apache.commons:commons-lang3 — показывает, какие версии commons-lang3 участвуют в дереве зависимостей проекта (но не всегда отображает classpath плагинов).
  • Проверьте ~/.m2/repository/org/apache/commons/commons-lang3 — наличие 3.20.0 и отсутствие попыток загрузить 3.16.0 подтвердит успех.

Если mvn -X всё ещё показывает запрос на 3.16.0 до попытки применения ваших plugin-override, значит проблема на уровне зеркала/metadata — см. раздел про mirrors/pluginRepositories.


Примеры POM: готовые сниппеты

  1. Рекомендуемый (вставьте в ваш POM — с явным объявлением плагина):
xml
<build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>3.5.7</version>
 <dependencies>
 <!-- Принудительная версия для плагина -->
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
 </plugin>
 </plugins>
</build>
  1. Замена commons-compress + исключение старой версии:
xml
<plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <version>3.5.7</version>
 <dependencies>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-compress</artifactId>
 <version>1.28.0</version>
 <exclusions>
 <exclusion>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
</plugin>
  1. Пример dependencyManagement (помогает для проектных зависимостей, не гарантирует override для плагина):
xml
<dependencyManagement>
 <dependencies>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.20.0</version>
 </dependency>
 </dependencies>
</dependencyManagement>
  1. Пример pluginRepositories (если допустимо напрямую обращаться к central):
xml
<pluginRepositories>
 <pluginRepository>
 <id>central</id>
 <name>Maven Central</name>
 <url>https://repo.maven.apache.org/maven2</url>
 </pluginRepository>
</pluginRepositories>

Помните: если в settings.xml настроено mirrorOf=“*”, то этот pluginRepository может быть проигнорирован — тогда нужен доступ у админов.


Источники

  1. https://www.sonatype.com/blog/2008/04/how-to-override-a-plugins-dependency-in-maven
  2. https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
  3. https://stackoverflow.com/questions/6028534/how-to-exclude-dependency-in-a-maven-plugin
  4. https://stackoverflow.com/questions/3937195/maven-how-to-override-the-dependency-added-by-a-library
  5. https://stackoverflow.com/questions/65278378/overriding-transitive-version-dependency-in-maven
  6. https://spring.io/blog/2016/04/13/overriding-dependency-versions-with-spring-boot
  7. https://www.baeldung.com/mvn-plugin-dependency-exclusion
  8. https://www.baeldung.com/maven-version-collision
  9. https://blog.devgenius.io/find-and-fix-transitive-dependency-version-upgrade-conflicts-in-maven-7ffb4ceae683
  10. https://issue.life/questions/55127485

Заключение

Коротко: самый надёжный путь — явно объявить spring-boot-maven-plugin в и добавить в него зависимость org.apache.commons:commons-lang3:3.20.0 (или обновить commons-compress внутри плагина). Это решение выполняет задачу «maven переопределить транзитивную зависимость» для плагина и обычно устраняет 403, если артефакт доступен. Если же корпоративный mirror блокирует загрузку POM/артефакта до того, как override применится, то придётся настроить pluginRepositories / зеркала или привлечь админов репозитория для размещения/разрешения нужной версии.

Авторы
Проверено модерацией
Модерация
Maven: переопределить транзитивную зависимость плагина Spring Boot