Reputation: 5797
I'm working with eBay's LMS (Large Merchant Services) and kept running into the error:
org.xml.sax.SAXException:
SimpleDeserializer encountered a child
element, which is NOT expected, in
something it was trying to
deserialize.
After a lot of trial and error I traced the problem down. It turns out this works:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
While this (what I've been sending) doesn't:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest>
The difference is the XML namespace attribute on the AddFixedPriceItemRequest
. All of my XML is currently being marshalled via JAXB and I'm not sure what is the best way to go about adding a second xmlns attribute to a different element in my file.
So that's the question. How do I add an xmlns attribute to another element in JAXB?
package ebay.apis.eblbasecomponents;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
extends AbstractRequestType
{
@XmlElement(name = "Item")
protected ItemType item;
public ItemType getItem() {
return item;
}
public void setItem(ItemType value) {
this.item = value;
}
}
Added class definition by request.
Edited the above class like so to no effect:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "urn:ebay:apis:eBLBaseComponents",
name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
Here is a snippet of the BulkDataExchangeRequestsType
class. I tried throwing a namespace="urn:ebay:apis:eBLBaseComponents"
into the @XmlElement
for AddFixedPriceItemRequest
but it didn't do anything.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BulkDataExchangeRequestsType", propOrder = {
"header",
"addFixedPriceItemRequest"
})
public class BulkDataExchangeRequestsType {
@XmlElement(name = "Header")
protected MerchantDataRequestHeaderType header;
@XmlElement(name = "AddFixedPriceItemRequest")
protected List<AddFixedPriceItemRequestType> addFixedPriceItemRequest;
Upvotes: 8
Views: 45309
Reputation: 21
Check if the fields in a generated classed are missing the @XmlElement
annotation and if present are they missing the namespace attribute. These two must be present in order to get the namespace prefix against every element in your marshaled xml.
Upvotes: 4
Reputation: 403601
As far as I can tell, your XML fragments are semantically identical. The xmlns
attribute on the AddFixedPriceItemRequest
element is redundant, since it implicitly inherits the namespace of its parent element. JAXB knows this, and so doesn't bother adding the namespace to AddFixedPriceItemRequest
- it's just not necessary.
If the ebay server is only working when the AddFixedPriceItemRequest
xmlns
is present, then it's broken, and is making demands on the input over and above those required by XML and by the schema. If this is indeed the case (which is hard to believe, but possible), then using a Java XML document model like JAXB is going to be a struggle, since that will assume XML is XML is XML. Low-level farting about with which elements get the xmlns
declarations is not exposed to the API, since it shouldn't be needed.
None of which is helping you. My approach would be to marshal the JAXB model to a DOM object (using a DOMResult
passed to the Marshaller
), and then see if you can do some manual tweaking of the DOM to force the xmlns
into the document at the appropriate places. You can then serialize that DOM to XML and send that.
You shouldn't have to do this, and I suspect you may be doing something else wrong somewhere; this is more likely than the ebay web service being broken like this.
edit: here's another suggestion, a bit less awful than the JAXB-to-DOM-to-XML solution. If your request XML is reasonable static in structure, with only the numeric/string values changing, then define it as a String template, then replace the values at runtime, and send that. You can then interpret the results using JAXB. I've done this in the oast with web services thyat required very exact namespace prefixes, when persuading the java XML libraries to conform to that was unreasonably hard.
Upvotes: 6
Reputation: 59932
Try to use class annotation
@XmlType(namespace="urn:ebay:apis:eBLBaseComponents")
or
@XmlElement(namespace="urn:ebay:apis:eBLBaseComponents")
property annotation if you only want to specify namespace only in some certain cases
Upvotes: 5