Monday, April 22, 2013

How to Programatically Parse a Custom Web Services SoapFault and Map it to an Object Defined in the WSDL's Schema xsd

Sometimes the server side Web Services provider offers a custom soap fault detail implementation. The client side needs to parse it and map it back into a java object generated from the WSDL/xsd.
For example, an soapFault look likes this with the custom :

<s:Body>
 <s:Fault>
  <faultcode>s:Client</faultcode>
  <faultstring xml:lang="en-US">Operation parameter is invalid.</faultstring>
  <detail>
   <ServerCustomizedError>
    <ErrorMessage>Operation parameter is invalid.</ErrorMessage>
    <Id>56a145c6-a7f3-4069-94a4-6ec945d95613</Id>
    <ParameterName>input</ParameterName>
    <ValidationDetails>
     <Message>Why is this wrong?</Message>
     <Target>wrong value</Target>
     <Key>wrong data</Key>
    </ValidationDetails>
   </ServerCustomizedError>
  </detail>
 </s:Fault>
</s:Body>


The corresponding client side java code to parse the above Soap Fault will look like:
Iterator it = soapFaultClientException.getSoapFault().getFaultDetail().getDetailEntries();
while (it.hasNext())
{
 Source errSource = it.next().getSource();
 @SuppressWarnings("unchecked")
 JAXBElement errJaxb = (JAXBElement) springWebServiceTemplate.getUnmarshaller().unmarshal(errSource);
 ServerCustomizedError err = errJaxb.getValue();
 ....
}

5 comments:

  1. This was good to get me started, but a few things didn't work. This is what I ended up with:

    private void tryThrowCustomException(SoapFaultClientException e) throws MyException {
    try{
    //get the fault details
    Source errSource = ((SoapFaultDetailElement)e.getSoapFault().getFaultDetail().getDetailEntries().next()).getSource();
    Object soapFaultDocImpl = getWebServiceTemplate().getUnmarshaller().unmarshal(errSource);

    if(soapFaultDocImpl instanceof MyFaultDocumentImpl){
    //convert to specific fault class
    MyFaultDocumentImpl MyFaultDocumentImpl = (MyFaultDocumentImpl)soapFaultDocImpl;
    MyFaultType myFaultType = MyFaultDocumentImpl.getMyFault();

    //map to exception
    MyException ex = new MyException(myFaultType.getErrorMessage());
    //MORE MAPPING HERE AS YOU NEED
    throw ex;
    }
    } catch (MyException ex){
    throw ex;
    } catch (Exception ex){
    LOGGER.error("Error converting custom exception", ex);
    }
    }

    ReplyDelete
  2. Thank you, This was great and helpful

    ReplyDelete