WSO2 ESB - 使用负载标签内的 XML 数据调用 Web 服务
WSO2 ESB - Invoking Webservices with XML data within a tag of the payload
我需要通过中间件调用外部网络服务,我的有效负载中的一个标签包含嵌入式 XML。下面的示例负载和序列片段。我遇到以下问题。
场景 1:(第 24 行)expression="get-property('PayloadXML')" - 发出发送命令后,无法识别 webservice 方法。
场景 2:(第 24 行)expression="get-property('lPayload')" - 发出发送命令后,webservice 方法被成功调用。但是,要使目标系统成功处理消息,它需要处理 CDATA 元素(包装)。
尝试通过soapUI 调用场景2 时,过程成功。根据我的研究 (Passing CDATA in WSO2),soapUI 似乎在转发消息之前在内部处理 CDATA 元素。
现在,我明白我设置方案 2 的方式并不理想(更像是一种 hack),但我不知道有任何其他方法可以实现这一点。我已经阅读了大量 blogs/posts 并尝试通过 XSLT 调解器转换(开发)有效负载,但没有成功。我也遇到了以下 post http://www.yenlo.com/en/how-to-preserve-a-cdata-in-xml-that-is-circulating-in-a-wso2-enterprise-service-bus/ ,但我似乎找不到所引用的补丁。
所以我的问题如下:
1.还有其他的ways/mechanisms可以满足我的要求吗?
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('<![CDATA[',get-property('PayloadXML')), ']]>')"/>
<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=""></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>
这是一个示例代理服务,它接收 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>
如果您的基本要求是在标签内传递 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[]]></xs:xmlBody>
<xs:sessionId xmlns:xs="http://example.com"></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/xml
registry resource
的已定义注册表资源
我需要通过中间件调用外部网络服务,我的有效负载中的一个标签包含嵌入式 XML。下面的示例负载和序列片段。我遇到以下问题。
场景 1:(第 24 行)expression="get-property('PayloadXML')" - 发出发送命令后,无法识别 webservice 方法。
场景 2:(第 24 行)expression="get-property('lPayload')" - 发出发送命令后,webservice 方法被成功调用。但是,要使目标系统成功处理消息,它需要处理 CDATA 元素(包装)。
尝试通过soapUI 调用场景2 时,过程成功。根据我的研究 (Passing CDATA in WSO2),soapUI 似乎在转发消息之前在内部处理 CDATA 元素。
现在,我明白我设置方案 2 的方式并不理想(更像是一种 hack),但我不知道有任何其他方法可以实现这一点。我已经阅读了大量 blogs/posts 并尝试通过 XSLT 调解器转换(开发)有效负载,但没有成功。我也遇到了以下 post http://www.yenlo.com/en/how-to-preserve-a-cdata-in-xml-that-is-circulating-in-a-wso2-enterprise-service-bus/ ,但我似乎找不到所引用的补丁。
所以我的问题如下: 1.还有其他的ways/mechanisms可以满足我的要求吗? 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('<![CDATA[',get-property('PayloadXML')), ']]>')"/>
<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=""></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>
这是一个示例代理服务,它接收 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>
如果您的基本要求是在标签内传递 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[]]></xs:xmlBody>
<xs:sessionId xmlns:xs="http://example.com"></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/xml
registry resource