Java 无法将类型编组为 XML 元素,因为缺少 @XmlRootElement 注释

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

Unable to marshal type as XML element because @XmlRootElement annotation is missing

javaxmljaxbmarshalling

提问by nazar_art

I want to marshal object to XML.

我想将对象编组为 XML。

However, it fails with exception:

但是,它失败了:

javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.SAXException2: unable to marshal type "FreightOfferDetail" as an element because it is missing an @XmlRootElement annotation]
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:331)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:257)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:96)
    at com.wktransportservices.fx.test.util.jaxb.xmltransformer.ObjectTransformer.toXML(ObjectTransformer.java:27)
    at com.wktransportservices.fx.test.sampler.webservice.connect.FreightOfferToConnectFreight.runTest(FreightOfferToConnectFreight.java:59)
    at org.apache.jmeter.protocol.java.sampler.JavaSampler.sample(JavaSampler.java:191)
    at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:429)
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:257)
    at java.lang.Thread.run(Thread.java:662)
Caused by: com.sun.istack.SAXException2: unable to marshal type "FreightOfferDetail" as an element because it is missing an @XmlRootElement annotation
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:244)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:303)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:490)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:328)

In fact, this annotation is present (for parent and delivered class):

事实上,这个注解是存在的(对于父类和交付类):

