Исключить все переходные зависимости одной зависимости

221

В Maven2, чтобы исключить одну транзитивную зависимость, я должен сделать что-то вроде этого:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

Проблема с этим подходом состоит в том, что я должен делать это для каждой транзитивной зависимости, вносимой sample-artifactB.

Есть ли способ использовать какой-то подстановочный знак, чтобы исключить все транзитивные зависимости сразу, а не по одному?

pbreault
источник
Иногда нужно использовать последнюю версию библиотеки, скажем, Spring 2.5.6, но некоторые другие зависимости включают в себя более старую версию, например struts2-spring-plugin (2.1.6) включает в себя Spring 2.5.3. В таких сценариях существует требование об исключении или переопределении версии.
Винод Сингх
1
Используйте плющ. Просто шучу.
Джейк Торонто

Ответы:

54

Для maven2 нет способа сделать то, что вы описываете. Для Maven 3 есть. Если вы используете Maven 3, пожалуйста, смотрите другой ответ на этот вопрос

Для maven 2 я бы порекомендовал создать свой собственный pom для зависимости с вашим <exclusion>. Для проектов, которым необходимо использовать эту зависимость, установите зависимость для своего пользовательского pom вместо типичного артефакта. Хотя это не обязательно позволяет исключать все транзитивные зависимости с помощью одного <exclusion>, оно позволяет вам написать свою зависимость только один раз, и все ваши проекты не должны поддерживать ненужные и длинные списки исключений.

Уэйли
источник
12
Я бы порекомендовал не делать свой собственный пом, чтобы обойти исключения. Это делает вашу сборку гораздо менее переносимой и снижает понимание.
Брайан Фокс
1
В случае, если вы не смотрите мимо принятого ответа: jira.codehaus.org/browse/MNG-3832
Якуб Боченски
@JakubBochenski ответ, который я дал, специфичен для maven 2, которым и был помечен этот вопрос (в то время, когда я писал этот комментарий). Ваша ссылка актуальна только для maven 3. Несмотря на это, я отредактировал свой ответ, чтобы перейти к ссылке с более высоко оцененным ответом.
кит
306

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

У меня есть многомодульный проект, который содержит модуль «приложение», на который ссылаются в двух WAR-упакованных модулях. Один из этих WAR-упакованных модулей действительно нуждается только в классах домена (и я еще не отделил их от модуля приложения). Я нашел это, чтобы работать:

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>app</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Подстановочный знак для groupId и artifactId исключает все зависимости, которые обычно распространяются на модуль с использованием этой зависимости.

enricopulatzo
источник
9
Символ * для группы и artifiact , кажется, работает в Maven 3
nkr1pt
22
Я не знаю, как вам удалось найти это работающим, поскольку Maven 3 явно предупреждает об использовании звездочки: [WARNING] соответствовать действительному шаблону идентификатора. [ПРЕДУПРЕЖДЕНИЕ] Настоятельно рекомендуется исправить эти проблемы, поскольку они угрожают стабильности вашей сборки. [ПРЕДУПРЕЖДЕНИЕ] По этой причине будущие версии Maven могут больше не поддерживать создание таких некорректных проектов. Не могли бы вы предоставить некоторые доказательства того, что они поддерживаются и могут использоваться? В противном случае я бы посчитал ваш комментарий крайне вводящим в заблуждение.
ᄀ ᄀ
7
Прекрасно работал с Maven 3.0.4. Спасибо большое !
Евгений Гольдин
1
maven 3.0.4 -> у меня не получилось. В результате jar сильно отличается, когда я использую asterix, или когда я явно исключаю все прямые зависимости. возможно, это связано с тем, что я использую плагин maven-assembly-plugin для создания толстой фляги. в этом случае предложенный sulotion не работает!
Гилад Хох
31
Этот метод действителен. Они исправили предупреждение, о котором другие сообщают в maven 3.2.1: questions.apache.org/jira/browse/MNG-3832
Райан
32

Одна вещь, которую я нашел полезным:

Если вы поместите зависимость с исключениями в раздел dependencyManagement родительского POM для вашего проекта или в импортируемое POM для управления зависимостями, вам не нужно повторять исключение (или версию).

Например, если ваш родительский POM имеет:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

Тогда модули в вашем проекте могут просто объявить зависимость как:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

В родительском POM будет указана версия и исключения. Я использую эту технику почти во всех наших проектах, и она исключает много повторений.

Джошуа Дэвис
источник
23

Три года назад я рекомендовал использовать версию 99, которой не существует, но теперь я нашел лучший способ, тем более что версия 99 находится в автономном режиме:

