我们在系统中长期使用JAXB 2.1。我们有一个使用Ant构建的平台,并生成一堆部署在OSGi运行时的捆绑包。我们使用Java SE 6.两个类具有相同的XML类型名称“objectFactory”
我们在构建过程中使用JAXB从不同模式生成数据类型。这些类打包在捆绑包中,并在运行时用于序列化/反序列化内容。另外我们在运行时在我们的平台中使用JAXB来从用户提供的其他模式(它是一种MDA平台)生成数据类型。
在OSGi运行时,我们有一个包含JAXB jar包并导出必需包的包。我们使用生成的所有对象工厂的上下文路径创建一个JAXBContext实例,因此我们可以编组/解组所有数据类型。
到目前为止,我们正在努力升级到JAXB (2.2.4)的最新稳定版本,并且我们在尝试在运行时创建上下文时遇到问题。我们得到以下异常:
Two classes have the same XML type name "objectFactory". Use @XmlType.name and @XmlType.namespace to assign different names to them.
this problem is related to the following location:
at some.package.ObjectFactory
this problem is related to the following location:
at some.other.package.ObjectFactory
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:191)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:187)
... 76 more
错误两个类具有相同的XML类型名称“objectFactory对象”打印每个在生成过程中产生的对象工厂。
我们已经在SO中看到了几个帖子,但是应用于生成的类型而不是对象工厂。我们认为JAXB可能不会将ObjectFactory类标识为对象工厂,而是将其标识为数据类型。
一种可能性是,我们在Java中使用6 JAXB的内部版本是,所以我们决定使用系统属性-Djava.endorsed.dirs,并把三个罐子(JAXB的API-2.2.4 .jar,jaxb-impl-2.2.4.jar和jaxb-xjc-2.2.4.jar)在该路径中,但仍然无法正常工作。
我们认为这个问题可能是因为我们在OSGi运行时和构建过程中使用了不同版本的JAXB,所以生成的代码不兼容。但也许我们错了,还有另一个问题。
你有什么想法吗?
在此先感谢。
(编辑:更多关于这方面的详细信息)
我们以这种方式创建的JAXBContext:
ClassLoader classLoader = new JAXBServiceClassLoader(getParentClassLoader(),
Collections.unmodifiableMap(objectFactories));
context = JAXBContext.newInstance(contextPath.toString(), classLoader);
其中的contextPath是包含通过分隔我们的所有对象工厂字符串 ':',和JAXBServiceClassLoader是:
private static final class JAXBServiceClassLoader extends ClassLoader
{
@NotNull
private final Map<String, Object> objectFactories;
private JAXBServiceClassLoader(@NotNull ClassLoader parent, @NotNull Map<String, Object> objectFactories)
{
super(parent);
this.objectFactories = objectFactories;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException
{
Class<?> ret;
try
{
ret = super.loadClass(name);
}
catch (ClassNotFoundException e)
{
Object objectFactory = objectFactories.get(name);
if (objectFactory != null)
{
ret = objectFactory.getClass();
}
else
{
throw new ClassNotFoundException(name + " class not found");
}
}
return ret;
}
}
(编辑:后阿龙的职位)
我一直在调试JAXBContextImpl的所有内部,事情是JAXBContextImpl试图从我们的ObjectFactory类获取类型信息,这是错误的。实际上,在com.sun.xml.internal.bind.v2.model.impl.ModelBuilder:314中,getClassAnnotation()调用返回null,但是当我看到该实例时,我可以看到注释XmlRegistry。如果我运行((Class)c).getAnnotations()[0] .annotationType()。getClassLoader(),它将返回该对象的值。包含我的JAXB JARB的OSGi包“lib.jaxb”的classLoader,它是正确的。
所以,我想,我们正在加载在同一时间两个不同版本XmlRegistry的,一个从JDK和JAXB 2.2.4罐子另一个。问题是:为什么?
而且,更重要的是,而不是加载所有com.sun.xml.internal。*类(如JAXBContextImpl),而不是加载并执行com.sun.xml.bind.v2.runtime.JAXBContextImpl JAXB罐子?在调试过程中,我可以看到它正在做一些反射,但我不明白为什么要这样做。
使用Java SE 6我建议使用支持JAXB 2.1的JAXB impl的最新修补程序版本,除非您尝试使用特定的JAXB 2.2功能。 –
对不起,我没有提到。升级到JAXB 2.2.4的原因是我们正在将我们的JAX-WS版本升级到2.2.5,并取决于该版本的JAXB(http://jax-ws.java.net/2.2.5/docs/ ReleaseNotes.html)。否则,我们可以使用JAXB 2.1。 – Denian
它看起来像您的JAXB impl错误地将'ObjectFactory'视为一个域类。这很可能是由于@ XmlRegistry注释由于您的域类和JAX-WS实现之间的ClassLoader差异而未被识别。您是直接创建'JAXBContext',还是使用JAX-WS实现? –