java 两个类具有相同的 XML 类型名称“objectFactory”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7361336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Two classes have the same XML type name "objectFactory"
提问by Denian
We have been using JAXB 2.1 for a long time in our system. We have a platform that is built with Ant and generates a bunch of bundles that are deployed in an OSGi runtime. We use Java SE 6.
我们已经在系统中使用 JAXB 2.1 很长时间了。我们有一个使用 Ant 构建的平台,并生成一堆部署在 OSGi 运行时中的包。我们使用 Java SE 6。
We use JAXB during the build process to generate datatypes from different schemas. Those classes are packaged in the bundles and used in runtime to serialize/deserialize content. In addition we use JAXB in our platform in runtime to generate datatypes from other schemas provided by the user (it a sort of MDA platform).
我们在构建过程中使用 JAXB 从不同的模式生成数据类型。这些类打包在包中并在运行时用于序列化/反序列化内容。此外,我们在运行时在我们的平台中使用 JAXB 从用户提供的其他模式(它是一种 MDA 平台)生成数据类型。
In the OSGi runtime we have a bundle that has the JAXB jars and exports the necessary packages. We create a JAXBContext instance with the context path of all the object factories generated, so we can marshall/unmarshall all our datatypes.
在 OSGi 运行时中,我们有一个包含 JAXB jar 并导出必要包的包。我们使用生成的所有对象工厂的上下文路径创建一个 JAXBContext 实例,因此我们可以编组/解组所有数据类型。
That has been working so far but right now we are trying to upgrade to the latest stable version of JAXB (2.2.4)and we are having problems trying to create the context in runtime. We get the following exception:
到目前为止,这一直在工作,但现在我们正在尝试升级到 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
The error Two classes have the same XML type name "objectFactory"is printed for each of the object factories generated during the build process.
为构建过程中生成的每个对象工厂打印错误两个类具有相同的 XML 类型名称“objectFactory”。
We have seen several posts in SO with the same error but applying to the generated types, not to the object factory. We think that JAXB may not be identifying the ObjectFactory class as an object factory but as a datatype.
我们在 SO 中看到了几篇帖子,但都出现了相同的错误,但适用于生成的类型,而不是对象工厂。我们认为 JAXB 可能不会将 ObjectFactory 类标识为对象工厂,而是将其标识为数据类型。
One possibility was that we were using the internal version of JAXB in Java 6, so we decided to use the System Property -Djava.endorsed.dirsand put the three jars (jaxb-api-2.2.4.jar, jaxb-impl-2.2.4.jar and jaxb-xjc-2.2.4.jar) in that path, but still not working.
一种可能性是我们在 Java 6 中使用了 JAXB 的内部版本,因此我们决定使用系统属性-Djava.endorsed.dirs并将三个 jar(jaxb-api-2.2.4.jar、jaxb-impl- 2.2.4.jar 和 jaxb-xjc-2.2.4.jar)在该路径中,但仍然无法正常工作。
We think that the problem might be that we are using a different version of JAXB in the OSGi runtime and in the build process, so the generated code is not compatible. But maybe we are wrong and there is another problem.
我们认为问题可能在于我们在 OSGi 运行时和构建过程中使用了不同版本的 JAXB,因此生成的代码不兼容。但也许我们错了,还有另一个问题。
Do you have any ideas?
你有什么想法?
Thanks in advance.
提前致谢。
(Edit: more details on this)
(编辑:有关此的更多详细信息)
We create the JAXBContext in this way:
我们以这种方式创建 JAXBContext:
ClassLoader classLoader = new JAXBServiceClassLoader(getParentClassLoader(),
Collections.unmodifiableMap(objectFactories));
context = JAXBContext.newInstance(contextPath.toString(), classLoader);
where contextPath is a String that contains all our object factories separated by ':', and the JAXBServiceClassLoader is:
其中 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;
}
}
(Edit: after Aaron's post)
(编辑:在亚伦的帖子之后)
I've been debugging all the internals of JAXBContextImpl and the thing is that the JAXBContextImpl is trying to get the type info from our ObjectFactory classes, which is wrong. In fact, in com.sun.xml.internal.bind.v2.model.impl.ModelBuilder:314, the getClassAnnotation() call returns null but when I see the instance I can see the annotation XmlRegistry.
我一直在调试 JAXBContextImpl 的所有内部结构,问题是 JAXBContextImpl 试图从我们的 ObjectFactory 类中获取类型信息,这是错误的。实际上,在 com.sun.xml.internal.bind.v2.model.impl.ModelBuilder:314 中,getClassAnnotation() 调用返回 null,但是当我看到实例时,我可以看到注释 XmlRegistry。
The thing is that, at that point XmlRegistry.class.getClassLoader() returns null, but if I run ((Class)c).getAnnotations()[0].annotationType().getClassLoader() it returns the classLoader of the OSGi bundle "lib.jaxb" that contains my JAXB jars, which is correct.
问题是,此时 XmlRegistry.class.getClassLoader() 返回 null,但如果我运行 ((Class)c).getAnnotations()[0].annotationType().getClassLoader() 它返回 OSGi 的 classLoader捆绑包含我的 JAXB jar 的“lib.jaxb”,这是正确的。
So, I guess that we are loading at the same time two different versions of XmlRegistry, one from the JDK and the other one from JAXB 2.2.4 jars. The question is: why?
所以,我猜我们同时加载了两个不同版本的 XmlRegistry,一个来自 JDK,另一个来自 JAXB 2.2.4 jar。问题是:为什么?
And, even more, instead of loading all those com.sun.xml.internal.* classes (like JAXBContextImpl), shouldn't be loading and executing com.sun.xml.bind.v2.runtime.JAXBContextImpl from JAXB jars? During the debug process I can see that it's doing some stuff with reflection but I don't understand why is doing that.
而且,更重要的是,不应该从 JAXB jar 加载和执行 com.sun.xml.bind.v2.runtime.JAXBContextImpl,而不是加载所有那些 com.sun.xml.internal.* 类(如 JAXBContextImpl)?在调试过程中,我可以看到它正在用反射做一些事情,但我不明白为什么要这样做。
采纳答案by Denian
We finally found a solution for this.
我们终于找到了解决方案。
From the JAXB documentation (Discovery of JAXB implementationsection):
从 JAXB 文档(发现 JAXB 实现部分):
http://jaxb.java.net/nonav/2.2.4-1/docs/api/javax/xml/bind/JAXBContext.html
http://jaxb.java.net/nonav/2.2.4-1/docs/api/javax/xml/bind/JAXBContext.html
We tried to add a resource in META-INF/services/javax.xml.bind.JAXBContextin order to enforce the use of com.sun.xml.bind.v2.ContextFactoryinstead of Sun's internal factory. That didn't work, probably because we are using an OSGi bundle.
我们尝试在META-INF/services/javax.xml.bind.JAXBContext中添加一个资源,以强制使用com.sun.xml.bind.v2.ContextFactory而不是 Sun 的内部工厂。这不起作用,可能是因为我们使用的是 OSGi 包。
Anyway, as we are using our own classloader, we override the getResourceAsStream() method, that is called from ContextFinder:343:
无论如何,当我们使用我们自己的类加载器时,我们覆盖了从ContextFinder:343调用的 getResourceAsStream() 方法:
@Override
public InputStream getResourceAsStream(String name)
{
if (name!=null && name.equals("META-INF/services/javax.xml.bind.JAXBContext"))
{
return new ByteArrayInputStream("com.sun.xml.bind.v2.ContextFactory".getBytes());
}
return super.getResourceAsStream(name);
}
This is not the prettiest solution but it works for us. And that classloader is used only when we create the JAXBContext, it should be fine.
这不是最漂亮的解决方案,但它对我们有用。并且该类加载器仅在我们创建 JAXBContext 时使用,应该没问题。
回答by Aaron Digulla
Make sure that there is only one
@XmlRegistry
annotation in your classpath (Search forXmlRegistry.class
file, not usage). Maybe the wrong annotation is picked up.If that doesn't work, create your own classloader which sees only one factory. That should not be necessary but who knows.
Try to set a breakpoint at JAXBContextImpl.java:436 to see which types it processes and why.
确保
@XmlRegistry
您的类路径中只有一个注释(搜索XmlRegistry.class
文件,而不是用法)。也许错误的注释被拾取。如果这不起作用,请创建您自己的类加载器,它只能看到一个工厂。这不应该是必要的,但谁知道呢。
尝试在 JAXBContextImpl.java:436 处设置断点以查看它处理的类型以及原因。
回答by Matthias B
I had the same problem, but a different cause. Even if it might not fix the authors problems I post this answer for all those, reading this post later on and having the same issue as me.
我遇到了同样的问题,但原因不同。即使它可能无法解决作者的问题,我也会为所有这些问题发布此答案,稍后阅读这篇文章并遇到与我相同的问题。
I used this compiler-plugin configuration, which excluded package-info.java files from compilation. After removing the excludes everything worked like a charm! It seems that JAXB include some important definitions in these files!
我使用了这个编译器插件配置,它从编译中排除了 package-info.java 文件。删除排除后,一切都像魅力一样!JAXB 似乎在这些文件中包含了一些重要的定义!
Broken Config:
损坏的配置:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<excludes>
<exclude>**/package-info.java</exclude>
</excludes>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<fork>false</fork>
</configuration>
</plugin>
Working Config:
工作配置:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<fork>false</fork>
</configuration>
</plugin>
回答by Nat Kidder
I had a similar issue when trying to deploy a spring-based soap web service. I added a package to the contextPaths
of a org.springframework.oxm.jaxb.Jaxb2Marshaller
spring bean. The problem was that the same class was in other packages included in the same contextPaths
. I changed the Ant build script to exclude those other classes from the package I was adding, that that resolved the issue.
我在尝试部署基于 spring 的soap Web 服务时遇到了类似的问题。我contextPaths
在org.springframework.oxm.jaxb.Jaxb2Marshaller
spring bean 中添加了一个包。问题是同一个类在同一个contextPaths
. 我更改了 Ant 构建脚本以从我添加的包中排除那些其他类,这解决了问题。