Я пытаюсь размонтировать XML файл в сгенерированную структуру классов, используя JAXB в java. Я сталкиваюсь с недоумением, когда загрузчик классов, который я передаю в JAXBContext.newInstance(packageName, classLoader)
, по-видимому, не может найти некоторые из необходимых классов для создания экземпляров классов схемы, но когда я вручную просматриваю поставляемый загрузчик классов для необходимых классов, они находятся там:
URLClassLoader cl = this.getJaxbClassloader();
try
{
cl.loadClass("org.postgresql.util.PGInterval");
Log.error("Found class [" + name + "] in provided classloader");
}
catch (ClassNotFoundException e)
{
Log.error("Unable to find class [" + name + "] in provided classloader");
}
JAXBContext ctx = JAXBContext.newInstance( "com.comp.gen", cl);
Метод getJaxbClassloader()
просто создает новый URLClassLoader, загружая некоторые конкретные банки, необходимые для сгенерированных классов, а затем устанавливает системный загрузчик классов как родительский. Сгенерированные классы используют некоторые библиотеки postgresql, которые я вставляю в загрузчик классов, и это тот ресурс, с которым я столкнулся. JAXB правильно находит класс ObjectFactory в поставляемом пакете, это просто создание самих сгенерированных классов, которые кажутся проблемой.
Результатом запуска этого кода является то, что ручной вызов cl.loadClass("org.postgresql.util.PGInterval");
работает нормально, он регистрирует первый оператор, говорящий, что он нашел класс, никаких исключений не было. Но когда экземпляр JAXBContext
создается, он бросает CNFE на тот же самый ресурс:
java.lang.ClassNotFoundException: org.postgresql.util.PGInterval
at java.net.URLClassLoader.findClass(URLClassLoader.java:600)
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:772)
at java.lang.ClassLoader.loadClass(ClassLoader.java:745)
at java.lang.ClassLoader.loadClass(ClassLoader.java:726)
... 78 more
Больше трассировки стека:
java.lang.NoClassDefFoundError: org.postgresql.util.PGInterval
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
at java.lang.Class.getDeclaredFields(Class.java:740)
at com.sun.xml.bind.v2.model.nav.ReflectionNavigator.getDeclaredFields(ReflectionNavigator.java:249)
at com.sun.xml.bind.v2.model.nav.ReflectionNavigator.getDeclaredFields(ReflectionNavigator.java:58)
at com.sun.xml.bind.v2.model.impl.ClassInfoImpl.findFieldProperties(ClassInfoImpl.java:370)
at com.sun.xml.bind.v2.model.impl.RuntimeClassInfoImpl.getProperties(RuntimeClassInfoImpl.java:176)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:243)
at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:100)
at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:81)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:209)
at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:95)
at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:81)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:315)
at com.sun.xml.bind.v2.model.impl.RegistryInfoImpl.<init>(RegistryInfoImpl.java:99)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.addRegistry(ModelBuilder.java:357)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:327)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:466)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1136)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:202)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
at java.lang.reflect.Method.invoke(Method.java:620)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:184)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:144)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:346)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:443)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:406)
У кого-нибудь есть идея, что здесь происходит? Я был под впечатлением (и JAXBContext docs поддерживают это), что он будет использовать предоставленный загрузчик классов для поиска классов реализации, необходимых для создания экземпляров классов, поэтому, учитывая, что ресурс, как представляется, находится в загрузчике классов, который я поставляю, почему JAXB не удалось найти его?
EDIT: Добавление соответствующей части сгенерированного класса, использующего ресурс PGInterval:
import org.postgresql.util.PGInterval;
...
...
...
@XmlElement(name = "time_to_live", required=false)
protected PGInterval time_to_live;
public PGInterval gettime_to_live()
{
return time_to_live;
}
public void settime_to_live(PGInterval time_to_live)
{
this.time_to_live = time_to_live;
}
Я думаю, стоит отметить, что это единственный импорт в сгенерированном классе, который не находится в стандартной библиотеке java.