0

We are migrating from Axis-2 to CXF and trying to have similar responses.

Axis-2 response for soap request

<?xml version="1.0" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <loginResponse xmlns="urn:TestWebAPI">
            <loginReturn xmlns="">9876</loginReturn>
        </loginResponse>
    </soapenv:Body>
</soapenv:Envelope>

CXF response after migration:

<?xml version="1.0" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns1:loginResponse xmlns:ns1="urn:TestWebAPI">
            <loginReturn xmlns:ns2="urn:TestWebAPI">9876</loginReturn>
        </ns1:loginResponse>
    </soap:Body>
</soap:Envelope>

How can i make CXF response similar to Axis-2 response ?

1 Answer 1

0

Modify SOAP Prefix

CXF provides a property "soap.env.ns.map" to modify prefix of soap response.

import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

import java.util.HashMap;
import java.util.Map;


public class SoapResponsePrefixInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private String soapEnvelopePrefix;

    public SoapResponsePrefixInterceptor(String soapPrefix) {
        super(Phase.PREPARE_SEND);
        soapEnvelopePrefix = soapPrefix;
    }

    @Override
    public void handleMessage(SoapMessage message) {
        Map<String, String> envelopeNSMap = new HashMap<>();
        envelopeNSMap.put(soapEnvelopePrefix, Soap11.SOAP_NAMESPACE); // "http://schemas.xmlsoap.org/soap/envelope/"
        message.put("soap.env.ns.map", envelopeNSMap);
        message.put(AbstractOutDatabindingInterceptor.DISABLE_OUTPUTSTREAM_OPTIMIZATION, Boolean.TRUE);
    }
}

Include this class as an out interceptor, to modify the soap prefix.

SoapResponsePrefixInterceptor responsePrefixInterceptor = new SoapResponsePrefixInterceptor("soapenv");
factoryBean.getOutInterceptors().add(responsePrefixInterceptor);
factoryBean.getOutFaultInterceptors().add(responsePrefixInterceptor);

The logic for the same is implemented in SoapOutInterceptor.writeSoapEnvelopeStart(). hasAdditionalEnvNs() checks whether the application has configured any custom envelope name space and replace it with configured value.


Modify or remove namespace

CXF provides transformer feature that help us to modify namespace.

private Feature getTransformer() {
    StaxTransformFeature staxFeature = new StaxTransformFeature();
    Map<String, String> replaceElements = new HashMap<>();
    // value between braces is used as namespace, followed by localName.
    replaceElements.put('{' + DEFAULT_NAMESPACE + "}*", "");
    staxFeature.setOutTransformElements(replaceElements);
    staxFeature.setOutDefaultNamespace(DEFAULT_NAMESPACE);
    return staxFeature;
}

Add this transformer as a feature into the factory bean.

fb.setFeatures(List.of(getTransformer()));
  1. TransformOutInterceptor.createTransformWriterIfNeeded() - creates transformer if any of the values are set.
  2. RPCOutInterceptor.addOperationNode() > StaxUtils.writeStartElement() > OutTransformWriter.writeStartElement() > OutTransformWriter.write() - modifies the response based on the transformer.

logic for the same is present in OutTransformWriter() > TransformUtils.convertToQNamesMap() > DOMUtils.convertStringToQName()

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.