Мы предоставляем клиентскую банку для других внутренних приложений для подключения к нашему API-интерфейсу REST. Наш API зависит от нескольких стандартных библиотек Джакарты. Лучше ли включать эти файлы JAR в файл клиента jar? Или вы просто задокументируете зависимости и их клиентов, чтобы убедиться, что у них есть эти банки на пути к классам?
Должны ли вы предоставлять зависимые библиотеки в банке клиента?
Ответ 1
Вы должны не объединить любые сторонние банки в свою банку как банку uber, но было бы неплохо включить копию всей банки, которая требуется в вашем дистрибутиве, сказать в lib или что-то еще.
Основная причина заключается в том, что ваши клиенты могут использовать некоторую систему управления зависимостями (maven/ivy и т.д.) и предоставление пакетов и классов, которые на самом деле не принадлежат вашему проекту, аннулируют эти схемы.
Существует одна альтернатива, и вы должны использовать что-то вроде плагин maven shade, чтобы переместить ваши зависимости в ваше собственное пространство имен пакетов. Это, конечно, имеет нижнюю сторону, что вы увеличите размер кода в вашей библиотеке, но на обратной стороне вы почти гарантируете версии своих зависимостей без использования каких-либо других библиотек, которые могут использовать ваши клиенты.
EDIT: в ответ на комментарий Маркуса Леона:
Возможные решения без комплектации/перемещения:
- Документация, убедитесь, что вы документируете свои зависимости и любые известные конфликты с предыдущими версиями - никто ее не читает.
- Распространяйте библиотеку через управляемую систему зависимостей... как репозиторий maven или ivy, это позволяет вам документировать в очень определенном наборе ограничений (включая верхний), какие ваши зависимости - все равно можно переопределить только ваши клиенты будут знайте, что они это делают.
- Добавить информацию OSGi в MANIFEST.MF - полезно, только если ваши клиенты фактически используют OSGi
- Если ваши зависимости были созданы с использованием maven или имеют информацию о версии в файлах манифеста, вы можете написать какую-то рутину проверки, которая сканирует путь к классам для них и проверяет там версии - немного экстремальный
В конце концов, чрезвычайно сложно гарантировать, что у вас есть зависимости, которые вы хотите, поскольку java - это связанный с поздним языком язык, возможно, что ваши зависимости (даже если они включены) переопределены кем-то, включая другую версию до вашего на пути к классам,
Примечание. Я недавно провел плохой день очень, пытаясь выяснить, почему одному из наших приложений не удалось найти новую версию log4j. причина: кто-то, пытающийся быть полезным, связал его с случайным полностью несвязанным банком.
Ответ 2
Вы должны включать любые банки, от которых вы зависите. Если вы разрешаете клиенту предоставлять стандартные банки, вы полагаетесь на них, чтобы предоставить правильную версию. Это намного более безболезненно для вас обоих, если вы включаете версии, о которых вы знаете, что работает с вашим приложением.
Ответ 3
Плюсы объединения в одну банку, очевидно:
- простота для клиента
Концы комплекта:
- невозможность обновления версий зависимых библиотек
- скрытие необходимых библиотек может фактически привести к потенциальным конфликтам в клиенте с этими дополнительными библиотеками.
- сложность для вас в процессе сборки (но способы сделать это довольно легко в Ant/Maven)
- некоторые библиотеки с манифестами не могут просто быть не затронутыми и повторно затронутыми - вам нужно фактически объединить информацию манифеста. Существует Ant и поддержка Maven для этого.
Другой вариант - использовать одну основную банку (ваш код) с атрибутом манифеста класса, установленным для вставки в другие банки. Лично мне это не нравится, так как очень легко пропустить эти полузакрытые зависимости.
В конце концов, если вы говорите только одну или две банки, я оставлю их расщепленным. Если вы говорите 10 или 15, вам может потребоваться расслоение.
Ответ 4
Вы должны включить эти банки, если вы развертываете приложение как отдельное приложение. Если вы создаете источник для компиляции, и вы предоставляете файл maven mom, вам необязательно.
Ответ 5
Вы выражаете нервозность по поводу очень специфических зависимостей между версиями библиотек (и я могу понять, что, учитывая, насколько тесно связаны, например, Hibernate между его различными модулями, только определенные версии Hibernate-аннотаций работают с одним спящим ядром, который, в свою очередь, должен использоваться со специальным валидатором hibernate).
Если вы знаете, что пакет должен работать как часть гораздо большей платформы (скажем, как плагин для фреймворка, который может загружать свои собственные банки), вам действительно нужна более мощная многоверсионная классовая загрузка OSGI (ака JSR-291): OSGI Technology
В среде с поддержкой OSGI, например Spring, Eclipse, Jonas или Glassfish, вы можете указать в XML файле свои зависимости от конкретной версии и если вы зависеть от пакета libfoo-1.1.4, тогда как другой плагин зависит от libfoo-2.0a, менеджер зависимостей OSGI гарантирует, что каждая загружает правильную версию.