WSO2 APIM PayloadFactory报SOAP禁止含处理指令异常排查
问题背景
在WSO2 APIM中配置入站序列,实现JSON格式请求负载到XML格式的转换。
此前遇到单元素数组转换故障:JSON中的单元素数组会被错误转换为XML对象,通过在synapse.properties文件中添加如下配置修复了该问题:
synapse.json.to.xml.processing.instruction.enabled=true
启用该配置后,传入包含多元素数组的JSON请求时,APIM抛出如下异常:
ERROR {org.apache.synapse.mediators.base.SequenceMediator} - SOAP message MUST NOT contain Processing Instructions(PI) {org.apache.synapse.mediators.base.SequenceMediator} org.apache.axiom.om.OMException: SOAP message MUST NOT contain Processing Instructions(PI)
排查故障序列后确认:请求体传入PayloadFactory中介的参数时,内容被自动添加了如下XML处理指令:
<?xml-multiple ListPacks?>
触发故障的简化序列代码如下:
<?xml version="1.0" encoding="UTF-8"?> <sequence name="seq_header_v2" trace="disable" xmlns="http://ws.apache.org/ns/synapse"> <property expression="//soapenv:Body/*" name="soapBody" scope="default" type="STRING" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"/> <payloadFactory media-type="xml"> <format> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <sec:Header xmlns:sec="http://www.pruebas.com/XSD/SecurityHeader/"> <sec:User>$1</sec:User> </sec:Header> </soapenv:Header> <soapenv:Body> $2 </soapenv:Body> </soapenv:Envelope> </format> <args> <arg evaluator="xml" expression="$ctx:api.ut.consumerKey"/> <arg evaluator="xml" expression="get-property('soapBody')"/> </args> </payloadFactory> </sequence>
测试使用的JSON请求样例:
{ "ListPacksFullOnline": { "typePack": "006", "numPack": "632", "ListPacks": [{ "relationPerson": "1", "numOrder": 1 }, { "relationPerson": "1", "numOrder": 2 } ] } }
已排除消息格式化器(Formatters)、构建器(Builders)的配置错误,需要定位序列本身的配置问题并给出修复方案。
问题根因
- 核心问题是
soapBody属性的配置类型与后续使用逻辑不匹配:该属性被定义为STRING类型,取值时通过XPath表达式//soapenv:Body/*提取节点内容,传入PayloadFactory时又指定参数求值器为xml。断裂的类型转换链路导致Synapse跳过了正常的临时处理指令清理流程,<?xml-multiple?>标记直接残留到XML解析环节。 - SOAP规范明确禁止消息中包含XML处理指令(PI),底层AXIOM对象模型检测到这类PI时会直接抛出合规性异常,也就是日志中打印的错误。
- 配置项
synapse.json.to.xml.processing.instruction.enabled=true的原生逻辑,就是在多值数组对应的父节点前插入<?xml-multiple 节点名?>临时标记,以此区分单对象和单元素数组,解决单元素数组转XML的类型识别错误。正常消息构建流程中,Synapse会在生成最终XML消息树前自动移除这些临时标记,只有当内容以纯字符串形式传递、绕过了标记清理逻辑时,PI才会残留触发报错。
修复方案
二选一即可,优先选方案1,兼容性更好无额外副作用。
方案1:修正属性类型(推荐)
将soapBody属性的类型从STRING改为OM(XML节点类型),其余逻辑保持不变。修改后Synapse会按照XML节点的正常传递流程处理内容,自动清理临时的xml-multiple处理指令,同时保留数组转换的正确结构,不会触发SOAP合规性校验错误。
修改后的属性配置如下:
<property expression="//soapenv:Body/*" name="soapBody" scope="default" type="OM" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"/>
方案2:调整PayloadFactory参数求值规则
如果业务上必须保留soapBody为字符串类型,将第二个入参的求值器从xml改为text,让PayloadFactory把内容作为纯文本节点插入,不会触发XML PI的合规性校验。注意该方案需要提前处理XML特殊字符转义问题,避免生成格式非法的XML。
修改后的参数配置如下:
<arg evaluator="text" expression="get-property('soapBody')"/>
内容的提问来源于stack exchange,提问作者Rusty23
相关产品推荐
相关产品推荐

