Объявить зависимость в разделе <dependencyManagement>, даже если зависимость не используется везде? - PullRequest
19 голосов
/ 28 мая 2009

Мы используем Maven 2.1.0. У меня есть несколько модулей, которые полностью разделены, но все еще имеют много общих зависимостей. Как и log4J, но некоторым модулям это не нужно. Мне интересно, если это хорошая идея объявить все общие зависимости в одном родительском файле в разделе <dependencyManagement> или есть лучший способ справиться с этим?

Последующий вопрос о <dependencyManagement>. Если я объявлю Log4J в родительском разделе <dependencyManagement> и подпроект не будет его использовать, будет ли он включен в любом случае?

Ответы [ 6 ]

33 голосов
/ 30 июля 2009

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

Обратите внимание, что вы можете сделать то же самое с плагинами, объявив их в разделе pluginManagement. Это означает, что любой дочерний элемент, объявляющий плагин, унаследует конфигурацию.

Например, если у вас есть 4 проекта, parent , core , ui и utils , вы можете объявить все внешние зависимости и внутренние версии проекта в родительском. Затем дочерние проекты наследуют эту конфигурацию для любых зависимостей, которые они объявляют. Если все модули должны иметь одинаковую версию, они могут даже быть объявлены как свойства в родительском.

Пример родительского элемента следующий:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.4</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>ui</artifactId>
      <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>core</artifactId>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>utils</artifactId>
        <version>${project.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <modules>
    <module>utils</module>
    <module>core</module>
    <module>ui</module>
  </modules>
</project>

И проекты utils, core и ui наследуют все соответствующие версии. Utils:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>utils</artifactId>
  <!--note version not declared as it is inherited-->
  <parent>
    <artifactId>parent</artifactId>
    <groupId>name.seller.rich</groupId>
    <version>1.0.0</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
    </dependency>
  </dependencies>
</project>

ядро:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<parent>
  <artifactId>parent</artifactId>
  <groupId>name.seller.rich</groupId>
  <version>1.0.0</version>
</parent>
<dependencies>
  <dependency>
    <groupId>name.seller.rich</groupId>
    <artifactId>utils</artifactId>
  </dependency>
</dependencies>

щ

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>ui</artifactId>
  <parent>
    <artifactId>parent</artifactId>
    <groupId>name.seller.rich</groupId>
    <version>1.0.0</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>name.seller.rich</groupId>
      <artifactId>core</artifactId>
    </dependency>
  </dependencies>
</project>
16 голосов
/ 20 августа 2011

Я написал список лучших практик . Вот самые важные из них.

  • Всегда используйте maven-forcecer-plugin
    • Enforce конвергенция зависимостей
      • В противном случае возможно, что вы зависите от двух разных jar-файлов, которые зависят от log4j. Какой из них используется во время компиляции, зависит от набора правил, которые вам не нужно запоминать. Они могут (!) Экспортироваться как транзитивные зависимости.
    • Требуется версии плагинов (для всех плагинов, даже для встроенных)
      • Определите их в pluginManagement в родительском pom для определения версий
      • В противном случае новая версия maven-surefire-plugin может сломать вашу сборку
  • Использование dependencyManagement в родительском модуле для согласованного использования версий во всех модулях
  • Периодически запускается зависимость mvn: анализ
    • Возможно, вы получаете транзитивную зависимость, от которой вы напрямую зависите во время компиляции. Если это так, важно добавить его в свою версию с нужной вам версией. Это хорошо сочетается с плагином Enforcer.
    • Возможно, вы объявляете дополнительные зависимости, которые вы не используете. Это не работает должным образом в 100% случаев, особенно с библиотеками, которые спроектированы так, чтобы иметь необязательные фрагменты (то есть slf4j-api определяется правильно, но slf4j-log4j12 завершается ошибкой).
8 голосов
/ 28 мая 2009

Каждый модуль должен иметь свой собственный POM и где он объявляет свои собственные зависимости. Это отслеживает не только внешние, но и внутренние зависимости.

Когда вы используете Maven для создания проекта, он все рассортирует. Так что, если многие модули (возможно, все) зависят от log4j, то он будет включен только один раз. Существуют некоторые проблемы, если ваши модули зависят от разных версий log4j, но этот подход обычно работает нормально.

Также полезно (если вместе работают более 1-2 разработчиков) настроить внутренний репозиторий (например, Artifactory ) и использовать его для внутреннего использования. Это значительно упрощает работу с библиотеками, которых нет в общедоступных репозиториях (просто добавьте их в свое внутреннее репозиторий!), И вы также можете использовать инструменты сборки для отправки туда сборок своего собственного кода, чтобы другие могли использовать модули без проверки код (полезный в больших проектах)

1 голос
/ 12 мая 2011

Мы используем одного общего родителя с блоком dependencyManagement для всех наших проектов. Это начинает разрушаться, когда мы перемещаем больше проектов в maven - если проекту нужна другая версия, то мы должны либо объявить ее как зависимость для всех дочерних элементов, либо явно определить версию для каждого соответствующего дочернего элемента.

Мы пробуем модель, в которой мы отделяем семейство dependencyManagement от нашего общего родителя, а затем импортируем наш корпоративный pom dependencyManagement в проект верхнего уровня. Это позволяет нам выборочно определять значения по умолчанию проекта, которые переопределяют корпоративные значения по умолчанию.

Вот оригинальный сценарий:

A   defines version 1.0 of foo.jar as the corporate default
B   child of A
C1, C2, C3  children of B
D1, D2, D3 children of C1, C2, C3 respectively

Если D1 и D2 требуют версию 1.1 файла foo.jar, то наш выбор был:

  1. Объявите foo.jar версии 1.1 как зависимость в B, создавая впечатление, что C1, C2, C3 и D3 также зависят от версии 1.1
  2. Объявите foo.jar версии 1.1 как зависимость в D1 и D2, перемещая объявление зависимости на несколько мест глубже в нашей иерархии проекта.

Вот что мы пробуем:

A   defines version 1.0 of foo.jar as the corporate default
B   dependencyManagement: imports A, declares a default of foo.jar version 1.1
C1, C2, C3  children of B
D1, D2, D3 children of C1, C2, C3 respectively

Теперь D1 и D2 просто объявляют зависимость от foo.jar и выбирают версию 1.1 из блока dependencyManagement в B.

1 голос
/ 28 мая 2009

Последующий вопрос о. Если я объявлю Log4J в разделе родительского и подпроект не использует его, будет ли он включен в любом случае?

Нет. Управление зависимостями устанавливает только версию по умолчанию и, возможно, область действия (я видел, что оба они, по-видимому, унаследованы и, по-видимому, не унаследованы, поэтому вам придется искать их самостоятельно). Чтобы включить зависимость в дочерний модуль, вам нужно объявить ее как зависимость от модуля и пропустить элемент версии. Вы можете переопределить значение по умолчанию в дочернем модуле, просто включив номер версии в элемент зависимостей POM дочернего модуля.

У меня есть несколько модулей, которые полностью разделены, но все еще имеют много общих зависимостей.

В этом случае да и нет.

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

Для модулей, которые не связаны напрямую, но построены в рамках одной группы внутри компании, вы можете рассмотреть возможность объявления версий по умолчанию для общих библиотек, таких как утилиты тестирования, утилиты ведения журналов и т. Д., Чтобы команда работала со стандартом. версии инструментов, которые вы определили как часть ваших лучших практик. Помните, что вы всегда можете увеличить версию своего супер POM, когда вы стандартизируете новый набор общих библиотек. От того, где вы проводите грань между стандартизированной библиотекой и инструментами, и до конкретных библиотек и инструментов проекта, зависит только от вас, но вашей команде должно быть легко найти.

0 голосов
/ 28 мая 2009

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

...