WSO2 6.6.0中Call Mediator后Log Mediator无法获取Payload求助
问题描述
在WSO2中搭建了一个简单API,调用后端服务后无法获取到预期的响应Payload,Postman直接调用后端能正常返回结果,但API里各种方式都拿到空Payload或空对象。
API代码
<?xml version="1.0" encoding="UTF-8"?> <api context="/dwh" name="dwhCallEp" xmlns="http://ws.apache.org/ns/synapse"> <resource methods="GET" uri-template="/ep/{sysparam}"> <inSequence> <log level="custom"> <property name="START" value="call into dwh storage"/> <property expression="get-property('uri.var.sysparam')" name="sysparam"/> </log> <call> <endpoint> <http method="get" statistics="enable" trace="enable" uri-template="http://my_path?sysparam={uri.var.sysparam}&call_in_async_mode=false"> <timeout> <duration>120000</duration> <responseAction>fault</responseAction> </timeout> <suspendOnFailure> <initialDuration>-1</initialDuration> <progressionFactor>1.0</progressionFactor> </suspendOnFailure> <markForSuspension> <retriesBeforeSuspension>0</retriesBeforeSuspension> </markForSuspension> </http> </endpoint> </call> <property expression="json-eval($[0])" name="JsonPayload" scope="default" type="STRING"/> <log level="full" separator="
"> <property expression="$ctx:JsonPayload" name="JsonPayload"/> </log> <script language="js"><![CDATA[var payload = mc.getPayloadJSON(); var log = mc.getServiceLog(); log.info("payload_json : " + payload); log.info("payload_json : " + JSON.stringify(payload)); mc.setProperty("payload_json",JSON.stringify(payload));]]></script> <log level="full" separator="
"> <property name="payload" expression="json-eval($)" /> </log> <respond/> </inSequence> <outSequence/> <faultSequence> <payloadFactory media-type="xml"> <format> <error>$1</error> </format> <args> <arg value="something go wrong!!!"/> </args> </payloadFactory> </faultSequence> </resource> </api>
尝试过的方法
- 使用
level="full"的Log Mediator查看API返回的所有内容 - 在Property Mediator中使用
expression="json-eval($[0])"并记录其值到日志 - 使用Script Mediator通过
mc.getPayloadJSON()获取Payload,再用JSON.stringify(payload)转为字符串并存入属性 - 在Property Mediator中使用
expression="json-eval($)"并记录其值到日志
日志堆栈
[2024-02-01 11:07:51,198] INFO {LogMediator} - {api:dwhCallEp} START = call into dwh storage, sysparam = pn_citytypes [2024-02-01 11:07:51,201] INFO {TRACE_LOGGER} - Sending message through endpoint : null resolving to address = http://erp.ukrposhta.loc/ws/api/_MR_DWH_KATALOG?sysparam={uri.var.sysparam}&call_in_async_mode=false [2024-02-01 11:07:51,201] INFO {TRACE_LOGGER} - SOAPAction: null [2024-02-01 11:07:51,201] INFO {TRACE_LOGGER} - WSA-Action: null [2024-02-01 11:07:51,208] INFO {TimeoutHandler} - This engine will expire all callbacks after GLOBAL_TIMEOUT: 120 seconds, irrespective of the timeout action, after the specified or optional timeout [2024-02-01 11:07:51,254] INFO {LogMediator} - {api:dwhCallEp} To: http://www.w3.org/2005/08/addressing/anonymous WSAction: SOAPAction: MessageID: urn:uuid:d16a7929-5a73-4bd9-9a52-d2431aed680b correlation_id: 04c91129-739e-4628-a206-ddb3bb047bc1 Direction: request JsonPayload = Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body/></soapenv:Envelope> [2024-02-01 11:07:51,273] INFO {CommonScriptMessageContext} - payload_json : [object Object] [2024-02-01 11:07:51,274] INFO {CommonScriptMessageContext} - payload_json : {} [2024-02-01 11:07:51,275] INFO {LogMediator} - {api:dwhCallEp} To: http://www.w3.org/2005/08/addressing/anonymous WSAction: SOAPAction: MessageID: urn:uuid:d16a7929-5a73-4bd9-9a52-d2431aed680b correlation_id: 04c91129-739e-4628-a206-ddb3bb047bc1 Direction: request payload = Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body/></soapenv:Envelope>
核心疑问
所有方式都拿到空Payload或空对象,但Postman直接调用后端服务能返回预期Payload,问题出在哪里?
问题分析与解决方案
核心原因
当前使用的是无阻塞的<call>中介,它不会等待后端服务的响应返回就继续执行后续的中介逻辑,所以后续的Log、Property、Script中介都只能拿到初始的空请求Payload,而非后端的响应。
从日志里的Direction: request也能佐证这一点——正常拿到响应时,这个字段应该是response。
解决步骤
- 将
<call>改为阻塞模式,添加<blocking/>子元素,让Synapse等待后端响应返回后再继续执行后续逻辑:
<call> <blocking/> <endpoint> <!-- 原endpoint配置保持不变 --> </endpoint> </call>
- 确保后端返回的是JSON格式,并且响应的
Content-Type头为application/json。如果后端返回的JSON没有正确设置Content-Type,Synapse可能无法自动识别为JSON Payload,导致json-eval和mc.getPayloadJSON()无法解析。可以在<call>之后添加<property>强制设置消息类型:
<call> <blocking/> <endpoint>...</endpoint> </call> <!-- 强制将消息类型设为JSON --> <property name="messageType" value="application/json" scope="axis2"/>
- 验证修改后的流程:添加阻塞模式后,后续的中介就能正确获取到后端返回的响应Payload,日志中的
Direction也会变为response。
修正后的完整inSequence示例
<inSequence> <log level="custom"> <property name="START" value="call into dwh storage"/> <property expression="get-property('uri.var.sysparam')" name="sysparam"/> </log> <call> <blocking/> <endpoint> <http method="get" statistics="enable" trace="enable" uri-template="http://my_path?sysparam={uri.var.sysparam}&call_in_async_mode=false"> <timeout> <duration>120000</duration> <responseAction>fault</responseAction> </timeout> <suspendOnFailure> <initialDuration>-1</initialDuration> <progressionFactor>1.0</progressionFactor> </suspendOnFailure> <markForSuspension> <retriesBeforeSuspension>0</retriesBeforeSuspension> </markForSuspension> </http> </endpoint> </call> <!-- 强制设置消息类型为JSON --> <property name="messageType" value="application/json" scope="axis2"/> <property expression="json-eval($[0])" name="JsonPayload" scope="default" type="STRING"/> <log level="full" separator="
"> <property expression="$ctx:JsonPayload" name="JsonPayload"/> </log> <script language="js"><![CDATA[var payload = mc.getPayloadJSON(); var log = mc.getServiceLog(); log.info("payload_json : " + payload); log.info("payload_json : " + JSON.stringify(payload)); mc.setProperty("payload_json",JSON.stringify(payload));]]></script> <log level="full" separator="
"> <property name="payload" expression="json-eval($)" /> </log> <respond/> </inSequence>
内容的提问来源于stack exchange,提问作者Evgeniy Zhurenko
相关产品推荐
相关产品推荐