@XmlRootElement(name = "Freight_Offer")
@XmlAccessorType(XmlAccessType.FIELD)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class FreightOffer {
    @JsonIgnore
    @XmlTransient
    private String freightId;
    private String id;

    private String externalSystemId;

    private AddressLocation pickUp;

    private AddressLocation delivery;

    private FreightDescription freightDescription;

    private ListContacts contacts;

    private Customer customer;

    private ListSla slas;

    private String pushId;

    private CompanyProfile company;

    private Route route;

    private String href;

    private Lifecycle lifecycle;

    private Visibility visibility;

    private Boolean unfoldedVXMatching;
    // getters / setters

Child class:

儿童班:

@XmlAccessorType(XmlAccessType.PROPERTY)
public class FreightOfferDetail extends FreightOffer {

    private List<Contact> contact;

    @XmlElement(name = "contacts")
    @JsonProperty("contacts")
    public List<Contact> getContact() {
        return contact;
    }

    public void setContact(List<Contact> contact) {
        this.contact = contact;
    }

It fails exactly at this method toXML():

它完全失败了这种方法toXML()

public class ObjectTransformer<T> implements Transformer<T> {

    protected final JAXBContext context;
    protected final Marshaller marshaller;

    protected final int okStatusCode = 200;
    protected final String okSubErrorCode = "OK";

    public ObjectTransformer(JAXBContext context) throws JAXBException {
        this.context = context;
        marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.encoding", "UTF-8");
        marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
    }

    public String toXML(T object) throws JAXBException {
        StringWriter writer = new StringWriter();
        marshaller.marshal(object, writer);
        String xmlOffer = writer.toString();
        return xmlOffer;
    }

It should work, but it shouldn't.

它应该工作,但它不应该。

I couldn't find what is missed or wrong here.

我在这里找不到遗漏或错误的内容。

UPDATE:

更新:

Here is snippet from test:

这是测试的片段:

public SampleResult runTest(JavaSamplerContext context) {
    AbstractSamplerResults results = new XMLSamplerResults(new SampleResult());
    results.startAndPauseSampler();

    if (failureCause != null) {
        results.setExceptionFailure("FAILED TO INSTANTIATE connectTransformer", failureCause);
    } else {
        FreightOfferDTO offer = null;
        FreightOffer freightOffer = null;
        try {
            results.resumeSampler();            

            RouteInfo routeDTO = SamplerUtils.getRandomRouteFromRepo(context.getIntParameter(ROUTES_TOUSE_KEY));

            offer = FreightProvider.createRandomFreight(routeDTO, createUserWithLoginOnly(context));

            freightOffer = connectTransformer.fromDTO(offer);
            String xmlOfferString = connectTransformer.toXML(freightOffer); // <- it fails here.

I take the date from CSVfile and converting to DTOobject. This method returns to me FreightOfferDetail.

我从CSV文件中获取日期并转换为DTO对象。这个方法返回给我 FreightOfferDetail.

Here is snippet from this method:

这是此方法的片段:

public FreightOfferDetail freightFromDTO(FreightOfferDTO freightDTO, boolean fullFormat){
    FreightOfferDetail freight = new FreightOfferDetail();

    freight.setFreightId(freightDTO.getIds().getAtosId());
    freight.setId(freightDTO.getIds().getFxId());
    // ...

How to marshal object to XML file, at this case?

在这种情况下,如何将对象编组到 XML 文件?

采纳答案by Alain Van Hout

Note that the error message talks about FreightOfferDetail, not FreightOffer.

请注意,错误消息谈论的是FreightOfferDetail,而不是FreightOffer

Based on that, I would expect that somewhere (outside the provided code), you're asking a Detail to be marshalled.

基于此,我希望在某个地方(在提供的代码之外),您要求对 Detail 进行编组。

If you want to be able to do that (with JAXB?) you need to annotate that class as well with the XmlRootElementannotation.

如果您希望能够做到这一点(使用JAXB?),您还需要使用XmlRootElement注释对该类进行注释。

回答by Lazar Lazarov

public String toXML(T object) throws JAXBException {
  StringWriter stringWriter = new StringWriter();

  JAXBContext jaxbContext = JAXBContext.newInstance(T.class);
  Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

  // format the XML output
  jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

  QName qName = new QName("com.yourModel.t", "object");
  JAXBElement<T> root = new JAXBElement<Bbb>(qName, T.class, object);

  jaxbMarshaller.marshal(root, stringWriter);

  String result = stringWriter.toString();
  LOGGER.info(result);
  return result;
}

Here is the article I use when I have to marshal/unmarshal without @XmlRootElement: http://www.source4code.info/2013/07/jaxb-marshal-unmarshal-with-missing.html

这是我在没有 @XmlRootElement 的情况下必须编组/解组时使用的文章:http: //www.source4code.info/2013/07/jaxb-marshal-unmarshal-with-missing.html

All the best hope it helps :)

所有最好的希望它有帮助:)

回答by prasadg

You can use the ObjectFactoryclass to workaround for the classes which doesn't have the @XmlRootElement. ObjectFactory has overloaded methods.

您可以使用ObjectFactory类来解决没有@XmlRootElement 的类。ObjectFactory 有重载的方法。

Method:1It does simple creation of the object and

方法:1它做对象的简单创建和

Method:2It will wrap the object with @JAXBElement.

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

Always to use Method:2to avoid javax.xml.bind.MarshalException - with linked exception missing an @XmlRootElement annotation

始终使用方法:2以避免 javax.xml.bind.MarshalException - 链接异常缺少 @XmlRootElement 注释

Method:1

方法:1

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

Method:2

方法:2

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

for more information follow this stackoverflow-question

有关更多信息,请关注此 stackoverflow-question

Hope this will be helpful...

希望这会有所帮助...

回答by duffy356

When creating the Java-Objects from the WSDL with the apache-cxf maven-plugin, using sth. like:

当使用 apache-cxf maven-plugin 从 WSDL 创建 Java 对象时,使用 sth. 喜欢:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    ...
</plugin> 

There will be a automatically generated ObjectFactory.

会有一个自动生成的ObjectFactory。

When configuring your Exception in Java you can use this generated ObjectFactory for returning the fault. The important step is to return a JAXBElement<YourSoapFault>in the getFaultInfo() method of your exception.

在 Java 中配置您的 Exception 时,您可以使用此生成的 ObjectFactory 来返回错误。重要的一步是JAXBElement<YourSoapFault>在异常的 getFaultInfo() 方法中返回一个。

@WebFault(name = "YourSoapFault",
        targetNamespace = "ns://somenamespace")
public class SomeWebServiceException extends RuntimeException {
    private final YourSoapFault fault;

    public SomeWebServiceException(String message, YourSoapFault fault) {
        super(message);
        this.fault = fault;
    }

    public SomeWebServiceException(String message, YourSoapFault fault, Throwable e) {
        super(message, e);
        this.fault = fault;
    }

    public JAXBElement<YourSoapFault> getFaultInfo() {
        return new ObjectFactory().createYourSoapFault(fault);
    }

}