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
Unable to marshal type as XML element because @XmlRootElement annotation is missing
提问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);
}
}