Hi,
i have built the Webservice client with Java 1.7 (JAX-WS). The namespace for the AXLError class is set to "http://www.cisco.com/AXL/API/10.5". This is defind in the AXL Schema file.
When i call a function on the client with dummy parameters to test the AXLError, i never get an AXLError. It throws always a SOAPFaultException.
The analysis of the result is showing no namespaces for the detail section. So JAX-B never maps the fault to the correct object class.
Is that an error ?
Example:
Input:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/10.5">
<soapenv:Header/>
<soapenv:Body>
<ns:getUser sequence="1">
<userid>asdfg</userid>
</ns:getUser>
</soapenv:Body>
</soapenv:Envelope>
Return:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>Item not valid: The specified User was not found</faultstring>
<detail>
<axlError>
<axlcode>5007</axlcode>
<axlmessage>Item not valid: The specified User was not found</axlmessage>
<request>getUser</request>
</axlError>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
My solution is writing a SOAPMessageHandler which corrects the namespaces on all AXLErrors.
class CiscoAXLErrorHandler implements SOAPHandler<SOAPMessageContext> {
public CiscoAXLErrorHandler() {
}
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
//ntohing to do
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
//find AXLError in SoapFaultDetail...
try {
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope env = soapMsg.getSOAPPart().getEnvelope();
env.addNamespaceDeclaration("ns1", "http://www.cisco.com/AXL/API/10.5");
Node n = soapMsg.getSOAPBody().getFault().getDetail().getFirstChild();
if(n.getNodeName().equals("axlError")){
SOAPElement newAXLError = soapMsg.getSOAPBody().getFault().getDetail().addChildElement(
env.createName("axlError", "ns1", "http://www.cisco.com/AXL/API/10.5"));
soapMsg.getSOAPBody().getFault().getDetail().removeChild(n);
NodeList nl = n.getChildNodes();
for(int i =0; i<nl.getLength();i++){
SOAPElement child = newAXLError.addChildElement(nl.item(i).getNodeName());
child.setTextContent(nl.item(i).getTextContent());
}
soapMsg.saveChanges();
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMsg.writeTo(out);
String xml = new String(out.toByteArray());
out.close();
Logger.getLogger(CiscoAXLErrorHandler.class.getName()).log(Level.INFO, "######################\r\n"
+ xml +"\r\n"
+ "######################");
}
} catch (SOAPException ex) {
Logger.getLogger(CiscoAXLErrorHandler.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CiscoAXLErrorHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
@Override
public void close(MessageContext context) {
//nothing to clean up
}
}
Best regards
Mathias