Вопрос по jaxb, java – Почему JAXB не может найти мой jaxb.index при работе внутри Apache Felix?

52

Это прямо там, в пакете, который он должен индексировать. Тем не менее, когда я звоню

JAXBContext jc = JAXBContext.newInstance("my.package.name");

Я получаю JAXBException, говоря, что

"my.package.name" doesnt contain ObjectFactory.class or jaxb.index

хотя он содержит оба.

Что работает, но не совсем то, что я хочу, это

JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);

Этот вопрос от других людей появляется в некоторых списках рассылки и на форумах, но, похоже, не получает ответов.

Я запускаю это на OpenJDK 6, поэтому я получил исходные пакеты и включил мой отладчик в библиотеку. Он начинает с поиска jaxb.properties, затем ищет системные свойства и, не находя ни того, ни другого, пытается создать контекст по умолчанию, используя com.sun.internal.xml.bind.v2.ContextFactory. Там, исключение бросается (внутриContextFactor.createContext(String ClassLoader, Map)), но я не вижу, что происходит, потому что здесь нет источника.

ETA:

Судя по исходному коду для ContentFactory, я нашелВот, это, вероятно, кусок кода, который не работает должным образом:

/**
 * Look for jaxb.index file in the specified package and load it's contents
 *
 * @param pkg package name to search in
 * @param classLoader ClassLoader to search in
 * @return a List of Class objects to load, null if there weren't any
 * @throws IOException if there is an error reading the index file
 * @throws JAXBException if there are any errors in the index file
 */
private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
    final String resource = pkg.replace('.', '/') + "/jaxb.index";
    final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);

    if (resourceAsStream == null) {
        return null;
    }

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

Я имел в виду, пожалуйста, опубликуйте трассировку стека исключений. akarnokd
Пост уже немного длиннее, но я уже отследил происхождение исключения, только что опубликовал это выше. Hanno Fietz

Ваш Ответ

10   ответов
0

Edit 2:

Однажды у меня была похожая странная проблема с загрузкой классов в моем приложении. Если я запускал его как обычное приложение, все было в порядке, но когда я вызывал его как службу Windows, он начинал давать сбой с ClassNotFoundExceptions. Анализ показал, что загрузчики классов имеют свои нулевые загрузчики. Я решил проблему, установив SystemClassLoader в потоках:

// ...
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
thread.start();
// ...

Не знаю, допускает ли ваш контейнер такие изменения.

Error: User Rate Limit Exceeded Hanno Fietz
0

добавив пакет сгенерированных классов, содержащийObjectFactory к<Private-Package> часть моего определения пакета, плюсorg.jvnet.jaxb2_commons.*

4

6

над которым я работаю. После прочтенияhttp://jaxb.java.net/faq/index.html#classloader Я понял, что JAXBContext не может найти пакет, содержащий jaxb.index.

Я постараюсь сделать это как можно более ясным.

У нас есть

Bundle A
   -- com.a
      A.java
        aMethod()
        {
            B.bMethod("com.c.C");
        }
MANIFEST.MF
Import-Package: com.b, com.c         

Bundle B
   -- com.b
      B.java
        bmethod(String className)
        {
            Class clazz = Class.forName(className);
        }

Export-Package: com.b

Bundle C
   -- com.c
      C.java
        c()
        {
            System.out.println("hello i am C");
        }

Export-Package: com.c

Относиться кJAXB. class B is JAXBContext and bMethod is newInstance()

Если вы знакомы с ограничениями пакетов OSGi, тогда должно быть ясно, чтоBundle B не импортирует пакетcom.c т.е.class C являетсяnot visible вclass B следовательно, он не может создать экземпляр C.

Решение было бы передатьClassLoader к методу. Этот ClassLoader должен исходить изbundle that is importing com.c, В этом случае мы можем пройтиA.class.getClassLoader() посколькуbundle A is importing com.c

Надеюсь, это было полезно.

0

что модульный тест, который не был связан с разработанным мной модулем, не имел зависимости pom.xml от моего модуля. UT все еще распознал мой модуль из-за извлечения списка пакетов из общего файла конфигурации.

При запуске UT он не компилировал новый модуль, поэтому он не генерировал ObjectFactory.java, поэтому я получил сообщение об ошибке, хотя при компиляции модуля я мог видеть ObjectFactory.java

добавили следующую зависимость:

<dependency>
    <groupId>com.myCompany</groupId>
    <artifactId>my-module-name</artifactId>
    <version>${project.version}</version>
    <scope>test</scope>
</dependency>
60

это заняло довольно много времени, но ответ не удивителен и даже не сложен:

JAXB can't find jaxb.index, because by default, newInstance(String) uses the current thread's class loader (as returned by Thread.getContextClassLoader()). This doesn't work inside Felix, because the OSGi bundles and the framework's threads have separate class loaders.

Решение состоит в том, чтобы получить подходящий загрузчик классов и использоватьnewInstance(String, ClassLoader), Я получил подходящий загрузчик классов от одного из классов в пакете, который содержитjaxb.indexразумный выбор по причинам гибкости, вероятно,ObjectFactory:

ClassLoader cl = my.package.name.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("my.package.name", cl);

Может быть, вы могли бы также получить в загрузчике классов, чтоBundle экземпляр использует, но я не могу понять, как, и приведенное выше решение кажется мне безопасным.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Hanno Fietz
Error: User Rate Limit Exceededin generalError: User Rate Limit Exceeded Hanno Fietz
Error: User Rate Limit Exceeded
1

просто используйте эту библиотеку:

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-osgi</artifactId>
    <version>2.2.7</version>
</dependency>

Он создан для сервера Glasfish, но также работает с Tomcat (проверено). С этой библиотекой вы можете легко использовать JAXB с пакетами OSGI.

0

том, чтобы использовать JRE IBM вместо Oracle. Похоже, что реализация JAXB более удобна для OSGI.

0

Когда вы устанавливаете и запускаете пакет, который экспортирует пакет, содержащий jaxb.index или objectFactory.java

Затем убедитесь, что пакеты, импортирующие классы, остановлены или указывают на правильное имя пакета.

Также проверьте операторы экспорта и импорта в pom.xml

Столкнулся с подобной проблемой в контейнере servicemix (karaf) osgi

-1

JAXBContext context = JAXBContext.newInstance (new Class[]{"my.package.name"});

ИЛИ ЖЕ

JAXBContext context = JAXBContext.newInstance (new Class[]{class.getName()});

ИЛИ ЖЕ

полное решение:

public static <T> T deserializeFile(Class<T> _class, String _xml) {

        try {

            JAXBContext context = JAXBContext.newInstance(new Class[]{_class});
            Unmarshaller um = context.createUnmarshaller();

            File file = new File(_xml);
            Object obj = um.unmarshal(file);

            return _class.cast(obj);

        } catch (JAXBException exc) {
            return null;
        }
    }

Работает 100%

Похожие вопросы