【问题标题】:WSO2 ESB - Invoking Webservices with XML data within a tag of the payloadWSO2 ESB - 使用有效负载标签内的 XML 数据调用 Web 服务
【发布时间】:2015-08-19 07:53:49
【问题描述】:

我需要通过中间件调用外部 Web 服务,我的有效负载中的一个标签包含嵌入式 XML。下面的示例有效负载和序列 sn-p。我遇到以下问题。

场景 1:(第 24 行)表达式="get-property('PayloadXML')" - 发出发送命令后,无法识别 Web 服务方法。

场景 2 : (line 24) expression="get-property('lPayload')" - 发出发送命令后,成功调用 web 服务方法。然而,为了让目标系统成功处理消息,它需要处理 CDATA 元素(包装)。

当尝试通过soapUI 调用场景2 时,该过程是成功的。根据我的研究 (Passing CDATA in WSO2),soapUI 似乎在转发消息之前在内部处理 CDATA 元素。

现在,我知道我设置场景 2 的方式并不理想(更像是一种 hack),但我不知道有任何其他方法可以实现这一点。我已经阅读了许多博客/帖子,并尝试通过 XSLT 调解器转换(开发)有效负载,但没有成功。我也遇到过以下帖子 http://www.yenlo.com/en/how-to-preserve-a-cdata-in-xml-that-is-circulating-in-a-wso2-enterprise-service-bus/ ,但我似乎找不到所引用的补丁。

所以我的问题如下: 1. 有没有其他方法/机制可以达到我的要求? 2. WSO2 ESB 4.9.0 版本会解决上述问题吗?

样本负载:

<sample><test>MyData</test></sample>

序列片段:

     <property xmlns:ns1="http://ws.wso2.org/dataservice"
               xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
               name="PayloadXML"
               expression="$body/data-services-event/content/ns1:return/ns1:return/ns1:PayLoadXML"/>
     <property xmlns:ns="http://org.apache.synapse/xsd"
               name="lPayload"
               expression="fn:concat(fn:concat('&lt;![CDATA[',get-property('PayloadXML')), ']]&gt;')"/>
     <payloadFactory media-type="xml">
        <format>
           <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                             xmlns:log="http://mynamespace">
              <soapenv:Header/>
              <soapenv:Body>
                 <log:publishMessage>
                    <Payload xmlns="">$1</Payload>
                 </log:publishMessage>
              </soapenv:Body>
           </soapenv:Envelope>
        </format>
        <args>
           <arg xmlns:ns2="http://org.apache.synapse/xsd"
                xmlns:ns="http://org.apache.synapse/xsd"
                evaluator="xml"
                expression="get-property('lPayload')"/>
        </args>
     </payloadFactory>

