Removing namespace prefix in the output of Spring WS web service

徘徊边缘 提交于 2019-12-12 09:11:08

问题


I have created web service using Spring-WS. When I send a request to the web service, this is the response I get in soap-ui:

enter code here
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns2:SendResponse xmlns:ns2="http://mycompany.com/schema/">
         <ns2:SendResult>
            <ns2:Token>A00179-02</ns2:Token>
         </ns2:SendResult>
      </ns2:SendResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Is there any way to get rid of the "ns2" namespace prefix from the response? I tried a couple of options: 1) Manually updated package-info.java to set the prefix to "":

@XmlSchema(namespace = "http://mycompany.com/schema/",  
    xmlns = {   
        @XmlNs(namespaceURI = "http://mycompany.com/schema/", prefix = "")  
    },  
    elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)  

package com.example.foo.jaxb; 

2) Set the prefix to "" in the QName object in the endpoint class:

return new JAXBElement<SendAndCommitResponse>(new QName("http://mycompany.com/schema/",
"SendResponse",""), SendResponse.class, response);

Both didn't work. How to get rid off the "ns2" namespace prefix?


回答1:


I eventually found a solution for this.

My problem was caused by JDK 6 not shipping a full version of rt.jar (http://www.oracle.com/technetwork/java/javase/compatibility-137541.html).

I added the following to my maven config

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.6</version>
</dependency>

And then added

@XmlSchema(namespace = "http://mycompany.com/schema/", 
   elementFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED).

In the package-info.java (like suggested by @acdcjunior above)




回答2:


it was hard

first: create a class that intercepts soap request and responses:

package examples.webservices.handler;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class CorrigirConteudoRequisicaoSOAP implements SOAPHandler<SOAPMessageContext> {
    public Set<QName> getHeaders() {
        return Collections.emptySet();
    }

    public boolean handleMessage(SOAPMessageContext messageContext) {
        this.corrigirConteudoRequisicaoSOAP(messageContext);
        return true;
    }

    private void corrigirConteudoRequisicaoSOAP(SOAPMessageContext messageContext){
        SOAPMessage msg = messageContext.getMessage();
        try {
            NodeList childNodes = msg.getSOAPBody().getChildNodes();

            for(int k = 0; k < childNodes.getLength(); k++){
                Node item = childNodes.item(k);
                String localName = item.getLocalName();
                {
                    item.setPrefix("");
                    Method m = SOAPElement.class.getDeclaredMethod("setElementQName", QName.class);
                    //I was forced to use reflection because the method setElementQname is not //visible, neither the class that implements it
                    m.invoke(item, new QName("", item.getLocalName()));
                    msg.saveChanges();
                }

            }
        } catch (Exception e) {
            try {
                msg.writeTo(System.out);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            System.out.println();
        }
    }

    public boolean handleFault(SOAPMessageContext messageContext) {
        return true;
    }

    public void close(MessageContext messageContext) {
    }

    public static void main(String[] args)throws Exception {
    }
}

second: associate the service to soap handle

public class PortalFornecedor {

    public Usuario getUsuario(){
        XIF367Afae09A3344Fbf2E1De819D6EcbaService classeComNomeFeio = new XIF367Afae09A3344Fbf2E1De819D6EcbaService();

        Usuario service = classeComNomeFeio.getHTTPPort();
        BindingProvider bp = (BindingProvider)service;
        Map<String, Object> requestContext = bp.getRequestContext();
        requestContext.put(BindingProvider.USERNAME_PROPERTY, "user");
        requestContext.put(BindingProvider.PASSWORD_PROPERTY, "pass");
        this.handle(service);
        return service;
    }

    public Object getDashboard(){
        return "";
    }
    // here we associate the service to soap handle
    private BindingProvider handle(Usuario service) {
        BindingProvider bp = (BindingProvider)service;
        @SuppressWarnings("rawtypes")
        List<Handler> chain = new ArrayList<Handler>();
        chain.add(new CorrigirConteudoRequisicaoSOAP());
        bp.getBinding().setHandlerChain(chain);
        return bp;
    }

    public static void main(String[] args) {

        PortalFornecedor pf = new PortalFornecedor();
        Usuario usuario = pf.getUsuario();
        LoginExecutarIN in = new LoginExecutarIN();
        generated.Usuario user = new generated.Usuario();
        user.setLogin("onias");
        user.setSenha("12345");
        user.setCodigoUsuario(0);
        in.setParametroEntrada(user);
        try {
            LoginExecutarOUT out = usuario.loginExecutar(in);
            // SOAPMessageContext.getMessage();

            System.out.println(out.getRegistroSelecionado().getNome());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}



回答3:


I tried a few of the approaches discussed here, but nothing worked...

Below Class from the link - https://zhuanlan.zhihu.com/p/35298171 fixed my issue

Added the below interceptor to remove the namespaces -

public class PayloadPrefixInterceptor extends TransformerHelper implements EndpointInterceptor {

    public static final String NAMESPACE = ObjectFactory.class.getPackage().getAnnotation(XmlSchema.class).namespace();
    public static final String XMLNS = "xmlns:";

    @Override
    public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
        WebServiceMessage response = messageContext.getResponse();
        Source payloadSource = response.getPayloadSource();
        DOMResult result = new DOMResult();
        transform(payloadSource, result);
        removePrefix(result.getNode());
        transform(new DOMSource(result.getNode()), response.getPayloadResult());
        return true;
    }

    private void removePrefix(Node node) {
        if (node == null) {
            return;
        }

        if (node.getNodeType() == Node.ELEMENT_NODE) {
            removeNamespaceDeclaration(node);
        }
        if (node.getPrefix() != null) {
            node.setPrefix(null);
        }
        NodeList childNodes = node.getChildNodes();
        if (childNodes != null) {
            IntStream.of(0, childNodes.getLength()).forEach(index -> removePrefix(childNodes.item(index)));
        }
        Node nextSibling = node.getNextSibling();
        if (nextSibling != null) {
            removePrefix(nextSibling);
        }
    }

    private void removeNamespaceDeclaration(Node node) {
        NamedNodeMap attributes = node.getAttributes();
        IntStream.range(0, attributes.getLength()).forEach(index -> {
            Node attribute = attributes.item(index);
            if (StringUtils.startsWith(attribute.getNodeName(), XMLNS) &&
                    StringUtils.equals(attribute.getNodeValue(), NAMESPACE)) {
                attributes.removeNamedItemNS(attribute.getNamespaceURI(), attribute.getLocalName());
            }
        });
    }

    @Override
    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
        return true;
    }

    @Override
    public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
    }
}

Registered the interceptor using below -

@EnableWs
@Configuration
public class Config extends WsConfigurerAdapter {

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        interceptors.add(new PayloadPrefixInterceptor());
        super.addInterceptors(interceptors);
    }

}


来源:https://stackoverflow.com/questions/16616544/removing-namespace-prefix-in-the-output-of-spring-ws-web-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!