如何在WSO2 EI 6.2.0的REST API中从OnComplete AggregateMediator获取属性
问题分析与解决方案
看起来你遇到的核心问题有两个:一是主序列没有等待Aggregate完成就执行后续逻辑,导致聚合结果还没生成就发送了请求;二是OutSequence里的ForEach没有正确指向聚合后的ID集合,加上SQL语句的小错误,导致DBReport没有执行。
下面是具体的修复步骤:
1. 调整InSequence,确保Aggregate完成后再发送请求
原来的InSequence中,Iterate和Aggregate是异步执行的,主序列会直接跑到后面的payloadFactory和send,这时候Aggregate的onComplete还没触发,message属性是空的。你需要把payloadFactory和send移到onComplete内部,这样只有当所有迭代分支完成、聚合结果生成后才会执行发送逻辑:
<inSequence> <property expression="count(//parameter/objects)" name="count" scope="default" type="STRING"/> <iterate expression="//parameter/objects" id="iterate1" sequential="true"> <target> <sequence> <property expression="//objects/text()" name="element1" scope="default" type="STRING"/> <sequence key="getIdOfElement1"/> <property expression="json-eval($.result.id)" name="el1id" scope="default" type="STRING"/> <payloadFactory media-type="xml"> <format> <ids xmlns=""> <id>$1</id> </ids> </format> <args> <arg evaluator="xml" expression="get-property('el1id')"/> </args> </payloadFactory> </sequence> </target> </iterate> <aggregate id="iterate1"> <completeCondition timeout="10"> <messageCount max="-1" min="{get-property('count')}"/> </completeCondition> <onComplete expression="//ids"> <property expression="$body" name="message" scope="operation" type="OM"/> <!-- 把原来的payloadFactory和send移到这里 --> <payloadFactory media-type="xml"> <format> <result xmlns="">$1</result> </format> <args> <arg evaluator="xml" expression="get-property('operation','message')"/> </args> </payloadFactory> <send> <endpoint key="NamedEP"/> </send> </onComplete> </aggregate> <!-- 移除原来这里的payloadFactory和send --> </inSequence>
2. 修复OutSequence里的ForEach与DBReport问题
现在OutSequence处理的是NamedEP返回的响应,而聚合后的ID集合存在operation作用域的message属性里,你需要先把这个属性的内容加载到当前消息体,再调整ForEach的遍历表达式,同时修正SQL语句的参数占位符:
<outSequence> <property expression="get-property('operation', 'message')" name="IDs" scope="default" type="OM"/> <!-- 将聚合后的ID集合设置为当前消息体 --> <payloadFactory media-type="xml"> <format>$1</format> <args> <arg evaluator="xml" expression="$ctx:IDs"/> </args> </payloadFactory> <log level="custom"> <property expression="//ids" name="========== LIST IDs =========="/> </log> <!-- 修改ForEach表达式,遍历每个id元素,而不是整个ids节点 --> <foreach expression="//ids/id" id="foreach1"> <sequence> <log level="custom"> <property expression="./text()" name="========== ID =========="/> </log> <dbreport> <connection> <pool> <dsName>A_DS</dsName> </pool> </connection> <statement> <!-- 修正SQL:添加第二个参数占位符 --> <sql>INSERT INTO "table" ("field1", "id") VALUES (?, ?)</sql> <parameter expression="get-property('field1')" type="VARCHAR"/> <!-- 用./text()获取当前迭代的id值 --> <parameter expression="./text()" type="INTEGER"/> </statement> </dbreport> </sequence> </foreach> <!-- 保留原来的响应构建逻辑 --> <payloadFactory media-type="json"> <format> [{ "field1" : "$1" }] </format> <args> <arg evaluator="xml" expression="get-property('field1')"/> </args> </payloadFactory> <property name="messageType" scope="axis2" type="STRING" value="application/json"/> <property expression="json-eval($.)" name="response" scope="default" type="STRING"/> <send/> </outSequence>
关键说明
- Aggregate的异步特性:WSO2 EI中,Iterate即使设置了
sequential="true",主序列也不会等待所有迭代分支完成,必须把依赖聚合结果的逻辑放到onComplete内部。 - ForEach遍历对象:原来的
//ids是遍历整个父节点,每次迭代拿到的是完整的<ids>,改成//ids/id才会遍历每个独立的ID元素。 - SQL参数错误:你的INSERT语句有两个字段,但原来只写了一个
?,这会导致数据库执行失败,必须补上第二个占位符。
这样调整后,应该就能正常遍历聚合后的ID并执行DBReport了。
内容的提问来源于stack exchange,提问作者yonaukha
相关产品推荐
相关产品推荐

