【问题标题】:Unable to marshal type as XML element because @XmlRootElement annotation is missing无法将类型编组为 XML 元素,因为缺少 @XmlRootElement 注释
【发布时间】:2016-08-31 05:23:39
【问题描述】:

我想将对象编组为 XML。

但是,它失败并出现异常:

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)

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

@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

儿童班:

@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;
    }

这个方法完全失败了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;
    }

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

我在这里找不到遗漏或错误的地方。

更新:

这是来自测试的 sn-p:

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.

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

这里是这个方法的sn-p:

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

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

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

【问题讨论】:

    标签: java xml jaxb marshalling


    【解决方案1】:
    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;
    }
    

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

    希望它有所帮助:)

    【讨论】:

      【解决方案2】:

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

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

      会有一个自动生成的ObjectFactory。

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

      @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);
          }
      
      }
      

      【讨论】:

      • 在那个项目中,我们不得不使用 ant 作为构建工具。我的主要目标是将对象编组为 XML,而不是包装错误消息。我有来自控制台的异常堆栈跟踪。
      【解决方案3】:

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

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

      Method:2 它将用 @JAXBElement 包裹对象。

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

      方法:1

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

      方法:2

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

      更多信息请关注stackoverflow-question

      希望这会有所帮助...

      【讨论】:

        【解决方案4】:

        请注意,错误消息是关于FreightOfferDetail,而不是FreightOffer

        基于此,我希望在某个地方(在提供的代码之外),您要求编组一个详细信息。

        如果您希望能够做到这一点(使用 JAXB?),您还需要使用 XmlRootElement em> 注释。

        【讨论】:

        • 我尝试了你的建议。结果是一样的 - javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2 ...
        • 能否包含整个堆栈跟踪?没有附带的异常消息,异常类型并没有说太多。实际的编组调用将有助于缩小范围(即实际编组的对象类型是什么?)。
        • 查看问题。它正好包含这个异常。
        • 好的,我只是在问,因为在最初的问题中,您似乎没有注意到异常并未引用您指出确实具有该注释的类。
        • sn-p 不包含实际的 toXml() 调用,并且 Detail 类包含 List 字段。该字段是否使用所需的 XML 注释进行了注释?根据最初的反馈,您能否更新类定义注释?
        猜你喜欢
        • 2018-05-27
        • 2015-09-22
        • 1970-01-01
        • 2014-08-22
        • 2019-06-25
        • 1970-01-01
        • 1970-01-01
        • 2017-12-05
        • 2019-09-07
        相关资源
        最近更新 更多