【问题标题】:Sending XmlData in soap request using spring ws使用spring ws在soap请求中发送XmlData
【发布时间】:2014-04-15 20:29:56
【问题描述】:

我需要将CDATA 中的XmlData 发送到返回附件的soap 请求。

使用org.springframework.oxm.jaxb.Jaxb2Marshaller 作为编组器和解组器。

<![CDATA[<tag>Test</tag>]]>这是我想在soap请求中发送的东西,远程服务期望它以同样的方式看到。

我已经创建了数据但是当我使用webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)

不知何故,有效载荷请求 xmltags 被编码并显示为

<![CDATA[<tag>Test<\tag>

由于这种编码,远程服务无法处理请求并发送 org.springframework.ws.soap.client.SoapFaultClientException: Object reference not set to an instance of an object.

我该如何解决这个问题?有什么建议!

更新:是否将 mvc 的 defaultHtmlEscape 作为负责此行为的 web.xml 中的上下文参数?

【问题讨论】:

    标签: java soap spring-ws


    【解决方案1】:

    我今天在工作中遇到了同样的问题,当我们必须在定义为从银行 Web 服务公开的 WSDL 中的数据结构的字段文本上注入 CDATA 部分时。

    要求是引入 CDATA 部分以将 Unicode 字符“+”转义到电话号码字段中。 WSDL 不可能因各种动机而改变。

    我们有相同的环境:

     org.springframework.oxm.jaxb.Jaxb2Marshaller
    
    webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)
    

    同样的失败结果

    <![CDATA[<tag>+<\tag>
    

    而不是

    <[[CDATA[+]]>
    

    经过多次测试以及在 Stackoverflow 和其他网站上咨询了许多字体后,我们了解到 JAXB 引擎本身不支持该解决方案,因此有必要将 SOAP 消息处理为处理请求的准时步骤。

    其他解决方案表明使用第三方插件和库,例如 MOXy,以实现对 CDATA 部分和 JAXB 的强大支持。但是这种解决方案不可能尽快以形式在大型企业应用程序上快速集成。

    我在此回复中发布的此解决方案允许使用经典 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 服务肥皂的所有环境中。关键方面是使用规范方法将 SoapMessage 转换为更友好的 DOMSource 来探索节点。也可以使用 XPath 引擎来导航这个 DOMSource。

    祝你好运!

    上午

    【讨论】:

      【解决方案2】:

      我在使用 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 {
      
      }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-06
        • 1970-01-01
        • 1970-01-01
        • 2015-11-15
        • 2019-10-26
        • 2013-08-13
        • 1970-01-01
        • 2014-11-03
        • 1970-01-01
        相关资源
        最近更新 更多