В родительском POM вашего проекта используйте maven -forcer-plugin для сбоя сборки, если нежелательная зависимость проникает в сборку. Это можно сделать с помощью правила запрещенных зависимостей плагина :

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Затем, когда это предупредит вас о нежелательной зависимости, исключите ее в разделе родительского POM <dependencyManagement>:

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Таким образом, нежелательная зависимость не будет отображаться случайно (в отличие от простой, <exclusion>которую легко забыть), она не будет доступна даже во время компиляции (в отличие от providedобласти действия), нет поддельных зависимостей (в отличие от версии 99) и она ' Будет работать без собственного репозитория (в отличие от версии 99). Этот подход будет работать даже на основе версии артефакта, классификаторов, области действия или целого идентификатора группы - подробности см. В документации .

Эско Луонтола
источник
Обратите внимание, что по крайней мере в Maven 3.1, <configuration>игнорируется при выполнении цели из командной строки и должен быть перемещен прямо вверх <plugin>.
Дэвид Харкнесс
Я только что нашел то, что похоже на неприятную ошибку Maven - версия 3.5.2. У меня есть проект с подмодулями, где я исключаю зависимость в родительском <dependencyManagement>разделе. Запуск mvn dependency:treeв этом конкретном проекте не будет иметь исключенной зависимости вообще. Но все проекты, импортирующие эту зависимость, не будут учитывать <exclusions>другой родительский объект - исключенный будет закрадываться !!! Я должен был перейти <exclusions>к каждому модулю пом непосредственно.
cbaldan
11

Я использую следующий обходной путь: вместо того, чтобы пытаться исключить артефакт во всех соответствующих зависимостях, я рисую зависимость как «предоставленную» на верхнем уровне. Например, чтобы избежать отправки xml-apis «любой версии»:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Майкл Зильберманн
источник
9

В настоящее время нет способа исключить более одной транзитивной зависимости за раз, но для этого существует запрос функции на сайте Maven JIRA:

https://issues.apache.org/jira/browse/MNG-2315

Питер
источник
6

Для этого есть обходной путь: если вы установите область зависимости во время выполнения , транзитивные зависимости будут исключены. Хотя имейте в виду, это означает, что вам нужно добавить дополнительную обработку, если вы хотите упаковать зависимость времени выполнения.

Чтобы включить зависимость времени выполнения в любой пакет, вы можете использовать цель копирования плагина maven-dependency-plugin для определенного артефакта .

Богатый продавец
источник
1
Это помогло мне обойти проблемы с компилятором Android Dalvik, который не мог справиться с некоторыми из двухуровневых переходных включений - но мне пришлось использовать <scope>provided</scope>вместо этого <scope>runtime</scope>.
Гаррет Уилсон
6

если вам нужно исключить все транзитивные зависимости из артефакта зависимости, который вы собираетесь включить в сборку, вы можете указать это в дескрипторе сборки-плагина:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>
Superole
источник
3

Если вы разрабатываете в Eclipse, вы можете в графе POM Editor (расширенные вкладки включены) найти зависимость, которую вы хотите исключить из своего проекта, а затем:

щелкните по нему правой кнопкой мыши -> «Исключить артефакт Maven ...», и Eclipse сделает исключение для вас без необходимости выяснять, с какой зависимостью связана библиотека.

тиб
источник
обратите внимание, что это работает, только если вы используете плагин m2eclipse
Николас Момартс
2

По какой причине вы исключаете все переходные зависимости?

Если есть конкретный артефакт (например, регистрация общего доступа), который необходимо исключить из каждой зависимости, может помочь подход Версии 99 не существует .


Обновление 2012: не используйте этот подход. Используйте maven -forcer-plugin и исключения . Версия 99 создает фиктивные зависимости, а хранилище Версии 99 находится в автономном режиме (есть похожие зеркала, но вы не можете полагаться на них, чтобы оставаться в сети всегда; лучше всего использовать только Maven Central).

Эско Луонтола
источник
1

В симуляционной проблеме у меня была объявлена ​​желаемая зависимость с предоставленной областью действия. При таком подходе транзитивные зависимости выбираются, но НЕ включаются в фазу пакета, что вам и нужно. Мне также нравится это решение с точки зрения обслуживания, потому что для обслуживания не требуется ни pom, ни пользовательского pom, как в решении whaley; вам нужно только указать конкретную зависимость в контейнере и все готово

nkr1pt
источник
-2

Используйте последний Maven в вашем classpath. Он удалит дубликаты артефактов и сохранит последний Maven артефакт.

Самрадж
источник