我试图从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,然后包括所有类型。


当前回答

为了解决这个问题,你应该在使用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>

其他回答

JAXBElement包装器适用于JAXB没有生成@XmlRootElement的情况。这些包装器在maven-jaxb2-plugin生成的ObjectFactory类中可用。如:

     public class HelloWorldEndpoint {
        @PayloadRoot(namespace = NAMESPACE_URI, localPart = "person")
        @ResponsePayload
        public JAXBElement<Greeting> sayHello(@RequestPayload JAXBElement<Person> request) {

        Person person = request.getValue();

        String greeting = "Hello " + person.getFirstName() + " " + person.getLastName() + "!";

        Greeting greet = new Greeting();
        greet.setGreeting(greeting);

        ObjectFactory factory = new ObjectFactory();
        JAXBElement<Greeting> response = factory.createGreeting(greet);
        return response;
      }
 }

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

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

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

使用“jaxb2-basics- annotation”插件。

查看更多信息:参见

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

和JAXB XJC代码生成

经过两天的努力,我找到了解决问题的办法。您可以使用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();

如您所知,答案是使用ObjectFactory()。下面是一个为我工作的代码示例:)

ObjectFactory myRootFactory = new ObjectFactory();

MyRootType myRootType = myRootFactory.createMyRootType();

try {

        File file = new File("./file.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(MyRoot.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        //output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        JABXElement<MyRootType> myRootElement = myRootFactory.createMyRoot(myRootType);

        jaxbMarshaller.marshal(myRootElement, file);
        jaxbMarshaller.marshal(myRootElement, System.out);

    } catch (JAXBException e) {
        e.printStackTrace();
    }