Java JAXB 没有生成 @XmlRootElement

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/819720/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:51:56  来源:igfitidea点击:

No @XmlRootElement generated by JAXB

javajaxbxjcfpml

提问by robinr

I'm trying to generate Java classes from the FpML (Finanial Products Markup Language) version 4.5. A ton of code is generated, but I cannot use it. Trying to serialize a simple document I get this:

我正在尝试从 FpML(金融产品标记语言)4.5 版生成 Java 类。生成了大量代码,但我无法使用它。尝试序列化一个简单的文档,我得到了这个:

javax.xml.bind.MarshalException
  - with linked exception: [com.sun.istack.SAXException2: unable
  to marshal type
  "org.fpml._2008.fpml_4_5.PositionReport"
  as an element because it is missing an
  @XmlRootElement annotation]

In fact noclassses have the @XmlRootElement annotation, so what can I be doing wrong?. I'm pointing xjc (JAXB 2.1) to fpml-main-4-5.xsd, which then includes all types.

事实上,没有任何类具有 @XmlRootElement 注释,那么我做错了什么?。我将 xjc (JAXB 2.1) 指向 fpml-main-4-5.xsd,然后包含所有类型。

采纳答案by skaffman

To tie together what others have already stated or hinted at, the rules by which JAXB XJC decides whether or not to put the @XmlRootElementannotation on a generated class are non trivial (see this article).

为了将其他人已经陈述或暗示的内容联系在一起,JAXB XJC 决定是否将@XmlRootElement注释放在生成的类上的规则非常重要(请参阅本文)。

@XmlRootElementexists because the JAXB runtime requires certain information in order to marshal/unmarshal a given object, specifically the XML element name and namespace. You can't just pass any old object to the Marshaller. @XmlRootElementprovides this information.

@XmlRootElement之所以存在,是因为 JAXB 运行时需要某些信息来编组/解组给定对象,特别是 XML 元素名称和命名空间。您不能将任何旧对象传递给 Marshaller。@XmlRootElement提供此信息。

The annotation is just a convenience, however - JAXB does not require it. The alternative to is to use JAXBElementwrapper objects, which provide the same information as @XmlRootElement, but in the form of an object, rather than an annotation.

注释只是一种方便,但是 - JAXB 不需要它。另一种方法是使用JAXBElement包装对象,它提供与 相同的信息@XmlRootElement,但以对象的形式,而不是注释。

However, JAXBElementobjects are awkward to construct, since you need to know the XML element name and namespace, which business logic usually doesn't.

但是,JAXBElement对象很难构建,因为您需要知道 XML 元素名称和命名空间,而业务逻辑通常不知道。

Thankfully, when XJC generates a class model, it also generates a class called ObjectFactory. This is partly there for backwards compatibility with JAXB v1, but it's also there as a place for XJC to put generated factory methods which create JAXBElementwrappers around your own objects. It handles the XML name and namespace for you, so you don't need to worry about it. You just need to look through the ObjectFactorymethods (and for large schema, there can be hundreds of them) to find the one you need.

值得庆幸的是,当 XJC 生成一个类模型时,它也会生成一个名为ObjectFactory. 这部分是为了与 JAXB v1 向后兼容,但它也是 XJC 放置生成的工厂方法的地方,这些方法JAXBElement在您自己的对象周围创建包装器。它会为您处理 XML 名称和命名空间,因此您无需担心。您只需要查看ObjectFactory方法(对于大型模式,可能有数百个)即可找到您需要的方法。

回答by mcherm

It's not working for us either. But we did find a widely-quoted article that adds SOME background... I'll link to it here for the sake of the next person: http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

它对我们也不起作用。但是我们确实找到了一篇被广泛引用的文章,其中添加了一些背景……为了下一个人,我会在这里链接到它:http: //weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html

回答by Yaqoob

Joe's answer (Joe Jun 26 '09 at 17:26) does it for me. The simple answer is that absence of an @XmlRootElement annotation is no problem if you marshal a JAXBElement. The thing that confused me is the generated ObjectFactory has 2 createMyRootElement methods - the first takes no parameters and gives the unwrapped object, the second takes the unwrapped object and returns it wrapped in a JAXBElement, and marshalling that JAXBElement works fine. Here's the basic code I used (I'm new to this, so apologies if the code's not formatted correctly in this reply), largely cribbed from link text:

