我试图从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]

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


当前回答

经过两天的努力,我找到了解决问题的办法。您可以使用ObjectFactory类来解决没有@XmlRootElement的类。ObjectFactory重载了一些方法来将其包装在JAXBElement周围。

方法:1简单地创建对象。

方法:2将使用@JAXBElement包装对象。

总是使用Method:2来避免javax.xml.bind.MarshalException -与链接异常缺少@XmlRootElement注释。

请查看下面的示例代码

方法:1简单地创建对象

public GetCountry createGetCountry() {
        return new GetCountry();
    }

方法:2将使用@JAXBElement包装对象。

 @XmlElementDecl(namespace = "my/name/space", name = "getCountry")
 public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
        return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
    }

工作代码示例:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
WebServiceTemplate springWSTemplate = context.getBean(WebServiceTemplate.class);

GetCountry request = new GetCountry();
request.setGuid("test_guid");

JAXBElement<GetCountryResponse> jaxbResponse = (JAXBElement<GetCountryResponse>)springWSTemplate .marshalSendAndReceive(new ObjectFactory().createGetCountry(request));

GetCountryResponse response = jaxbResponse.getValue();

其他回答

您可以使用如何在XSD中为基类型生成@XmlRootElement类中的绑定来修复此问题。

下面是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>

这是装订。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>

你试过这样改变你的xsd吗?

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

这对我们也没用。但我们确实找到了一篇被广泛引用的文章,增加了一些背景……我将在这里链接到它,以方便下一个人:http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

正如上面的答案之一所暗示的,如果在XSD中根元素的类型定义为命名类型,则根元素上不会有XMLRootElement,因为该命名类型可以在XSD中的其他地方使用。尝试将其转换为匿名类型,即:

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

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

你会:

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

经过两天的努力,我找到了解决问题的办法。您可以使用ObjectFactory类来解决没有@XmlRootElement的类。ObjectFactory重载了一些方法来将其包装在JAXBElement周围。

方法:1简单地创建对象。

方法:2将使用@JAXBElement包装对象。

总是使用Method:2来避免javax.xml.bind.MarshalException -与链接异常缺少@XmlRootElement注释。

请查看下面的示例代码

方法:1简单地创建对象

public GetCountry createGetCountry() {
        return new GetCountry();
    }

方法:2将使用@JAXBElement包装对象。

 @XmlElementDecl(namespace = "my/name/space", name = "getCountry")
 public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
        return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
    }

工作代码示例:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
WebServiceTemplate springWSTemplate = context.getBean(WebServiceTemplate.class);

GetCountry request = new GetCountry();
request.setGuid("test_guid");

JAXBElement<GetCountryResponse> jaxbResponse = (JAXBElement<GetCountryResponse>)springWSTemplate .marshalSendAndReceive(new ObjectFactory().createGetCountry(request));

GetCountryResponse response = jaxbResponse.getValue();