У моєму кабінеті достатньо лише згадки про слово Xerces, щоб викликати в розробників жорстоку лють. Побіжний погляд на інші запитання Xerces про SO, схоже, вказує на те, що майже всі користувачі Maven в певний момент "торкаються" цієї проблеми. На жаль, розуміння проблеми вимагає трохи знань про історію Xerces ...
Історія
Xerces - це найбільш широко використовуваний аналізатор XML в екосистемі Java. Практично кожна бібліотека або фреймворк, написаний на Java, використовує Xerces у певній якості (транзитивно, якщо не безпосередньо).
Банки Xerces, що входять до офіційних бінарних файлів , на сьогоднішній день не піддаються версії. Наприклад, банку реалізації Xerces 2.11.0 названо,
xercesImpl.jar
а неxercesImpl-2.11.0.jar
.Команда Xerces не використовує Maven , а це означає, що вони не завантажують офіційний реліз у Maven Central .
Xerces раніше випускався як один jar (
xerces.jar
), але був розбитий на дві банки, в одній з яких містився API (xml-apis.jar
) і в одній, що містив реалізацію цих API (xercesImpl.jar
). Багато людей старшого віку Мейвен все ще декларують залежність відxerces.jar
. У якийсь момент в минулому, Xerces також був звільнений якxmlParserAPIs.jar
, від чого залежать і деякі старші POM.Версії, призначені банкам xml-apis та xercesImpl тими, хто розгортає свої банки в сховищах Maven, часто різні. Наприклад, xml-apis може бути надана версія 1.3.03, а xercesImpl може бути надана версія 2.8.0, навіть якщо обидва з Xerces 2.8.0. Це відбувається тому, що люди часто позначають банку xml-apis версією специфікацій, які вона реалізує. Існує дуже хороший, але неповний пробій цього тут .
Для ускладнення питань, Xerces - це аналізатор XML, який використовується в опорній реалізації Java API для обробки XML (JAXP), включеного в JRE. Класи реалізації перепаковуються під
com.sun.*
простором імен, що робить небезпечним доступ до них безпосередньо, оскільки вони можуть бути недоступні в деяких JRE. Однак не всі функції Xerces піддаються впливуjava.*
таjavax.*
API; наприклад, не існує API, який би піддавав серіалізацію Xerces.Додаючи до заплутаного безладу, майже всі контейнери сервлетів (JBoss, Jetty, Glassfish, Tomcat та ін.) Доставляють із Xerces в одну або кілька своїх
/lib
папок.
Проблеми
Вирішення конфліктів
З деяких (або, можливо, з усіх) причин, зазначених вище, багато організацій публікують та споживають власні збірки Xerces у своїх POM. Це насправді не є проблемою, якщо у вас є невеликий додаток і ви використовуєте лише Maven Central, але це швидко стає проблемою для корпоративного програмного забезпечення, де Artifactory або Nexus мають доступ до кількох сховищ (JBoss, Hibernate тощо):
Наприклад, організація A може публікувати xml-apis
як:
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
Тим часом організація B може публікувати те саме jar
, що:
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
Хоча B's jar
є нижчою версією, ніж A jar
, Maven не знає, що вони є тим самим артефактом, оскільки вони мають різні
groupId
s. Таким чином, він не може виконувати вирішення конфлікту, і обидва
jar
s будуть включені як вирішені залежності:
Пекло класу
Як було сказано вище, JRE поставляється з Xerces в JAXP RI. Хоча було б непогано позначити всі залежності Xerces Maven як <exclusion>
s або як<provided>
, сторонній код, від якого ви залежите, може або не може працювати з версією, наданою в JAXP JDK, яку ви використовуєте. Крім того, у вас є контейнери Xerces, що постачаються у вашому контейнері сервлетів. Це надає вам ряд варіантів: Ви видалите версію сервлетів і сподієтесь, що ваш контейнер працює на версії JAXP? Чи краще залишити сервлет-версію і сподіватися, що ваші програми додатків працюватимуть на версії сервлетів? Якщо один або два з вирішених вище невирішених конфліктів вдасться прослизнути у ваш продукт (це легко трапиться у великій організації), ви швидко опинитесь у пеклі завантажувачів, цікавившись, яку версію Xerces вибирає завантажувач класів під час виконання і чи ні вибере ту саму банку в Windows та Linux (мабуть, ні).
Рішення?
Ми намагалися позначаючи все залежності Xerces Maven , як <provided>
або як <exclusion>
, але це важко реалізувати (особливо з великою групою) , з огляду на , що артефакти мають так багато псевдонімів ( xml-apis
, xerces
, xercesImpl
, xmlParserAPIs
і т.д.). Крім того, наші ліцензії / рамки сторонніх розробників можуть не працювати у версії JAXP або версії, наданій контейнером сервлетів.
Як ми можемо найкраще вирішити цю проблему з Мейвен? Чи потрібно нам здійснювати такий тонкозернистий контроль над своїми залежностями, а потім покладатися на багаторівневе навантаження класів? Чи є спосіб глобально виключити всі залежності Xerces і змусити всі наші рамки / версії використовувати версію JAXP?
ОНОВЛЕННЯ : Джошуа Співак завантажив виправлену версію сценаріїв побудови Xerces на XERCESJ-1454, яка дозволяє завантажувати в Maven Central. Голосуйте / дивіться / сприяйте цій проблемі, і давайте вирішимо цю проблему раз і назавжди.