Joe 的回答(Joe Jun 26 '09 at 17:26)对我有用。简单的答案是,如果您编组 JAXBElement,则没有 @XmlRootElement 注释是没有问题的。让我感到困惑的是生成的 ObjectFactory 有 2 个 createMyRootElement 方法——第一个没有参数并给出解包的对象,第二个获取解包的对象并返回它包装在 JAXBElement 中,并且编组 JAXBElement 工作正常。这是我使用的基本代码(我是新手,如果此回复中的代码格式不正确,请道歉),主要来自链接文本

ObjectFactory objFactory = new ObjectFactory();
MyRootElement root = objFactory.createMyRootElement();
...
// Set root properties
...
if (!writeDocument(objFactory.createMyRootElement(root), output)) {
    System.err.println("Failed to marshal XML document");
}
...

private boolean writeDocument(JAXBElement document, OutputStream output) {

  Class<?> clazz = document.getValue().getClass();
  try {
    JAXBContext context =
        JAXBContext.newInstance(clazz.getPackage().getName());
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(document, output);
    return true;

  } catch (JAXBException e) {
    e.printStackTrace(System.err);
    return false;
  }
}

回答by Tony

Did you try to change your xsd like this?

你有没有尝试像这样改变你的xsd?

<!-- create-logical-system -->
<xs:element name="methodCall">
  <xs:complexType>
    ...
  </xs:complexType>
</xs:element>

回答by Gurnard

This is mentioned at the bottom of the blog post already linked above but this works like a treat for me:

上面已经链接的博客文章底部提到了这一点,但这对我来说就像一种享受:

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(new JAXBElement<MyClass>(new QName("uri","local"), MyClass.class, myClassInstance), System.out);

回答by Sayantam

@XmlRootElement is not needed for unmarshalling - if one uses the 2 parameter form of Unmarshaller#unmarshall.

解组不需要@XmlRootElement - 如果使用 Unmarshaller#unmarshall 的 2 参数形式。

So, if instead of doing:

所以,如果不是这样做:

UserType user = (UserType) unmarshaller.unmarshal(new StringReader(responseString));

one should do:

一个应该做的:

JAXBElement<UserType> userElement = unmarshaller.unmarshal(someSource, UserType.class);
UserType user = userElement.getValue();

The latter code will not require @XmlRootElement annotation at UserType class level.

后面的代码在 UserType 类级别不需要 @XmlRootElement 注释。

回答by leandruol

To soluction it you should configure a xml binding before to compile with wsimport, setting generateElementProperty as false.

要解决它,您应该在使用 wsimport 编译之前配置一个 xml 绑定,将 generateElementProperty 设置为 false。

     <jaxws:bindings wsdlLocation="LOCATION_OF_WSDL"
      xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
         <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
    <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='NAMESPACE_OF_WSDL']">
      <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xjc:generateElementProperty>false</xjc:generateElementProperty> 
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>

回答by Olivier.Roger

You can fix this issue using the binding from How to generate @XmlRootElement Classes for Base Types in XSD?.

您可以使用How to generate @XmlRootElement Classes for Base Types in XSD? 中的绑定来解决此问题.

Here is an example with Maven

这是 Maven 的示例

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
                <execution>
                    <id>xjc</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaDirectory>src/main/resources/xsd</schemaDirectory>
                <packageName>com.mycompany.schemas</packageName>
                <bindingFiles>bindings.xjb</bindingFiles>
                <extension>true</extension>
            </configuration>
        </plugin>

Here is the binding.xjbfile content

这是binding.xjb文件内容

<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
        <jxb:globalBindings>
            <xjc:simple/>
        </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>

回答by metatechbe

With a Maven build, you can add the @XmlRootElementannotation

使用 Maven 构建,您可以添加@XmlRootElement注释

with the "jaxb2-basics-annotate" plug-in.

与“ jaxb2-basics-annotate”插件。

See more information : see

查看更多信息:见

Configure Maven to generate classes from XML Schema using JAXB

配置 Maven 以使用 JAXB 从 XML 模式生成类

and JAXB XJC code generation

JAXB XJC 代码生成

回答by Matthew Wise

As hinted at in one of the above answers, you won't get an XMLRootElement on your root element if in the XSD its type is defined as a named type, since that named type could be used elsewhere in your XSD. Try mking it an anonymous type, i.e. instead of:

正如上述答案之一所暗示的那样,如果在 XSD 中将其类型定义为命名类型,您将不会在根元素上获得 XMLRootElement,因为该命名类型可以在 XSD 的其他地方使用。尝试将其设为匿名类型,即而不是:

<xsd:element name="myRootElement" type="MyRootElementType" />

<xsd:complexType name="MyRootElementType">
...
</xsd:complexType>

you would have:

你将会拥有:

<xsd:element name="myRootElement">
    <xsd:complexType>
    ...
    <xsd:complexType>
</xsd:element>