jaxb throws javax.xml.bind.UnmarshalException: Expected elements are (none) only when 运行 in osgi bundle

jaxb throws javax.xml.bind.UnmarshalException: Expected elements are (none) only when running in osgi bundle

我想在我的 liberty osgi web 应用程序中使用 jaxb 解组 xml。

我有一个包含以下代码的捆绑包:

InputStream is = new FileInputStream(serviceXmlPath);
JAXBContext jaxbContext = JAXBContext.newInstance(Service.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return jaxbUnmarshaller.unmarshal(is);

服务 class 在同一个包中,我使用蓝图将代码接口公开为服务。然后我有另一个包含使用它的 servlet 的捆绑包。

我对能够正确解组的核心代码进行了单元测试。但是,当我 运行 它在 Osgi 包中的 webshpere liberty 8.5.5.8 上时,出现以下异常:

[err] javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Service"). Expected elements are (none)
[err]   at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:660)

我检查以确保当我 运行 自由读取正确的文件和数据时,我的单元测试(来自 eclipse 的 junit 4)和服务器都使用相同的 jre。 (在本例中为 IBM java 7。)我没有自由地使用 jaxb 功能,因此它应该使用来自 java.

的功能

我不明白为什么 运行 osgi.你能建议我还应该检查什么吗?

编辑:

我发现这是一个 class 加载程序问题,因为我打印了 class 加载程序并看到 JAXBContext 有一个与我自己的 class 不同的 class 加载程序]是的。但是,使用以下代码更改 jaxb 的 classloader:

ClassLoader classloader = MyClass.class.getClassLoader();
jaxbContext = JAXBContext.newInstance(MyClass.class.getName(), classloader);

结果:

[err] javax.xml.bind.JAXBException: Unable to create context
 - with linked exception:
[java.lang.reflect.InvocationTargetException]

然后我在包中添加了一个 jaxb.index 文件和以下代码来打印 classloader:

JAXBContext jaxbContext = JAXBContext.newInstance(Service.class);
JAXBContext jaxbContext2 = JAXBContext.newInstance();
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();   

System.out.println("classloader of Service.class:" + Service.class.getClassLoader().toString());
System.out.println("classloader of JAXBContext:" + JAXBContext.class.getClassLoader());
System.out.println("classloader of jaxbContext:" + jaxbContext.getClass().getClassLoader());
System.out.println("classloader of jaxbContext2:" + jaxbContext2.getClass().getClassLoader());
System.out.println("classloader of jaxbUnmarshaller:" + Unmarshaller.class.getClassLoader());

当我 运行 我得到了:

classloader of Service.class:org.eclipse.osgi.internal.loader.EquinoxClassLoader@b0adb798[DataService:1.0.0.qualifier(id=379)]
classloader of JAXBContext:org.eclipse.osgi.internal.loader.EquinoxClassLoader@271677de[com.ibm.ws.javaee.jaxb.2.2:1.0.11.cl50820151201-1942(id=343)]
classloader of jaxbContext:org.eclipse.osgi.internal.loader.EquinoxClassLoader@b997af78[com.ibm.ws.xlxp.1.5.3:1.0.11.cl50820151201-1942(id=341)]
classloader of jaxbContext2:org.eclipse.osgi.internal.loader.EquinoxClassLoader@b997af78[com.ibm.ws.xlxp.1.5.3:1.0.11.cl50820151201-1942(id=341)]
classloader of jaxbUnmarshaller:org.eclipse.osgi.internal.loader.EquinoxClassLoader@271677de[com.ibm.ws.javaee.jaxb.2.2:1.0.11.cl50820151201-1942(id=343)

请注意,我是否传入 class 并不重要,它使用自己的 classloader(顺便说一句,这是自由启用的 jaxb2.2。如果我禁用它 classloaders 除了第一个之外都显示为 null 但其他行为相同)

我终于让它工作了。在我的包清单中,我导入了包 javax.xml.bind,我认为这是我所需要的,因为这是我在调用解组的代码中导入的。事实证明,我还需要添加 javax.xml.bind.annotation,因为模型 类 导入了它。

无论如何,感谢斯科特的评论