Управление Зависимостями Большой Системы Java

У нас есть большая (>500,000 LOC) Java-система, которая зависит от 40-50 OSS пакеты. Система построена с помощью Ant, и управление зависимостями в настоящее время обрабатывается вручную. Я исследую Айви и / или Maven, чтобы автоматизация зависимостей. Мы смотрели в Maven в качестве автоматизации сборки система в прошлом году и отклонила его, потому что это потребует полностью реструктуризация нашей системы в соответствии с архитектурой Maven. Теперь я хотите автоматизировать только задачи управления зависимостями.

Я провел некоторые эксперименты с Айви, но столкнулся с проблемами. Например, когда я указываю ActiveMQ как зависимость и говорю Ivy используйте POMs в репозитории Maven для спецификации зависимостей, Ivy извлекает кучу пакетов (Jetty, Derby и Geronimo для instance), что я знаю, не нужно просто использовать ActiveMQ.

Если я установил usepoms= "false" в ivysettings.xml он извлекает только в частности, ActiveMQ.jar, но это, кажется, разрушает цель Айви и низводит его до простого jar-fetcher c вручную построенной зависимостью технические характеристики.

здесь есть большая проблема, то, что раньше называлось "DLL Hell" в Окна. В некоторых случаях две прямые зависимости первого уровня будут укажите на разные версии одной и той же транзитивной зависимости (для экземпляр log4j.jar). Только один log4j.jar может быть в classpath, поэтому разрешение зависимостей включает в себя ручное определение версии совместим со всеми своими клиентами в нашей системе.

Я думаю, все это сводится к качеству зависимости каждого пакета спецификация (POM). В случае ActiveMQ нет области объявления, поэтому любая ссылка на ActiveMQ будет загружать все зависимости, если мы вручную не исключаем те, которые мы знаем, что мы не хотеть.

в случае log4j для автоматического разрешения зависимостей потребуется что все клиенты log4j (другие пакеты, которые зависят от log4j) проверьте все предыдущие версии log4j и укажите диапазон (или список) совместимые версии log4j в POM. Это, наверное, тоже я многого прошу.

Это текущее положение дел, или я что-то пропустила?

8 ответов


вы абсолютно правы, говоря, что

Я думаю, что все это сводится к качеству спецификации зависимостей каждого пакета (POM).

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

В конце концов, даже принимая log4j версия с учетом того, есть ли у вас внешние зависимости, выберите версию или выберите версию, которую вы знаете, работает для вас?


Что касается того, как вы можете настроить зависимости, вот что вы можете сделать с Ivy:

ненужные пакеты

Ivy извлекает кучу пакетов (например, Jetty, Derby и Geronimo), которые, как я знаю, не нужны для использования ActiveMQ.

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

вы, вероятно, хотите посмотреть в плющ исключить механизм:

<dependency name="A" rev="1.0">
  <exclude module="B"/>
</dependency>

версий зависимостей

только один log4j.jar может быть в пути к классам, поэтому разрешение зависимостей включает в себя ручное определение, какая версия совместима со всеми своими клиентами в нашем система.

возможно, я неправильно понимаю это, но нет руководство элемент в разрешении конфликта Айви. Существует список менеджеры конфликтов по умолчанию:

  • все: этот менеджер конфликтов разрешает конфликты, выбирая все версии. Также называемый NoConflictManager, он выселяет любой модуль.
  • последний раз: этот менеджер конфликтов выбирает только "последнюю" версию, последнее определяется как последнее по времени. Обратите внимание, что последнее по времени дорого вычислять, поэтому предпочитайте последнюю ревизию, если можете.
  • последний-редакция: этот менеджер конфликтов выбирает только "последнюю" ревизию, последняя определяется сравнением строк ревизий.
  • последний-совместимый: этот менеджер конфликтов выбирает последнюю версию в конфликтах, которые могут привести к совместимому набору зависимостей. Это означает, что в конец этот менеджер конфликтов не допускает никакого конфликта (как строгий менеджер конфликтов), за исключением того, что он следует наилучшей стратегии усилий, чтобы попытаться найти набор совместимых модулей (в соответствии с ограничениями версии);
  • строго: этот менеджер конфликтов создает исключение (т. е. вызывает сбой сборки) при обнаружении конфликта.

при необходимости, вы можете предоставьте свой собственный менеджер конфликтов.


Это в значительной степени. Система зависимостей maven (за которой более или менее следует Ivy) оставляет за отдельными проектами хорошую работу по добавлению необходимых метаданных для их зависимостей. Большинство нет.

