Проблема загрузчика классов с внутренним интерфейсом реализации JAXB com.sun.xml.bind.namespacePrefixMapper - PullRequest
1 голос
/ 11 ноября 2019

Мне нужна помощь для решения следующей проблемы: я использую Websphere Liberty 19.0.0.9 с Oracle и IBM Java 1.8 и запускаю старое приложение (EAR), содержащее EJB, который сериализует XML с JAXB. Прикладная программа должна управлять определениями и префиксами пространства имен XML и делает это, предоставляя реализацию com.sun.xml.bind.namespacePrefixMapper для javax.xml.bind.Marshaller.setProperty со свойством «com.sun.xml.bind.namespacePrefixMapper». ,Во время выполнения возникает ошибка java.lang.NoClassDefFoundError: com / sun / xml / bind / marshaller / NamespacePrefixMapper при загрузке класса реализации. В server.xml содержится функция javaee-8.0, а в реализации JAXB для библиотек свободы wlp-19.0.0.9 \ lib \ com.ibm.ws.jaxb.tools.2.2.10_1.0.32.jar содержит класс com.sun..xml.bind.marshaller.NamespacePrefixMapper.

Я попытался решить эту проблему, поместив jaxb-impl-2.2.4.jar в EAR / lib (что неверно, поскольку JAXB предоставляется JEE), но затемпроизошла ошибка в com.sun.xml.bind.v2.runtime.MarshallerImpl.setProperty (MarshallerImpl.java:511), потому что проверка if (! (значение instanceof NamespacePrefixMapper)) не удалась, потому что Classloader (AppClassLoader) реализациипредоставил другой объект класса для класса NamespacePrefixMapper, чем загрузчик классов MarshallerImpls (org.eclipse.osgi.internal.loader.EquinoxClassLoader). Но это показало, что свобода может получить доступ к NamespacePrefixMapper.

Я сделал несколько попыток использовать один и тот же загрузчик классов для реализации и MarschallerImpl при их загрузке, и я попытался решить его с помощью настроек загрузчика классов на сервере. XML. Нет успехаЯ знаю, что не рекомендуется использовать такие классы, специфичные для реализации JAXB, но приложение было разработано таким образом и не может быть легко изменено.

Любая помощь приветствуется, которая говорит мне, как убедить свободу в предоставлении NamespacePrefixMapper. класс для загрузчика классов приложения или для использования загрузчиков классов приложения NamespacePrefixMapper также в MarschallerImpl. Спасибо.

//The implementation class looks for example like this:
public class MyNamespacePrefixMapperImpl extends com.sun.xml.bind.marshaller.NamespacePrefixMapper {...}
JAXBContext c = JAXBContext.newInstance(some mapped class);
Marshaller m = c.createMarshaller();
com.sun.xml.bind.marshaller.NamespacePrefixMapper mapper = new MyNamespacePrefixMapperImpl();// Here the NoClassDefFoundError occurs.
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper); // Here the instanceof check fails if jaxb-impl.jar is in EAR/lib.

1 Ответ

0 голосов
/ 12 ноября 2019

это опасная ситуация без простого решения. Liberty пытается «спрятать» внутренние пакеты, чтобы избежать сценариев, когда пользователям нужна немного другая версия реализации, чем та, которую предоставляет среда - наиболее яркий пример этой проблемы был в традиционной WAS, где пользователи хотели использовать другую версию Jakarta Commons Logging. чем то, что было поставлено с WAS - для этого требовалось, чтобы пользователи предоставили свои собственные, либо в изолированной общей библиотеке, либо использовали другие хаки загрузки родительских классов, чтобы это работало. Liberty позволяет избежать этих проблем, изолируя внутренние реализации от пользовательских приложений.

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

Наиболее идеальным решением будет рефакторинг кода приложения, чтобы он не зависел от внутренних классов JAXB - кто-то с болееВ этом может помочь экспертиза JAXB ... Но, похоже, это неосуществимо, поэтому другой альтернативой будет создание пользовательской функции. Пользовательская функция, по сути, является расширением среды выполнения Liberty, поэтому она имеет доступ к пакетам, которых нет у пользовательских приложений. Он также позволяет вам добавлять пакеты в качестве API для пользовательских приложений - так что вы можете использовать пользовательскую функцию для добавления com.sun.xml.bind.marshaller в качестве общедоступного API - тогда ваше пользовательское приложение может свободно расширять его. Вы также можете включить свой класс MyNamespacePrefixMapperImpl в свою пользовательскую функцию и зарегистрировать ее там, чтобы она автоматически применялась ко всем приложениям на вашем сервере.

Более подробную информацию о пользовательских функциях можно найти здесь: https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_feat_example.html

Надеюсь, это поможет, Энди

...