2010-10-02 136 views
11

我正在使用JAXWS爲我們正在構建的Java應用程序生成WebService客戶端。更改使用JAXWS生成的默認XML名稱空間前綴

當JAXWS打造個XML的SOAP協議的使用,它會生成以下命名空間前綴:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> 
    <env:Body ...> 
     <!-- body goes here --> 
    </env:Body> 
</env:Envelope> 

我的問題是,我的對口(大匯款公司)負責管理服務器我的客戶端連接要拒絕接受WebService調用(請不要問我爲什麼),除非XMLNS(XML名稱空間前綴爲soapenv)。就像這樣:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Body ...> 
     <!-- body goes here --> 
    </soapenv:Body> 
</soapenv:Envelope> 

所以我的問題是:

有沒有一種方法,我命令JAXWS(或任何其他Java WS客戶端技術)使用的soapenv代替envXMLNS前綴生成的客戶端?是否有API調用來設置此信息?

謝謝!

+0

點pedantry:你不改變名字空間,你改變前綴。 – skaffman 2010-10-02 14:33:02

+0

@skaffman同意。謝謝! – 2010-10-02 14:35:09

+0

嗨: 我也有同樣的問題。你找到任何解決方案嗎? 感謝你, Kumar – 2011-01-20 14:04:15

回答

15

也許這對你來說已經遲到了,我不確定這是否可行,但你可以試試。

首先你需要實現一個SoapHandler,並且在handleMessage方法中你可以修改SOAPMessage。我不知道,如果你可以直接修改的前綴,但你可以嘗試:

public class MySoapHandler implements SOAPHandler<SOAPMessageContext> 
{ 

    @Override 
    public boolean handleMessage(SOAPMessageContext soapMessageContext) 
    { 
    try 
    { 
     SOAPMessage message = soapMessageContext.getMessage(); 
     // I haven't tested this 
     message.getSOAPHeader().setPrefix("soapenv"); 
     soapMessageContext.setMessage(message); 
    } 
    catch (SOAPException e) 
    { 
     // Handle exception 
    } 

    return true; 
    } 

    ... 
} 

然後,你需要創建一個HandlerResolver

public class MyHandlerResolver implements HandlerResolver 
{ 
    @Override 
    public List<Handler> getHandlerChain(PortInfo portInfo) 
    { 
    List<Handler> handlerChain = Lists.newArrayList(); 
    Handler soapHandler = new MySoapHandler(); 
    String bindingID = portInfo.getBindingID(); 

    if (bindingID.equals("http://schemas.xmlsoap.org/wsdl/soap/http")) 
    { 
     handlerChain.add(soapHandler); 
    } 
    else if (bindingID.equals("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")) 
    { 
     handlerChain.add(soapHandler); 
    } 

    return handlerChain; 
    } 
} 

最後,你必須將您HandlerResolver增加客戶服務:

Service service = Service.create(wsdlLoc, serviceName); 
service.setHandlerResolver(new MyHandlerResolver()); 
1

這個職位,而有可能爲時已晚,原來的海報,是爲了幫助別人誰可能會遇到此。過去幾天我必須解決這個問題。特別是,我需要更改SOAP信封中使用的前綴,因爲服務提供者要求名稱空間前綴符合特定的模式。符合這種模式需要更改信封,標題和正文以及正文元素(來自JAX-WS放入的標準字段)的名稱空間前綴。這是我所使用的溶液的概要:

import javax.xml.namespace.QName; 
import javax.xml.soap.SOAPBody; 
import javax.xml.soap.SOAPElement; 
import javax.xml.soap.SOAPEnvelope; 
import javax.xml.soap.SOAPException; 
import javax.xml.soap.SOAPHeader; 
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 java.util.HashSet; 
import java.util.Iterator; 
import java.util.Set; 

public class MyMessageNamespaceMapper implements SOAPHandler<SOAPMessageContext> { 

    @Override 
    public Set<QName> getHeaders() { 
    return null; 
    } 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
    final Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
    // only process outbound messages 
    if (outbound) { 
     try { 
     final SOAPMessage soapMessage = context.getMessage(); 
     final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope(); 
     final SOAPHeader soapHeader = soapMessage.getSOAPHeader(); 
     final SOAPBody soapBody = soapMessage.getSOAPBody(); 

     // STEP 1: add new prefix/namespace entries 
     soapEnvelope.addNamespaceDeclaration("S1", "http://schemas.xmlsoap.org/soap/envelope/"); 
     soapEnvelope.addNamespaceDeclaration("FOO-1", "http://foo1.bar.com/ns"); 

     // STEP 2: set desired namespace prefixes 
     // set desired namespace prefix for the envelope, header and body 
     soapEnvelope.setPrefix("S1"); 
     soapHeader.setPrefix("S1"); 
     soapBody.setPrefix("S1"); 
     addDesiredBodyNamespaceEntries(soapBody.getChildElements()); 

     // STEP 3: remove prefix/namespace entries entries added by JAX-WS 
     soapEnvelope.removeNamespaceDeclaration("S"); 
     soapEnvelope.removeNamespaceDeclaration("SOAP-ENV"); 
     removeUndesiredBodyNamespaceEntries(soapBody.getChildElements()); 

     // IMPORTANT! "Save" the changes 
     soapMessage.saveChanges(); 
     } 
     catch (SOAPException e) { 
     // handle the error 
     } 
    } 

    return true; 
    } 

    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("FOO-1"); 

     // 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 && ! "FOO-1".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; 
    } 

    @Override 
    public boolean handleFault(SOAPMessageContext context) { 
    return true; 
    } 

    @Override 
    public void close(MessageContext context) { 
    } 
} 

服務類(由JAX-WS /的wsimport產生的)的一個實例設置上述處理程序解析器看起來像這樣:的

yourWebServiceClient.setHandlerResolver(new HandlerResolver() { 
    @Override 
    public List<Handler> getHandlerChain(PortInfo portInfo) { 
    return Arrays.asList(new MyMessageNamespaceMapper()); 
    } 
});