2014-04-15 112 views
2

我有要求將中的XmlData發送到返回附件的soap請求。使用org.springframework.oxm.jaxb.Jaxb2Marshaller作爲編組和解組器。使用spring在肥皂請求中發送XmlData ws

<![CDATA[<tag>Test</tag>]]>這是我想在SOAP請求和遠程服務來發送期待它看到相同的方式。

我已創建的數據,但是當我使用webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)

某種方式,有效載荷請求xmltags被編碼並顯示爲

&lt;![CDATA[&lt;tag&gt;Test&lt;\tag&gt;

由於這種編碼的,遠程服務無法處理該請求,併發送 org.springframework.ws.soap.client.SoapFaultClientException: Object reference not set to an instance of an object.

我怎樣才能解決這個問題?有什麼建議麼!

更新:是否,在web.xml中彈出mvc的defaultHtmlEscape作爲context-param負責此行爲?

回答

1

我在這一天的工作,得到了同樣的問題時,我們必須注入過定義成從銀行Web服務公開一個WSDL的數據結構的字段中的文本CDATA節。

要求是引入CDATA部分以將Unicode字符「+」轉義爲數字電話字段。 WSDL不可能因各種動機而改變。

我們有相同的環境:

org.springframework.oxm.jaxb.Jaxb2Marshaller 

webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback) 

和相同的失敗結果

&lt;![CDATA[&lt;tag&gt;+&lt;\tag&gt; 

,而不是

<[[CDATA[+]]> 

經過多次和許多測試之後對諮詢很多字體Stackoverflow和其他網站,我們已經瞭解到該解決方案並非由JAXB eng本機支持ine,並且需要將SOAP消息操作爲處理請求的雙重步驟。

其他的解決方案表明使用第三方插件和庫,廣告例如莫西,到CDATA節還JAXB的實現了強有力的支持。但是這種解決方案不可能在ASAP的形式中快速集成到巨大的企業應用程序中。

此解決方案,我在此回覆許可證發佈使用經典對象爲DOMSource鑄造從MessageContext的消息SOAP的規範的方法中注入的CDATASection。

在你的答案中,你公開了解決方案的一部分,這是marshalSendAndReceive的回調。

如果您定義了marshalSendAndReceive方法支持的臨時回調,並且在此回調中操縱注入CDATASection的DOMSource,則可以解決此問題。

這是代碼:

WebServiceMessageCallback callbackCDATANumTelefono = new WebServiceMessageCallback() { 
      public void doWithMessage(WebServiceMessage message) { 

       //Recover the DOMSource dal message soap 
       DOMSource domSource = (DOMSource)message.getPayloadSource(); 

       //recover set of child nodes of domsource 
       NodeList nodeList = domSource.getNode().getChildNodes(); 

       //definisco il nome del tag da cercare 
       String nameNumTel = "ns2:sNumTel"; //in this example, but you can define another QName string to recover the target node (or nodes) 
       Node nodeNumTel = null; 
       for (int i = 0; i < nodeList.getLength(); i++) { 
        //search of text node of this tag name 
        if (nodeList.item(i).getNodeName().compareTo(nameNumTel) == 0) { 
         nodeNumTel = nodeList.item(i); 
         break; 
        } 
       } 
       //recover the string value (in this case of telephone number) 
       String valueNumTelefono = nodeNumTel.getTextContent(); 
       //clean of value of target text node 
       nodeNumTel.setTextContent(""); 
       //define and inject of CDATA section, in this case encapsulate "+" character 
       CDATASection cdata = nodeNumTel.getOwnerDocument().createCDATASection("+"); 
       //create of new text node 
       Text tnode = nodeNumTel.getOwnerDocument().createTextNode(valueNumTelefono); 
       //append of CDATASection (in this point is possible to inject many CDATA section on various parts of string (very usefull) 
       nodeNumTel.appendChild(cdata); 
       nodeNumTel.appendChild(tnode); 

       //done! 
      } 
     }; 

這個回調函數將被從marshalSendAndReceive

PayloadSoapResponse output = (PayloadSoapResponse) getWebServiceTemplate() 
       .marshalSendAndReceive(input, callbackCDATANumTelefono); 

調用的結果是與CDATA部分有效並以ASCII字符不轉換請求正確的發送。

該解決方案的目標是使用JAXB技術在Spring基礎結構上操縱CDATA節,而不是使用第三方庫。 一般來說,回調方法的指令集非常值得信賴,並且在web服務soap的所有環境中都很好注入。關鍵的方面是將SoapMessage轉換爲更加友好的DOMSource,並使用規範的方法來探索節點。也可以使用XPath引擎來導航此DOMSource。

祝你好運!

1

我用spring-WS時產生SOAP的Web服務有這種確切的問題。如上所述,CDATA部分總是會被轉義。

在我的情況下,解決方案(非常類似於Alessandro)創建了一個EndpointInterceptor,我將所需的節點轉換爲handleResponse中的org.w3c.dom.CDATASection。 然後,您需要將此攔截器添加到實施中的攔截器列表中。

import org.springframework.ws.WebServiceMessage; 
import org.springframework.ws.context.MessageContext; 
import org.springframework.ws.server.EndpointInterceptor; 
import org.springframework.ws.soap.saaj.SaajSoapMessage; 
import org.w3c.dom.CDATASection; 

import javax.xml.soap.Node; 
import javax.xml.soap.SOAPBody; 
import javax.xml.soap.SOAPEnvelope; 
import javax.xml.soap.SOAPMessage; 
import javax.xml.soap.SOAPPart; 
import java.util.Iterator; 

public class MyCdataInterceptor implements EndpointInterceptor { 

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

@Override 
public boolean handleResponse(MessageContext messageContext, Object o) throws Exception { 

    WebServiceMessage response = messageContext.getResponse(); 

    SaajSoapMessage saajSoapMessage = (SaajSoapMessage) response; 
    SOAPMessage soapMessage = saajSoapMessage.getSaajMessage(); 
    SOAPPart soapPart = soapMessage.getSOAPPart(); 
    SOAPEnvelope envelope = soapPart.getEnvelope(); 
    SOAPBody body = envelope.getBody(); 
    Iterator it = body.getChildElements(); 
    ... 
    /* find node of interest */ 

    Node interestingNode = (Node) blah.getNextSibling(); 

    CDATASection cdat = soapPart.createCDATASection(interestingNode.getFirstChild().getNodeValue()); 
    interestingNode.removeChild(interestingNode.getFirstChild()); 
    interestingNode.appendChild(cdat); 
    return true; 
} 

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

@Override 
public void afterCompletion(MessageContext messageContext, Object o, Exception e) throws Exception { 

} 
}