简体   繁体   English

两个类具有相同的XML类型名称“objectFactory”

[英]Two classes have the same XML type name “objectFactory”

We have been using JAXB 2.1 for a long time in our system. 我们在系统中长期使用JAXB 2.1。 We have a platform that is built with Ant and generates a bunch of bundles that are deployed in an OSGi runtime. 我们有一个使用Ant构建的平台,并生成一组部署在OSGi运行时中的bundle。 We use Java SE 6. 我们使用Java SE 6。

We use JAXB during the build process to generate datatypes from different schemas. 我们在构建过程中使用JAXB从不同的模式生成数据类型。 Those classes are packaged in the bundles and used in runtime to serialize/deserialize content. 这些类打包在bundle中,并在运行时用于序列化/反序列化内容。 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来从用户提供的其他模式(它是一种MDA平台)生成数据类型。

In the OSGi runtime we have a bundle that has the JAXB jars and exports the necessary packages. 在OSGi运行时,我们有一个包含JAXB jar的bundle并导出必要的包。 We create a JAXBContext instance with the context path of all the object factories generated, so we can marshall/unmarshall all our datatypes. 我们使用生成的所有对象工厂的上下文路径创建一个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. 到目前为止一直在工作,但是现在我们正在尝试升级到JAXB (2.2.4)的最新稳定版本,并且我们在尝试在运行时创建上下文时遇到问题。 We get the following exception: 我们得到以下异常:

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. 我们在SO中看到了几个具有相同错误的帖子,但是应用于生成的类型,而不是对象工厂。 We think that JAXB may not be identifying the ObjectFactory class as an object factory but as a datatype. 我们认为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.dirs and 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的内部版本,因​​此我们决定使用System Property -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. 我们认为问题可能是我们在OSGi运行时和构建过程中使用了不同版本的JAXB,因此生成的代码不兼容。 But maybe we are wrong and there is another problem. 但也许我们错了,还有另一个问题。

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是一个String,它包含以':'分隔的所有对象工厂,而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. 我一直在调试JAXBContextImpl的所有内部,事实是JAXBContextImpl试图从我们的ObjectFactory类中获取类型信息,这是错误的。 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. 实际上,在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. 所以,我想我们正在同时加载两个不同版本的XmlRegistry,一个来自JDK,另一个来自JAXB 2.2.4 jar。 The question is: why? 问题是:为什么?

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? 而且,除了加载所有com.sun.xml.internal。*类(如JAXBContextImpl)之外,不应该从JAXB jar加载和执行com.sun.xml.bind.v2.runtime.JAXBContextImpl? During the debug process I can see that it's doing some stuff with reflection but I don't understand why is doing that. 在调试过程中,我可以看到它正在用反射做一些事情,但我不明白为什么这样做。

We finally found a solution for this. 我们终于找到了解决方案。

From the JAXB documentation ( Discovery of JAXB implementation section): 从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.JAXBContext in order to enforce the use of com.sun.xml.bind.v2.ContextFactory instead of Sun's internal factory. 我们尝试在META-INF / services / javax.xml.bind.JAXBContext中添加资源,以强制使用com.sun.xml.bind.v2.ContextFactory而不是Sun的内部工厂。 That didn't work, probably because we are using an OSGi bundle. 这不起作用,可能是因为我们正在使用OSGi包。

Anyway, as we are using our own classloader, we override the getResourceAsStream() method, that is called from ContextFinder:343 : 无论如何,当我们使用自己的类加载器时,我们覆盖从ContextFinder调用的getResourceAsStream()方法:343

@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时才使用该类加载器,它应该没问题。

  1. Make sure that there is only one @XmlRegistry annotation in your classpath (Search for XmlRegistry.class file, not usage). 确保类路径中只有一个@XmlRegistry注释(搜索XmlRegistry.class文件,而不是用法)。 Maybe the wrong annotation is picked up. 也许拿起了错误的注释。

  2. If that doesn't work, create your own classloader which sees only one factory. 如果这不起作用,创建自己的类加载器,只能看到一个工厂。 That should not be necessary but who knows. 这不应该是必要的,但谁知道。

  3. Try to set a breakpoint at JAXBContextImpl.java:436 to see which types it processes and why. 尝试在JAXBContextImpl.java:436设置断点,以查看它处理的类型和原因。

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. 我使用了这个编译器插件配置,它从编译中排除了package-info.java文件。 After removing the excludes everything worked like a charm! 删除后排除所有工作就像一个魅力! It seems that JAXB include some important definitions in these files! 看来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>

I had a similar issue when trying to deploy a spring-based soap web service. 尝试部署基于Spring的soap Web服务时,我遇到了类似的问题。 I added a package to the contextPaths of a org.springframework.oxm.jaxb.Jaxb2Marshaller spring bean. 我在org.springframework.oxm.jaxb.Jaxb2Marshaller spring bean的contextPaths中添加了一个包。 The problem was that the same class was in other packages included in the same contextPaths . 问题是同一个类在同一个contextPaths包含的其他包contextPaths I changed the Ant build script to exclude those other classes from the package I was adding, that that resolved the issue. 我更改了Ant构建脚本,以从我添加的包中排除那些其他类,从而解决了这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 wsdl2java两个类具有相同的XML类型名称“{http://***.***。$。* * / * / / / / / *}} objectFactory” - wsdl2java Two classes have the same XML type name “{http://***.***.***.***/***/***/***}objectFactory” 两个类具有相同的 XML 类型名称 - Two Classes have same XML type name IllegalAnnotationException:两个类具有相同的 XML 类型名称 - IllegalAnnotationException: Two classes have the same XML type name 使用两个类具有相同的 XML 类型名称 - Use two classes have the same XML type name IllegalAnnotationExceptions:两个类具有相同的XML类型名称。 CXF插件生成的代码 - IllegalAnnotationExceptions: Two classes have the same XML type name. Code generated by CXF plugin java +消费SOAP Web服务+“两个类具有相同的XML类型名称……” - java + Consuming a SOAP web service + “Two classes Have the same XML type name …” 获取 JAXB 异常,例如“两个类具有相同的 XML 类型名称...” - Getting the JAXB exception like "Two classes have the same XML type name..." jaxb2-maven-plugin 在生成 xsd 时忽略命名空间 - 两个类具有相同的 XML 类型 - jaxb2-maven-plugin ignores namespace when generating xsd - Two classes have the same XML type 如何创建两个具有相同名称,签名和返回类型的方法的类,就像它们实现相同的接口一样 - How to make two classes which both have method with the same name, signature and return type behave like they would implement the same interface 我的 Java 应用程序中的两个类具有相同的限定名称 - Two classes in my java app have the same Qualified name
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM