0

I am making a call to an external webservice and the faultcode that is returned seems to be causing some trouble for CXF. The response is as follows :

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>S:Server</faultcode><faultstring>Something serious wen wrong</faultstring></soap:Fault></soap:Body></soap:Envelope>

CXF has trouble with this because of the S:Server not being valid. The resulting error is

    java.lang.RuntimeException: Invalid QName in mapping: S:Server

I am trying to use the CXF Transform feature to change the faultcode but I cannot seem to get it working correctly. The desired output should be:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Something serious wen wrong</faultstring></soap:Fault></soap:Body></soap:Envelope>

I have had a look at CXF Transform Feature and tried the following in my code :

    BindingProvider bp = (BindingProvider) port;
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
    Client client = ClientProxy.getClient(port);
    Map<String, String> inTransformMap = Collections.singletonMap("faultcode", "faultcode=soap:Server");
    org.apache.cxf.feature.StaxTransformFeature staxTransformFeature = new org.apache.cxf.feature.StaxTransformFeature();
    staxTransformFeature.setInAppendElements(inTransformMap);
    staxTransformFeature.initialize(client, client.getBus());

This does not seem to replace the faultcode. I have also tried other variations like

  1. staxTransformFeature.setInTransformElements(inTransformMap)
  2. inTransformMap = Collections.singletonMap("{}faultcode", "{}faultcode=soap:Server"); but with no luck.

I am unable to find any clear examples showing the usage of the transform feature (eg. input and output xml)

Please guide me on what I may be doing wrong.

Thanks in advance.

Tboneh
  • 1
  • 3

1 Answers1

0

I have resorted to creating an Interceptor to solve my problem (with the help of this).

public class ChangeSoapFaultCodeInterceptor extends AbstractPhaseInterceptor<Message> {

public ChangeSoapFaultCodeInterceptor() {
    super(Phase.RECEIVE);
}

@Override
public void handleMessage(Message message) throws Fault {

    boolean isInbound = message == message.getExchange().getInMessage() || message == message.getExchange().getInFaultMessage();

    if (isInbound) {
        try (InputStream is = message.getContent(InputStream.class);) {
            if (is != null) {
                byte[] rawContent = ByteStreams.toByteArray(is);
                String content = new String(rawContent, StandardCharsets.UTF_8);
                String cleanContent = modifySoapFaultCode(content);
                message.setContent(InputStream.class, new ByteArrayInputStream(cleanContent.getBytes(StandardCharsets.UTF_8)));
            }
        } catch (IOException e) {
            throw new Fault(e);
        }
    }
}

private static String modifySoapFaultCode(String message) {
    message = message.replaceAll("<faultcode>([^<]*)</faultcode>", "<faultcode>Server</faultcode>");
    System.out.println("After change message is " + message);

    return message;
}

}

Then add the interceptor to the chain :

BindingProvider bp = (BindingProvider)port;
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
    Client client = ClientProxy.getClient(port);    
    client.getInInterceptors().add(new ChangeSoapFaultCodeInterceptor());
    return port.sayRuntimeException();
Tboneh
  • 1
  • 3