I am using JAXB to parse xml elements from the SOAP response. I have defined POJO classes for the xml elements. I have tested pojo classes without namespace and prefix its working fine .Though when i am trying to parse with namespaces and prefix facing the following exception.Requirement is to parse the input from SOAPMessage Object
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
Tried to fix by creating @XMLSchema for the package in package-info.java and located this file in package folder.Can any one guide me to move forward?
Referred this posts but didn help me .
EDITED :XMLSchema
@javax.xml.bind.annotation.XmlSchema (
xmlns = { @javax.xml.bind.annotation.XmlNs(prefix = "env",
namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
Thanks in advance
In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.
This exception indicates that an error has occurred while performing an unmarshal operation that prevents the JAXB Provider from completing the operation. The ValidationEventHandler can cause this exception to be thrown during the unmarshal operations.
This can be done without modifying the generated JAXB code using standard SOAPMessage class. I wrote about this here and here
It's a little fiddly but works correctly.
Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());
String example =
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
Here is how you can handle your use cae:
Envelope
Elementpackage-info
Typically you would use the @XmlSchema
as follows. Using the namespace
and elementFormDefault
properties like I've done means that all data mapped to XML elements unless otherwise mapped will belong to the http://www.xxxx.com/ncp/oomr/dto/
namespace. The information specified in xmlns
is for XML schema generation altough some JAXB implementations use this to determine the preferred prefix for a namespace when marshalling (see: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
@XmlSchema (
namespace="http://www.xxxx.com/ncp/oomr/dto/",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
import javax.xml.bind.annotation.*;
Envelope
If within the com.one.two
you need to map to elements from a namespace other than http://www.xxxx.com/ncp/oomr/dto/
then you need to specify it in the @XmlRootElement
and @XmlElement
annotations.
package com.one.two;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
@XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
}
For More Information
You can use a StAX parser to parse the message and advance to the payload portion and unmarshal from there:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("return")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
xsr.close();
}
}
For More Information
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With