它就在那里,在它应该索引的包中。不过,当我打电话时
JAXBContext jc = JAXBContext.newInstance("my.package.name");
我得到一个JAXBException,说
“my.package.name”不包含ObjectFactory.class或jaxb.index
虽然它确实包含两者。
什么工作,但不是我想要的,是
JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);
来自其他人的这个问题出现在一些邮件列表和论坛上,但似乎没有得到答案。
我在OpenJDK 6上运行它,所以我获得了源包并将调试器放入库中。它首先查找jaxb.properties,然后查找系统属性并且无法找到,它尝试使用com.sun.internal.xml.bind.v2.ContextFactory创建默认上下文。在那里,Exception被抛出(在ContextFactor.createContext(String ClassLoader, Map)
内),但我看不到发生了什么,因为源不在这里。
ETA :
从ContentFactory的源代码判断,我发现here,这可能是代码无法正常工作的代码:
/**
* 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;
}
从我的previous experience,我猜这与运行的OSGi容器的类加载机制有关。不幸的是,我仍然有点不在我的深度在这里。
答案 0 :(得分:60)
好的,这需要花一些时间,但答案并不令人惊讶,甚至不是那么复杂:
JAXB找不到jaxb.index,因为默认情况下,newInstance(String)
使用当前线程的类加载器(由Thread.getContextClassLoader()
返回)。这在Felix内部不起作用,因为OSGi包和框架的线程都有单独的类加载器。
解决方案是从某个地方获取合适的类加载器并使用newInstance(String, ClassLoader)
。我从包含jaxb.index
的包中的一个类中获得了一个合适的类加载器,出于灵活性的原因,明智的选择可能是ObjectFactory
:
ClassLoader cl = my.package.name.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("my.package.name", cl);
也许您也可以使用Bundle
实例正在使用的类加载器,但我无法弄清楚如何,以上解决方案对我来说似乎是安全的。
答案 1 :(得分: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 相关。 B类是JAXBContext,bMethod是newInstance()
如果您熟悉OSGi程序包限制,那么现在必须非常清楚 Bundle B 不导入包 com.c ,即 C类 不可见到 B类因此无法实例化C。
解决方案是将 ClassLoader 传递给bMethod。此ClassLoader应来自导入com.c 的包。在这种情况下,我们可以传递 A.class.getClassLoader(),因为包A正在导入com.c
希望这有用。
答案 2 :(得分:4)
对于同样的问题,我通过手动将包放入导入来解决它。
答案 3 :(得分:1)
如果您在项目中使用maven,那么只需使用此库:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-osgi</artifactId>
<version>2.2.7</version>
</dependency>
它是为Glasfish服务器创建的,但也使用Tomcat(已检查)。 使用此库,您可以轻松地将JAXB与OSGI包一起使用。
答案 4 :(得分:0)
编辑2:
我曾经在我的应用程序中遇到类似奇怪的类加载问题。如果我将它作为普通应用程序运行,一切都很好但是当我将其作为Windows服务调用时,它开始因ClassNotFoundExceptions而失败。分析表明,线程的类加载器以某种方式为null。我通过在线程上设置SystemClassLoader解决了这个问题:
// ...
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
thread.start();
// ...
不知道你的容器是否允许这种改变。
答案 5 :(得分:0)
我刚遇到这个问题。对我来说,解决方案是使用IBM的JRE而不是Oracle。似乎JAXB实现在那个实现中对OSGI更友好。
答案 6 :(得分:0)
我成功解决了这个问题,方法是将我生成的包含ObjectFactory
的类的包添加到我的包定义的<Private-Package>
部分,再加上org.jvnet.jaxb2_commons.*
答案 7 :(得分:0)
可能有另一种情况可以解决这个问题。
安装并启动导出包含jaxb.index或objectFactory.java的包的包时
然后请确保导入类的包已停止或指向正确的包名。
还要检查pom.xml中的export和import语句
面对servicemix(karaf)osgi容器中的类似问题
答案 8 :(得分: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>
答案 9 :(得分:-1)
我的解决方案是:
JAXBContext context = JAXBContext.newInstance( new Class [] {“my.package.name”} );
OR
JAXBContext context = JAXBContext.newInstance( new Class [] {class.getName()} );
OR
完整的解决方案:
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%工作