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

时间:2016-05-05 12:11:54

标签: java xml jaxb marshalling

我想将对象编组为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;
    }

它应该有效,但它不应该。

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

更新:

以下是来自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.

我从 CSV 文件中取出日期并转换为 DTO 对象。这个方法回到我身边 FreightOfferDetail.

以下是此方法的摘录:

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

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

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

4 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:3)

请注意,错误消息涉及FreightOfferDetail,而不是FreightOffer

基于此,我希望在某个地方(在提供的代码之外),你要求细节被编组。

如果您希望能够这样做(使用 JAXB ?),您还需要使用 XmlRootElement 注释。

答案 2 :(得分:0)

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

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

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

始终使用方法: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

希望这会有所帮助......

答案 3 :(得分:0)

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

#!/bin/bash -l

#SBATCH --qos=regular
#SBATCH --nodes=20
#SBATCH --time=120:00:00
#SBATCH --job-name=sis_model
#SBATCH --array=0-20
#SBATCH --distribution=block

lambda=(0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1)

for paramater in ${lambda[*]}
do
        for ip1 in {0..100}
                do
                        srun ./test ${lambda[$SLURM_ARRAY_TASK_ID]}
                done
done

会有一个自动生成的ObjectFactory。

在Java中配置Exception时,可以使用此生成的ObjectFactory返回错误。重要的步骤是在异常的getFaultInfo()方法中返回<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> ... </plugin>

JAXBElement<YourSoapFault>