I use the wsdl2java
goal of cxf-codegen-plugin
to generate Java from a WSDL. Then, in my tests, I use JAXB.unmarshal() to populate classes from a raw webservice XML result.
A typical example is GetAllResponseType response = unmarshal("get-all.xml", GetAllResponseType.class)
, using the following method:
<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
InputStream body = getClass().getResourceAsStream(filename);
return javax.xml.bind.JAXB.unmarshal(body, clazz);
}
The problem is this: The raw XML response always have enclosing Envelope and Body tags which are not generated as classes by wsdl2java:
<n4:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:n="http://www.informatica.com/wsdl/"
xmlns:n4="http://schemas.xmlsoap.org/soap/envelope/" xmlns:n5="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<n4:Body>
<n:getAllResponse xmlns:n="http://www.informatica.com/wsdl/">
<n:getAllResponseElement>
...
</n:getAllResponseElement>
</n:getAllResponse>
</n4:Body>
</n4:Envelope>
So, in order to use JAXB.unmarshal() I have to
Currently I do 2, but it's a lot of code:
<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
InputStream is = getClass().getResourceAsStream(filename);
InputStream body = nodeContent(is, "n4:Body");
return javax.xml.bind.JAXB.unmarshal(body, clazz);
}
InputStream nodeContent(InputStream is, String name) throws Exception {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(is);
Node node = firstNonTextNode(doc.getElementsByTagName(name).item(0).getChildNodes());
return nodeToStream(node);
}
Node firstNonTextNode(NodeList nl) {
for (int i = 0; i < nl.getLength(); i++) {
if (!(nl.item(i) instanceof Text)) {
return nl.item(i);
}
}
throw new RuntimeException("Couldn't find nontext node");
}
InputStream nodeToStream(Node node) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(node);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
return new ByteArrayInputStream(outputStream.toByteArray());
}
My questions are:
To unmarshal an xml string into a JAXB object, you will need to create an Unmarshaller from the JAXBContext, then call the unmarshal() method with a source/reader and the expected root object.
Unmarshalling is the process of reading XML documents into Java objects. The JAXBContext class provides the client's entry point to the JAXB API. It provides API for marshalling, unmarshalling and validating.
To read XML, first get the JAXBContext . It is entry point to the JAXB API and provides methods to unmarshal, marshal and validate operations. Now get the Unmarshaller instance from JAXBContext . It's unmarshal() method unmarshal XML data from the specified XML and return the resulting content tree.
Use the DOMSource
to pass a Node as input. The following method takes a org.w3c.dom.Node
as input and returns the unmarshalled class.
private <T> T unmarshal(Node node, Class<T> clazz) throws JAXBException {
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
Source xmlSource = new DOMSource(node);
Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
return unmarshaller.unmarshal(xmlSource, clazz).getValue();
}
The node within the n4:Body
node can be unmarshalled by utilizing XMLStreamReader
and the "raw" JAXB Unmarshaller
:
<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(getClass().getResourceAsStream(filename));
xsr.nextTag();
while (!xsr.getLocalName().equals("Body")) {
xsr.nextTag();
}
xsr.nextTag();
Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
return unmarshaller.unmarshal(xsr, clazz).getValue();
}
Thanks to Blaise Doughan for helping on this answer.
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