@Override
  public Object decode(Response response, Type type) throws IOException {
    if (response.status() == 404) return Util.emptyValueOf(type);
    if (response.body() == null) return null;
    while (type instanceof ParameterizedType) {
      ParameterizedType ptype = (ParameterizedType) type;
      type = ptype.getRawType();
    }
    if (!(type instanceof Class)) {
      throw new UnsupportedOperationException(
          "SOAP only supports decoding raw types. Found " + type);
    }

    try {
      SOAPMessage message =
          MessageFactory.newInstance(soapProtocol)
              .createMessage(null, response.body().asInputStream());
      if (message.getSOAPBody() != null) {
        if (message.getSOAPBody().hasFault()) {
          throw new SOAPFaultException(message.getSOAPBody().getFault());
        }

        Unmarshaller unmarshaller = jaxbContextFactory.createUnmarshaller((Class<?>) type);

        if (this.useFirstChild) {
          return unmarshaller.unmarshal(message.getSOAPBody().getFirstChild());
        } else {
          return unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
        }
      }
    } catch (SOAPException | JAXBException e) {
      throw new DecodeException(response.status(), e.toString(), response.request(), e);
    } finally {
      if (response.body() != null) {
        response.body().close();
      }
    }
    return Util.emptyValueOf(type);
  }
Decodes SOAP responses using SOAPMessage and JAXB for the body part. <br>

<p>The JAXBContextFactory should be reused across requests as it caches the created JAXB
contexts.

<p>A SOAP Fault can be returned with a 200 HTTP code. Hence, faults could be handled with no
error on the HTTP layer. In this case, you'll certainly have to catch {@link SOAPFaultException}
to get fault from your API client service. In the other case (Faults are returned with 4xx or 5xx
HTTP error code), you may use {@link SOAPErrorDecoder} in your API configuration.

<pre>

public interface MyApi {

   &#64;RequestLine("POST /getObject")
   &#64;Headers({
     "SOAPAction: getObject",
     "Content-Type: text/xml"
   })
   MyJaxbObjectResponse getObject(MyJaxbObjectRequest request);

}

...

JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder()
    .withMarshallerJAXBEncoding(&quot;UTF-8&quot;)
    .withMarshallerSchemaLocation(&quot;http://apihost http://apihost/schema.xsd&quot;)
    .build();

api = Feign.builder()
    .decoder(new SOAPDecoder(jaxbFactory))
    .target(MyApi.class, &quot;http://api&quot;);

...

try {
   api.getObject(new MyJaxbObjectRequest());
} catch (SOAPFaultException faultException) {
   log.info(faultException.getFault().getFaultString());
}
</pre>

@see SOAPErrorDecoder
@see SOAPFaultException
soap/src/main/java/feign/soap/SOAPDecoder.java