How to change default SOAP-ENV and ns2 namespace prefixes in spring-ws

1.3k Views Asked by At

Following is the response I'm getting and I need to override SOAP-ENV and ns2 in this payload.

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Header/>
       <SOAP-ENV:Body>
          <ns2:Response xmlns:ns2="">
             <ns2:RequestReturn>
                <ns2:COUNTRY_CODE>1</ns2:COUNTRY_CODE>
             </ns2:RequestReturn>
          </ns2:Response>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

expected output

    <soapns:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <soapns:Header/>
       <soapns:Body>
          <tns:Response xmlns:tns="">
             <tns:RequestReturn>
                <tns:COUNTRY_CODE>1</tns:COUNTRY_CODE>
             </tns:RequestReturn>
          </tns:Response>
       </soapns:Body>
    </soapns:Envelope>
1

There are 1 best solutions below

0
On

We need to implement the following Interceptor

@Component
public class CustomEndpointInterceptor extends EndpointInterceptorAdapter {

    private static final Log LOG = LogFactory.getLog(CustomEndpointInterceptor.class);
    private static final String SOAP_ENV_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/";
    private static final String PREFERRED_PREFIX = "infasoapns";

    @Override
    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
        LOG.info("Endpoint Response Handling");
        SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
        alterSoapEnvelope(soapResponse);
        return super.handleResponse(messageContext, endpoint);
    }
  
    @Override
    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
        LOG.info("Endpoint Response Handling");  
        SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
        alterSoapEnvelope(soapResponse);
        return super.handleFault(messageContext, endpoint);
    }

    private void alterSoapEnvelope(SaajSoapMessage soapResponse) {
        try {
          SOAPMessage soapMessage = soapResponse.getSaajMessage();
          SOAPPart soapPart = soapMessage.getSOAPPart();
          SOAPEnvelope envelope = soapPart.getEnvelope();
          SOAPHeader header = soapMessage.getSOAPHeader();
          SOAPBody body = soapMessage.getSOAPBody();
          SOAPFault fault = body.getFault();
          envelope.removeNamespaceDeclaration(envelope.getPrefix());
          envelope.addNamespaceDeclaration(PREFERRED_PREFIX, SOAP_ENV_NAMESPACE);
          envelope.setPrefix(PREFERRED_PREFIX);
          header.setPrefix(PREFERRED_PREFIX);
          body.setPrefix(PREFERRED_PREFIX);
          addDesiredBodyNamespaceEntries(body.getChildElements());
          
          removeUndesiredBodyNamespaceEntries(body.getChildElements());
          if (fault != null) {
            fault.setPrefix(PREFERRED_PREFIX);
          }
        } catch (SOAPException e) {
          e.printStackTrace();
        }
    }

    private void addDesiredBodyNamespaceEntries(Iterator childElements) {
        while (childElements.hasNext()) {
          final Object childElementNode = childElements.next();
          if (childElementNode instanceof SOAPElement) {
            SOAPElement soapElement = (SOAPElement) childElementNode;
    
            // set desired namespace body element prefix
            soapElement.setPrefix("tns");
    
            // recursively set desired namespace prefix entries in child elements
            addDesiredBodyNamespaceEntries(soapElement.getChildElements());
          }
        }
      }

      private void removeUndesiredBodyNamespaceEntries(Iterator childElements) {
        while (childElements.hasNext()) {
          final Object childElementNode = childElements.next();
          if (childElementNode instanceof SOAPElement) {
            SOAPElement soapElement = (SOAPElement) childElementNode;
    
            // we remove any prefix/namespace entries added by JAX-WS in the body element that is not the one we want
            for (String prefix : getNamespacePrefixList(soapElement.getNamespacePrefixes())) {
              if (prefix != null && ! "tns".equals(prefix)) {
                soapElement.removeNamespaceDeclaration(prefix);
              }
            }
    
            // recursively remove prefix/namespace entries in child elements
            removeUndesiredBodyNamespaceEntries(soapElement.getChildElements());
          }
        }
      }

      private Set<String> getNamespacePrefixList(Iterator namespacePrefixIter) {
        Set<String> namespacePrefixesSet = new HashSet<>();
        while (namespacePrefixIter.hasNext()) {
          namespacePrefixesSet.add((String) namespacePrefixIter.next());
        }
        return namespacePrefixesSet;
      }
   
}

and add the following code segment to the Webservice config

@Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        // register global interceptor
        interceptors.add(new CustomEndpointInterceptor());

        // register endpoint specific interceptor
        interceptors.add(new PayloadRootSmartSoapEndpointInterceptor(
                new CustomEndpointInterceptor(),
                ValidationEndpoint.NAMESPACE_URI,
                ValidationEndpoint.LOCAL_PART));
    }