Если вы идете по этому маршруту, ожидайте потратить время на настройку исключений.

на плакаты, рекомендующие OSGi, ОП сказал, что он не готов перепроектировать свою систему сборки для Maven, я бы не подумал, что он захочет перепроектировать его приложение чтобы быть совместимым с OSGi. Кроме того, многие проекты OSS, совместимые с OSGi (и их не так много, как вы надеетесь), имеют плохие или худшие метаданные, чем в Maven


из перечисленных зависимостей следующие определяются как optional на activemq-core pom (Также см. соответствующий раздел из книги Maven).

  • org.апаш.дерби: дерби
  • org.апаш.Джеронимо.технические характеристики: geronimo-jta_1.0.1B_spec

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

в Maven необязательные зависимости автоматически. По сути, любая зависимость, объявленная необязательной, должна быть повторно объявлена в вашем pom для ее использования. Из документации, связанной выше:

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

однако, поскольку проект не может быть разделен (опять же, по какой-либо причине), эти зависимости объявляются необязательными. Если пользователь хочет использовать функции, связанные с необязательной зависимостью, ему придется повторно объявить эту необязательную зависимость в своем собственном проекте. Это не самый ясный способ справиться с этой ситуацией, но опять же, как необязательные зависимости, так и исключения зависимостей являются решениями stop-gap.

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

<dependency name="A" rev="1.0">
  <exclude module="B"/>
</dependency>

это не совсем удовлетворительно, я знаю. Может быть, Ivy поддерживает дополнительные зависимости (я буду иметь дальнейший взгляд и обновление, если я найти что-нибудь), но механизм исключений, по крайней мере, позволяет управлять ими.


Относительно последней части вашего вопроса. Maven разрешит версии зависимостей для log4j, и если версии совместимы, он автоматически выберет "ближайшую" из перечисленных версий.

С введение в механизм зависимостей:

  • посредничество зависимостей-это определяет, какая версия зависимость будет использоваться при обнаружении нескольких версий артефакта. В настоящее время Maven 2.0 поддерживает только использование "ближайшего определения", что означает, что он будет использовать версию ближайшей зависимости от вашего проекта в дереве зависимостей. Вы всегда можете гарантировать версию, объявив ее явно в POM вашего проекта. Обратите внимание, что если две версии зависимостей находятся на одной глубине в дереве зависимостей, до Maven 2.0.8 не было определено, какая из них выиграет, но поскольку Maven 2.0.9 считается порядок в объявлении: первое объявление выигрывает.

    • "ближайшее определение" означает, что используемая версия будет ближе всего к вашему проекту в дереве зависимостей, например. если зависимости для A, B и C определены как A -> B -> C -> D 2.0 и A -> E -> D 1.0, то D 1.0 будет использоваться при построении A, потому что путь от A до D через E короче. Вы можете явно добавить зависимость от D 2.0 В A, чтобы принудительно использовать D 2.0

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


Я думаю, что это действительно текущее положение дел. OSGi и предлагаемая новая система упаковки для java 1.7 (обсуждение этого уже пришло к выводу?) есть попытки исправить, по крайней мере, в зависимости от разных версий библиотеки, но я не думаю, что они смогут исправить вашу проблему прямо сейчас.


в настоящее время я использую Ivy для управления более чем 120 OSS и проприетарными библиотеками для нескольких проектов (некоторые автономные, некоторые зависимые). Еще в 2005 году (когда Айви еще была из Jayasoft) я решил (или должен был) написать The ivy.XML-файлы для каждого интегрированного пакета.

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



существует целая идея инъекции зависимостей, которая неизбежно приведет к необходимости реструктуризации программы. Я слышал некоторый шум о том, что GUICE хорош в этом отношении. В перспективе развертывания у меня был разумный успех с развертыванием только the .банку мы построили с зависимостью .банки извлекаются из оригинальных проектов через jnlp. Система сборки за этим включала ручное отслеживание новых версий зависимостей и обновление в системе сборки.


"таково текущее положение дел"

да.

это компромисс с открытым исходным кодом.

платформа с закрытым исходным кодом (т. е. .Net) решит все это для вас.

решение с открытым исходным кодом означает, что вы должны решить (и решить ее) все время.

возможно, вы сможете найти некоторые готовые конфигурации и заплатить кому-то, чтобы держать их в курсе. Например, вы можете использовать Red Hat Enterprise Линукс. Если вы придерживаетесь именно того, что они поддерживают (и ничего больше), тогда конфигурация решена.

шансы хороши, однако, что никакая упакованная конфигурация не соответствует вашим требованиям.