В моем офисе простого упоминания слова Xerces достаточно, чтобы вызвать убийственную ярость от разработчиков. Беглый взгляд на другие вопросы Xerces по SO, похоже, указывает на то, что в какой-то момент почти все пользователи Maven «затронуты» этой проблемой. К сожалению, понимание проблемы требует немного знаний об истории Xerces ...
история
Xerces - наиболее широко используемый анализатор XML в экосистеме Java. Почти каждая библиотека или фреймворк, написанный на Java, в некоторой степени использует Xerces (транзитивно, если не напрямую).
Банки Xerces, включенные в официальные двоичные файлы , до настоящего времени не имеют версий. Например, jar реализации Xerces 2.11.0 назван
xercesImpl.jar
и нетxercesImpl-2.11.0.jar
.Команда Xerces не использует Maven , что означает, что они не загружают официальный релиз в Maven Central .
Раньше Xerces выпускался как один jar (
xerces.jar
), но был разделен на два jar , один из которых содержал API (xml-apis.jar
), а другой содержал реализации этих API (xercesImpl.jar
). Многие старые POM Maven по-прежнему объявляют зависимостьxerces.jar
. В какой-то момент в прошлом был также выпущен XercesxmlParserAPIs.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 предоставляются через APIjava.*
иjavax.*
API; например, нет API, который предоставляет сериализацию Xerces.Помимо этого запутанного беспорядка, почти все контейнеры сервлетов (JBoss, Jetty, Glassfish, Tomcat и т. Д.) Поставляются с Xerces в одной или нескольких
/lib
папках.
Проблемы
Решение конфликта
По некоторым - или, возможно, по всем - причинам, изложенным выше, многие организации публикуют и используют пользовательские сборки Xerces в своих POM. На самом деле это не проблема, если у вас небольшое приложение и вы используете только Maven Central, но это быстро становится проблемой для корпоративного программного обеспечения, где Artifactory или Nexus проксирует несколько репозиториев (JBoss, Hibernate и т. Д.):
Например, организация А может опубликовать 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 jar
- более низкая версия, чем A jar
, Maven не знает, что это один и тот же артефакт, потому что у них разные
groupId
s. Таким образом, он не может выполнять разрешение конфликтов, и оба
jar
будут включены как разрешенные зависимости:
Classloader Hell
Как упоминалось выше, 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
и т.д.). Кроме того, наши сторонние библиотеки libs / frameworks могут не работать на версии JAXP или версии, предоставляемой контейнером сервлета.
Как мы можем лучше всего решить эту проблему с Maven? Должны ли мы осуществлять такой детальный контроль над нашими зависимостями, а затем полагаться на многоуровневую загрузку классов? Есть ли способ глобально исключить все зависимости Xerces и заставить все наши фреймворки / библиотеки использовать версию JAXP?
ОБНОВЛЕНИЕ : Джошуа Спивак загрузил исправленную версию сценариев сборки Xerces в XERCESJ-1454, которая позволяет загружать их в Maven Central. Проголосуйте / посмотрите / внесите свой вклад в эту проблему, и давайте решим эту проблему раз и навсегда.
источник
Ответы:
С 20 февраля 2013 года в Maven Central есть 2.11.0 JAR (и исходных JAR!) Xerces! Смотрите Ксерсес в Maven Central . Интересно, почему они не решили https://issues.apache.org/jira/browse/XERCESJ-1454 ...
Я использовал:
и все зависимости разрешились нормально - даже правильно
xml-apis-1.4.01
!И что самое важное (и что не было очевидно в прошлом) - JAR в Maven Central - это тот же JAR, что и в официальном
Xerces-J-bin.2.11.0.zip
дистрибутиве .Однако я не смог найти
xml-schema-1.1-beta
версию - это не может бытьclassifier
версия Maven из-за дополнительных зависимостей.источник
xml-apis:xml-apis:1.4.01
это новее , чемxml-apis:xml-apis:2.0.2
?? видеть search.maven.org/…Честно говоря, почти все, с чем мы столкнулись, прекрасно работает с версией JAXP, поэтому мы всегда исключаем
xml-apis
иxercesImpl
.источник
java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
во время выполнения.Вы можете использовать плагин Maven Enforcer с правилом запрещенных зависимостей. Это позволит вам запретить все псевдонимы, которые вы не хотите, и разрешить только тот, который вы хотите. Эти правила не удастся собрать maven вашего проекта при нарушении. Кроме того, если это правило применяется ко всем проектам на предприятии, вы можете поместить конфигурацию плагина в корпоративный родительский модуль.
видеть:
источник
Я знаю, что это не дает точного ответа на этот вопрос, но для пользователей из Google, которые используют Gradle для управления своими зависимостями:
Мне удалось избавиться от всех проблем xerces / Java8 с Gradle следующим образом:
источник
Я думаю, есть один вопрос, на который вам нужно ответить:
Существует ли xerces * .jar, с которым все в вашем приложении может жить?
Если нет, то вы в основном испорчены и должны использовать что-то вроде OSGI, что позволяет загружать разные версии библиотеки одновременно. Имейте в виду, что это в основном заменяет проблемы с jar-версиями на проблемы с загрузчиком классов ...
Если такая версия существует, вы можете заставить свой репозиторий возвращать эту версию для всех видов зависимостей. Это уродливый хак, и он в конечном итоге будет иметь одну и ту же реализацию xerces в вашем classpath несколько раз, но лучше, чем иметь несколько разных версий xerces.
Вы можете исключить каждую зависимость от xerces и добавить ее в версию, которую хотите использовать.
Интересно, можете ли вы написать какую-то стратегию разрешения версий в качестве плагина для Maven. Это было бы, вероятно, самым хорошим решением, но если это вообще возможно, потребуются некоторые исследования и кодирование.
Для версии, содержащейся в вашей среде выполнения, вы должны будете убедиться, что она либо будет удалена из пути к классам приложения, либо файлы jar приложения будут считаться первыми для загрузки классов, а затем папка lib на сервере.
Итак, чтобы подвести итог: это беспорядок, и это не изменится.
источник
Есть еще один вариант, который здесь не рассматривался: объявление зависимостей Xerces в Maven как необязательных :
По сути, это заставляет всех иждивенцев декларировать свои версию Xerces, иначе их проект не скомпилируется. Если они хотят переопределить эту зависимость, они могут это сделать, но тогда у них будет потенциальная проблема.
Это создает сильный стимул для последующих проектов:
Не все разработчики отслеживают вновь введенные зависимости (например, с
mvn dependency:tree
). Такой подход немедленно доведет дело до их сведения.Это хорошо работает в нашей организации. До его введения мы жили в том же аду, который описывает ОП.
источник
Каждый проект maven должен прекратиться в зависимости от xerces, вероятно, нет. XML API и Impl были частью Java с 1.4. Нет необходимости зависеть от xerces или XML API, все равно что сказать, что вы зависите от Java или Swing. Это неявно.
Если бы я был боссом репозитория Maven, я бы написал скрипт для рекурсивного удаления зависимостей xerces и написал read me, который говорит, что для этого репо требуется Java 1.4.
Все, что действительно ломается, потому что оно ссылается на Xerces напрямую через импорт org.apache, нуждается в исправлении кода, чтобы довести его до уровня Java 1.4 (и сделал это с 2002 года), или решение на уровне JVM с помощью одобренных библиотек, а не в maven.
источник
Вы должны сначала отладить, чтобы помочь определить свой уровень ада XML. На мой взгляд, первым шагом является добавление
в командной строке. Если это работает, тогда начните исключать библиотеки. Если нет, то добавьте
в командной строке.
источник
Что поможет, кроме исключения, это модульные зависимости.
С одной плоской загрузкой классов (автономное приложение) или полу-иерархической (JBoss AS / EAP 5.x) это было проблемой.
Но с модульными структурами, такими как модули OSGi и JBoss , это больше не такая большая боль. Библиотеки могут использовать любую библиотеку, какую захотят, независимо друг от друга.
Конечно, все же наиболее рекомендуется придерживаться только одной реализации и версии, но если нет другого пути (использование дополнительных функций из большего количества библиотек), тогда модульность может спасти вас.
Хорошим примером модулей JBoss в действии, разумеется, является JBoss AS 7 / EAP 6 / WildFly 8 , для которого он был изначально разработан.
Пример определения модуля:
По сравнению с OSGi, модули JBoss проще и быстрее. Несмотря на то, что некоторые функции отсутствуют, этого достаточно для большинства проектов, которые (в основном) находятся под управлением одного поставщика и позволяют выполнять потрясающую быструю загрузку (из-за разрешения парализованных зависимостей).
Обратите внимание, что в Java 8 ведется работа по модульности , но AFAIK предназначен прежде всего для модульности самой JRE, но не уверен, будет ли она применима к приложениям.
источник
По-видимому
xerces:xml-apis:1.4.01
, больше не в Maven Central, который, однако, чтоxerces:xercesImpl:2.11.0
ссылки.Это работает для меня:
источник
Мой друг, это очень просто, вот пример:
И если вы хотите проверить в терминале (в этом примере консоль Windows), что у вашего maven-дерева нет проблем:
источник