Есть ли способ глобально исключить зависимость Maven?

93

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

  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jmx</artifactId>
    <version>3.3.2.GA</version>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.4.0.GA</version>
    <type>jar</type>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>

Частично это сделано для очистки файла pom, частично для предотвращения проблем в будущем, когда люди будут добавлять зависимости, которые зависят от этой исключенной зависимости, и забывают исключить ее.

Есть способ?

Себастьян Ле Каллоннек
источник
2
Не решает проблему, но maven-enforcer-plugin имеет функцию запрещенных зависимостей, которая приведет к сбою сборки, если проникнут нежелательные зависимости. Тем не менее, вам все равно придется вручную исключить их: - /
dnault
Альтернативный ответ доступен здесь: stackoverflow.com/a/39979760/363573
Стефан

Ответы:

69

Это помогает? http://jlorenzen.blogspot.com/2009/06/maven-global-excludes.html

«Предполагая, что я хочу исключить avalon-framework из своей WAR, я бы добавил в свои проекты POM с предоставленным объемом. Это работает для всех транзитивных зависимостей и позволяет указать его один раз.

<dependencies>
  <dependency>
      <artifactId>avalon-framework</artifactId>
      <groupId>avalon-framework</groupId>
      <version>4.1.3</version>
      <scope>provided</scope>
  </dependency>
</dependencies>

Это работает даже при указании этого в родительском POM, что избавит проекты от необходимости объявлять это во всех дочерних POM ».

Джоффер
источник
49
Это все еще частичный взлом - зависимость не попадет внутрь артефакта сборки, но все еще доступна во время тестов.
Туукка Мустонен
@TuukkaMustonen А что насчет runtimeприцела вместо providedприцела?
Стефан
Что произойдет, если avalon-framework 4.1.3+ будет включен в другое место проекта? См. Ответ здесь: stackoverflow.com/a/39979760/363573
Стефан
Я больше не использую Maven, поэтому я не могу проверить другие ответы, но я бы посоветовал людям рассмотреть их на случай, если есть тот, который не является частичным взломом, согласно @TuukkaMustonen
Джоффер
18

Я создал пустую банку и создал эту зависимость:

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <scope>system</scope>
    <systemPath>${basedir}/src/lib/empty.jar</systemPath>
    <version>0</version>
</dependency>

Это не идеально, потому что с этого момента у вас есть пустая банка в вашем пути компиляции / тестирования. Но это просто косметика.

оборота Guus Bloemsma
источник
3
systemобласть действия устарела: maven.apache.org/guides/introduction/…
Джейсон Янг,
Чтобы избежать использования systemобласти видимости, см. Виртуальный репозиторий Maven version99.grons.nl (Предупреждение: только HTTP) или (только для commons-logging / log4j) см. «Альтернативу 3) пустые артефакты» здесь: slf4j.org/faq.html#excludingJCL
seanf
16

Чтобы расширить комментарий dnault :

Можно использовать правило Banned Dependencies плагина Maven Enforcer, чтобы исключить зависимости. Их по-прежнему нужно исключить вручную, но сборка завершится ошибкой, если кто-то по ошибке добавит зависимость в другом месте.

<dependencies>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jmx</artifactId>
    <version>3.3.2.GA</version>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.4.1</version>
    <executions>
      <execution>
        <goals>
          <goal>enforce</goal>
        </goals>
        <configuration>
          <rules>
            <bannedDependencies>
              <excludes>
                <exclude>org.slf4j:slf4j-api</exclude>
              </excludes>
            </bannedDependencies>
          </rules>
        </configuration>
      </execution>
    </executions>
  </plugin>
</plugins>

Также есть открытый запрос функции: MNG-1977 Global dependency exclusions

Аренд против Райнерсдорфа
источник
2
Следуя вашему ответу и прочитав обсуждение из предоставленной вами ссылки, я понял, что нежелательные банки иногда попадают в толстую банку только потому, что версия maven, используемая на локальном и на сервере, отличается, поэтому логика упаковки может добавлять совершенно разные версии зависимостей, если они не строго соблюдаются. Чтобы решить аналогичную проблему, я использовал конфигурацию / excludes / exclude spring-boot-maven-plugin для <goal> repackage </goal>.
aprodan
10

Напоминаем, что вот ответ из официальной документации Maven:

Почему исключения делаются для каждой зависимости, а не на уровне POM

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

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

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>[1.4.2,)</version>
   <scope>provided</scope>
</dependency>

Любая версия slf4j-api> = 1.4.2 будет считаться предложенной (предоставленной) во время выполнения либо из настроенного пути к классам, либо из контейнера.

Ссылки

Стефан
источник