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 зависимости и исключение, например:
<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>
Но при сборке получаю ошибку:
[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), объявите плагин явно в
Содержание
- Переопределение транзитивной зависимости Maven для spring-boot-maven-plugin
- Короткий ответ — рабочая конфигурация (рекомендуется)
- Подробные варианты — что пробовать и почему
- Вариант A — plugin
(override) - Вариант B — исключение и замена commons-compress в плагине
- Вариант C — dependencyManagement / прямая зависимость проекта (ограничения)
- Вариант D — pluginRepositories / settings.xml / зеркала (если плагин не разрешается)
- Вариант E — крайние меры: локальная установка / администраторы репозитория
- Проверка и отладка: как убедиться, что используется commons-lang3:3.20.0
- Примеры POM: готовые сниппеты
- Источники
- Заключение
Переопределение транзитивной зависимости Maven для spring-boot-maven-plugin
У вас типичная ситуация: spring-boot-maven-plugin (версия 3.5.7) опирается на spring-boot-loader-tools → commons-compress → commons-lang3:3.16.0, а корпоративный репозиторий возвращает 403 для этой версии и сборка падает. Попытка прописать зависимости в
Суть решения — не «ловить» ошибку скачивания, а изменить класс-путь плагина: явно указать нужную версию 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. Пример — минимальная рабочая конфигурация:
<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)
Идея: указать в
Плюсы:
- Работает локально и в 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:
<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.
Подробно про
Вариант C — dependencyManagement / прямая зависимость проекта (ограничения)
Можно добавить в parent POM секцию dependencyManagement с нужной версией commons-lang3:
<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
- Проверьте settings.xml и зеркала (mirror) — возможно, mirror настроен как mirrorOf=“*” и перенаправляет всё в корпоративный репозиторий. Тогда добавление
в POM не поможет — mirror перебьёт POM. - Решения: временно разрешить прямой доступ к central для плагинов/артефактов, настроить исключение в mirrors, либо попросить админов скопировать/выгрузить нужную версию (3.20.0) в корпоративный репозиторий.
- В POM можно попробовать добавить pluginRepositories с указанием central:
<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: готовые сниппеты
- Рекомендуемый (вставьте в ваш POM — с явным объявлением плагина):
<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>
- Замена commons-compress + исключение старой версии:
<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>
- Пример dependencyManagement (помогает для проектных зависимостей, не гарантирует override для плагина):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.20.0</version>
</dependency>
</dependencies>
</dependencyManagement>
- Пример pluginRepositories (если допустимо напрямую обращаться к central):
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>
</pluginRepositories>
Помните: если в settings.xml настроено mirrorOf=“*”, то этот pluginRepository может быть проигнорирован — тогда нужен доступ у админов.
Источники
- https://www.sonatype.com/blog/2008/04/how-to-override-a-plugins-dependency-in-maven
- https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
- https://stackoverflow.com/questions/6028534/how-to-exclude-dependency-in-a-maven-plugin
- https://stackoverflow.com/questions/3937195/maven-how-to-override-the-dependency-added-by-a-library
- https://stackoverflow.com/questions/65278378/overriding-transitive-version-dependency-in-maven
- https://spring.io/blog/2016/04/13/overriding-dependency-versions-with-spring-boot
- https://www.baeldung.com/mvn-plugin-dependency-exclusion
- https://www.baeldung.com/maven-version-collision
- https://blog.devgenius.io/find-and-fix-transitive-dependency-version-upgrade-conflicts-in-maven-7ffb4ceae683
- https://issue.life/questions/55127485
Заключение
Коротко: самый надёжный путь — явно объявить spring-boot-maven-plugin в