web-dev-qa-db-fra.com

Impossible de classer le type en tant qu'élément XML, car l'annotation @XmlRootElement est manquante

Je veux marshal objet à XML. 

Cependant, il échoue avec une 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)

En fait, cette annotation est présente (pour les classes parentes et livrées):

@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

Classe enfant:

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

Il échoue exactement à cette méthode 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;
    }

Cela devrait fonctionner, mais cela ne devrait pas. 

Je ne pouvais pas trouver ce qui manque ou ce qui ne va pas ici.

UPDATE:

Voici l'extrait du 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.

Je prends la date deCSVfichier et convertis enDTOobjet. Cette méthode me renvoie FreightOfferDetail.

Voici l'extrait de cette méthode:

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

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

Comment classer un objet dans un fichier XML, dans ce cas?

4
nazar_art

Notez que le message d'erreur parle de FreightOfferDetail, pas FreightOffer.

Sur cette base, je m'attendrais à ce que quelque part (en dehors du code fourni), vous demandez à un détail d'être organisé. 

Si vous voulez pouvoir le faire (avecJAXB?), Vous devez également annoter cette classe avec l'annotation - XmlRootElement .

3
Alain Van Hout
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;
}

Voici l'article que j'utilise lorsque je dois marshal/unmarshal sans @XmlRootElement: http://www.source4code.info/2013/07/jaxb-marshal-unmarshal-with-missing.html

Tout le meilleur espoir que ça aide :)

8
Lazar Lazarov

Vous pouvez utiliser la solution ObjectFactory class pour résoudre les problèmes des classes pour lesquelles le @XmlRootElement . ObjectFactory a surchargé les méthodes. 

Méthode: 1 Il fait une création simple de l'objet et 

Méthode: 2 Il encapsulera l'objet avec @JAXBElement

Toujours utiliser Méthode: 2 pour éviter javax.xml.bind.MarshalException - avec exception liée manquant d'une annotation @XmlRootElement

Méthode: 1  

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

Méthode: 2

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

pour plus d'informations, suivez ceci stackoverflow-question

J'espère que cela vous sera utile ...

0
prasadg

Lors de la création d'objets Java à partir du WSDL avec Apache-cxf maven-plugin, utilisez sth. comme:

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

Il y aura un ObjectFactory généré automatiquement.

Lors de la configuration de votre exception en Java, vous pouvez utiliser cet ObjectFactory généré pour renvoyer l'erreur. L'étape importante consiste à renvoyer un JAXBElement<YourSoapFault> dans la méthode getFaultInfo () de votre exception.

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

}
0
duffy356