Maven: как переопределить зависимость, добавленную библиотекой

116

Вот моя общая проблема:

Мой проект P зависит от A, который зависит от B, который зависит от C, который зависит от версии 1.0.1 D.

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

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

В конкретном случае D - это StAX, 1.0.1 которого содержит ошибку . Согласно примечаниям к ошибке, «проблемы были решены путем замены stax-api-1.0.1 (maven GroupId = stax) на stax-api-1.0-2 (maven GroupId = javax.xml.stream)», поэтому я Я пытаюсь именно это.

Таким образом, D = stax: stax-api: jar: 1.0.1 и C = org.apache.xmlbeans: xmlbeans: jar: 2.3.0

Я использую maven 2.0.9, если это имеет значение.

Вывод зависимости mvn: tree "

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

В POM моего проекта у меня есть следующая зависимость от «A»:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

Заранее спасибо.

wishihadabettername
источник

Ответы:

101

Просто укажите версию в вашем текущем пом. Указанная здесь версия будет иметь приоритет над другой.

Принудительное использование версии Версия
A всегда будет учитываться, если она объявлена ​​в текущем POM с определенной версией - однако следует отметить, что это также повлияет на другие нижестоящие помы, если она сама зависит от использования транзитивных зависимостей.


Ресурсы :

Колин Хеберт
источник
5
неясно, как я могу указать версию, поскольку я не объявляю зависимость от D. Кроме того, первая предоставленная вами ссылка имеет: «Этот документ описывает остальные требования для управления зависимостями, которые еще НЕ были реализованы для Maven 2.0, особенно в отношении транзитивных зависимостей ". на вершине.
wishihadabettername,
@wishihadabettername, Как сказано в другом документе: «Вы можете явно добавить зависимость к D 2.0 в A, чтобы принудительно использовать D 2.0»
Колин Хеберт,
1
Фактически вы дублируете ту же самую запись <dependency> в своем собственном файле pom. В зависимости укажите нужную <версию>. Это переопределит любую версию, используемую «более глубокими» зависимостями.
Кейт Тайлер
27

В качестве альтернативы вы можете просто исключить зависимость, которая вам не нужна. STAX включен в JDK 1.6, поэтому, если вы используете 1.6, вы можете просто исключить его полностью.

Мой пример ниже немного неверен для вас - вам нужно только одно из двух исключений, но я не совсем уверен, какое именно. Есть и другие версии Stax, плавающие вокруг, в моем примере ниже я импортировал A, который импортировал B, который импортировал C и D, каждая из которых (через еще более транзитивные зависимости) импортировала разные версии Stax. Поэтому в моей зависимости от «А» я исключил обе версии Stax.

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>
шотландец
источник
1
Необходимо отметить, что эту транзитивную зависимость можно использовать, и исключение может вызвать сбой сборки, если в этом возникнет необходимость.
Бернхард Колби
Если вы используете современный JDK (например, 1.6+) и вам нужна гораздо более старая версия stax, включенная через транзитивную зависимость, вы, вероятно, столкнетесь со всеми видами ужасных проблем с загрузчиком классов времени выполнения. Мой совет: используйте тот, что в JDK. Если вы получаете «сбой сборки», вы полагаетесь на какой-то древний API, который следует обновить. Или: откатите свой JDK до 1.5. Удачи с этим.
Скот,
11

То, что вы поместите в </dependencies>тег корневого pom, будет включено всеми дочерними модулями корневого pom. Если все ваши модули используют эту зависимость, это правильный путь.

Однако, если только 3 из 10 ваших дочерних модулей используют какую-либо зависимость, вы не хотите, чтобы эта зависимость включалась во все ваши дочерние модули. В этом случае вы можете просто поместить зависимость внутри </dependencyManagement>. Это гарантирует, что любой дочерний модуль, которому нужна зависимость, должен объявить ее в своем собственном файле pom, но они будут использовать ту же версию этой зависимости, что и указанная в вашем </dependencyManagement>теге.

Вы также можете использовать </dependencyManagement>для изменения версии, используемой в транзитивных зависимостях, потому что версия, объявленная в самом верхнем файле pom, является той, которая будет использоваться. Это может быть полезно, если ваш проект A включает внешний проект B v1.0, который включает другой внешний проект C v1.0. Иногда случается, что в проекте C v1.0 обнаруживается нарушение безопасности, которое исправлено в v1.1, но разработчики B не спешат обновлять свой проект для использования v1.1 of C. В этом случае вы можете просто объявить зависимость от C v1.1 в корневом pom вашего проекта внутри `, и все будет хорошо (при условии, что B v1.0 по-прежнему сможет компилироваться с C v1.1).

Кент Мунте Касперсен
источник
10

У меня также были проблемы с отменой зависимости в сторонней библиотеке. Я использовал подход Скота с исключением, но я также добавил зависимость с более новой версией в файле pom. (Я использовал Maven 3.3.3)

Итак, для примера stAX это будет выглядеть так:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>
Патрик Куреваар
источник
1

Принятый ответ правильный, но я хотел бы добавить свои два цента. Я столкнулся с проблемой, когда у меня был проект A, у которого был проект B в качестве зависимости. Оба проекта используют slf4j, но проект B использует log4j, а проект A использует логбэк. Проект B использует slf4j 1.6.1, а проект A использует slf4j 1.7.5 (из-за уже включенной зависимости logback 1.2.3).

Проблема: Project A не смог найти функцию, которая существует в slf4j 1.7.5, после проверки вкладки иерархии зависимостей eclipe я обнаружил, что во время сборки он использовал slf4j 1.6.1 из проекта B вместо использования logback slf4j 1.7.5 .

Я решил проблему, изменив порядок зависимостей в проекте A pom, когда я переместил запись проекта B ниже записи входа в систему, maven начал создавать проект с использованием slf4j 1.7.5.

Изменить: добавление зависимости slf4j 1.7.5 до того, как зависимость Project B.

Фернандо Майя
источник