Search code examples
javasoapjaxbspring-ws

SOAP fault cannot be unmarshalled


My problem is that the values in a SOAP fault are not unmarshalled correctly. The following is the SOAP FAULT string:

Source faultPayload = new StringSource("<SOAP-ENV:Fault xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:v1=\"http://domain/schema/common/fault\">"
                + "<faultcode>SOAP-ENV:Server</faultcode>"
                + "<faultstring xml:lang=\"en\">fault</faultstring>"
                + "<detail>"
                + "<v1:ExceptionInfoType>"
                + "<v1:TransactionId>655655455</v1:TransactionId>"
                + "<v1:ErrorCode>4</v1:ErrorCode>"
                + "<v1:Description>bla</v1:Description>"
                + "</v1:ExceptionInfoType>"
                + "</detail>"
                + "</SOAP-ENV:Fault>");

Here comes the unmarshalling code but the object exceptionInfo (ExceptionInfoType) has not the values/attributes mapped correctly:

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
SoapFaultDetail faultDetail = saajSoapMessage.getSoapBody().getFault().getFaultDetail();
Iterator<SoapFaultDetailElement> iterator = faultDetail.getDetailEntries();
if (iterator.hasNext()) {
     SoapFaultDetailElement detailElement = iterator.next();
     JAXBElement<ExceptionInfoType> exceptionElement = unmarshaller.unmarshal(detailElement.getSource(),ExceptionInfoType.class);
     ExceptionInfoType exceptionInfo = exceptionElement.getValue();
     ThreadContext.put("transactionId", String.valueOf(exceptionInfo.getTransactionId()));
     throw new IOException(BigExceptionHelper.createException(exceptionInfo.getErrorCode(),
                        exceptionInfo.getDescription()));
}

Below is the object's class in which the soap should be unmarshalled but it fails or to be more precise the attribute values are not set:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExceptionInfoType", propOrder = {
    "transactionId",
    "errorCode",
    "description"
})
@XmlSeeAlso({
    ExceptionType.class,
    AuthenticationExceptionType.class,
    AccessDeniedExceptionType.class,
    IllegalArgumentExceptionType.class
})
public class ExceptionInfoType {

    @XmlElement(name = "TransactionId")
    protected int transactionId;
    @XmlElement(name = "ErrorCode", required = true)
    protected BigInteger errorCode;
    @XmlElement(name = "Description", required = true)
    protected String description;
...
}

Do you have an idea why the attributes TransactionId, ErrorCode and Description could not have been set correctly? What is wrong with the SOAP Fault String?


Solution

  • I've found the answer and now the object is rendered correctly. The namespace must be 100% the right one. After I have taken the targetNamespace from the XSD as the namespace here the unmarshalling works as expected. That means the SOAP fault should look like this:

    <SOAP-ENV:Fault xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
      <faultcode>SOAP-ENV:Server</faultcode>
      <faultstring xml:lang="en">fault</faultstring>
      <detail>
        <ExceptionInfoType xmlns="http://webservice-provider.de/BIG_V1.2">
            <ErrorCode>4</ErrorCode>
            <Description>The BIC is invalid</Description>
        </ExceptionInfoType>
      </detail>
    </SOAP-ENV:Fault>
    

    This, namely xmlns="http://webservice-provider.de/BIG_V1.2" makes the difference.