Han*_*etz 52 java osgi jaxb apache-felix
它就在那里,在它应该索引的包中.我还是打电话的时候
JAXBContext jc = JAXBContext.newInstance("my.package.name");
Run Code Online (Sandbox Code Playgroud)
我得到一个JAXBException说
"my.package.name"不包含ObjectFactory.class或jaxb.index
虽然它确实包含两者.
什么工作,但不是我想要的,是
JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);
Run Code Online (Sandbox Code Playgroud)
来自其他人的这个问题出现在一些邮件列表和论坛上,但似乎没有得到答案.
我在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;
}
Run Code Online (Sandbox Code Playgroud)
Han*_*etz 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);
Run Code Online (Sandbox Code Playgroud)
也许你也可以得到Bundle实例正在使用的类加载器,但我无法弄清楚如何,以上解决方案对我来说似乎是安全的.
小智 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
Run Code Online (Sandbox Code Playgroud)
与JAXB相关.B类是JAXBContext,bMethod是newInstance()
如果您熟悉的OSGi包的限制,那么它必须很清楚,现在捆B未导入包com.c即C类是不可见的以B类,因此它无法实例C.
解决方案是将ClassLoader传递给bMethod.此ClassLoader应来自导入com.c的包.在这种情况下,我们可以传递A.class.getClassLoader(),因为bundle A正在导入com.c
希望这有用.