【问题讨论】:

    标签: wso2 cdata


    【解决方案1】:

    这是一个示例代理服务,它接收 XML 数据并发送回一条新的 XML 消息,其中包含 CDATA 部分中输入内容的子部分。

    发送:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
        <SOAP-ENV:Body>
            <PayloadXML>
                <sample><test>MyData</test></sample>
            </PayloadXML>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    

    您收到:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Header/>
        <soapenv:Body>
            <log:publishMessage xmlns:log="http://mynamespace">
                <Payload><![CDATA[<sample><test>MyData</test></sample>]]></Payload>
            </log:publishMessage>
        </soapenv:Body>
    </soapenv:Envelope>
    

    代理定义:

    <?xml version="1.0" encoding="UTF-8"?>
    <proxy xmlns="http://ws.apache.org/ns/synapse" name="TestSOF" transports="http" statistics="disable" trace="disable" startOnLoad="true">
        <target>
            <inSequence>
                <!-- extract xml content from the input message -->
                <property name="xmlContent" expression="$body/PayloadXML/*[1]" type="OM"/>
                <!-- compose a new message -->
                <enrich>
                    <source type="inline" clone="true">
                        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                            <soapenv:Header/>
                            <soapenv:Body>
                                <log:publishMessage xmlns:log="http://mynamespace">
                                    <Payload xmlns=""/>
                                </log:publishMessage>
                            </soapenv:Body>
                        </soapenv:Envelope>
                    </source>
                    <target type="envelope"/>
                </enrich>
                <!-- create a CDATA section for 'Payload' node -->
                <script language="js">
                    importPackage(Packages.org.apache.axiom.om);
                    var payloadElmt = mc.getEnvelope().getBody().getFirstElement().getFirstElement();
                    var omText = payloadElmt.getOMFactory().createOMText(payloadElmt, mc.getProperty("xmlContent"), OMNode.CDATA_SECTION_NODE);
                    payloadElmt.addChild(omText)                    
                </script>
                <!-- send back this new message as a response for the caller -->
                <header name="To" action="remove"/>
                <property name="RESPONSE" value="true"/>
                <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
                <send/>
            </inSequence>
        </target>
        <description/>
    </proxy>
    

    【讨论】:

    • 如果您使用 SoapUI 进行测试,请查看原始格式的响应
    • 您好 Jean-Michel,感谢您的及时响应和解决方案。我根据我的用例对其进行了调整,效果非常好。非常感谢...
    【解决方案2】:

    如果您的基本要求是在标签中传递 xml 数据,这里有一个例子。

    这里我使用的是 wso2 ESB 4.9.0。基本的事情是,您需要将有效负载工厂格式存储在注册表中,并在有效负载工厂配置中使用它,如下所示。

    <proxy xmlns="http://ws.apache.org/ns/synapse"
       name="foo"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
    <target>
        <inSequence>
            <property xmlns:ns="http://org.apache.synapse/xsd"
                      name="Request"
                      expression="$body/child::*[fn:position()=1]"
                      scope="default"
                      type="STRING"/>
            <payloadFactory media-type="xml">
                <format key="conf:/repository/esb/myPF"/>
                <args>
                    <arg evaluator="xml" expression="$ctx:Request"/>
                    <arg value="1"/>
                </args>
            </payloadFactory>
    
            <send>
                <endpoint>
                    <address uri="http://127.0.0.1:9763/services/Hello"/>
                </endpoint>
            </send>
        </inSequence>
        <outSequence>
            <send/>
        </outSequence>
    </target>
    <description/>
    

    以上是我的代理服务。我从 ESB 从客户端获取的请求中获取第一个子节点,并将其用作负载工厂调解器的输入。

    注册表资源的内容如下所示。

    <ns:testMethod xmlns:ns="http://example.com">
                                <xs:xmlBody xmlns:xs="http://example.com"><![CDATA[$1]]></xs:xmlBody>
                                <xs:sessionId xmlns:xs="http://example.com">$2</xs:sessionId>
                            </ns:testMethod>
    

    您可以通过为 ESB[2] 启用连线日志来测试场景。

    在这里,我在 WSO2 AS 中托管了一个简单的axis2服务进行测试。这是wirelog输出。

       [2016-02-24 19:02:24,696] DEBUG - wire << "POST /services/Hello HTTP/1.1[\r][\n]"
     [2016-02-24 19:02:24,696] DEBUG - wire << "Content-Type: application/soap+xml; charset=UTF-8; action="urn:mediate"[\r][\n]"
     [2016-02-24 19:02:24,696] DEBUG - wire << "Transfer-Encoding: chunked[\r][\n]"
     [2016-02-24 19:02:24,696] DEBUG - wire << "Host: 127.0.0.1:9763[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "Connection: Keep-Alive[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "180[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body><ns:testMethod xmlns:ns="http://example.com"><xs:xmlBody xmlns:xs="http://example.com"><![CDATA[<sample><test>MyData</test></sample>]]></xs:xmlBody><xs:sessionId xmlns:xs="http://example.com">1</xs:sessionId></ns:testMethod></soapenv:Body></soapenv:Envelope>[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "0[\r][\n]"
     [2016-02-24 19:02:24,697] DEBUG - wire << "[\r][\n]"
    

    在这里可以找到内容类型为text/xmlregistry resource的已定义注册表资源

    [2]https://docs.wso2.com/display/ESB490/Setting+Up+Logging

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多