WSO2 ESB中Iterator与Script Mediator计算成绩求和异常问题
WSO2 ESB Iterator Mediator累加成绩总和异常解决方法
问题现象
使用Iterator Mediator遍历学生成绩,配合Script Mediator累加totalnote变量时,无法实现持续累加效果:每次计算都是初始值与当前成绩直接相加,而非基于上一次的累加结果继续计算。例如初始值设为0时,日志显示ms值为13、15、16、17,而非预期的13→28→44→61。
问题原因
Iterator Mediator默认采用多线程并行处理每个迭代分支,每个分支在执行时都会读取totalnote的初始值,分支之间的变量修改互相隔离,无法共享更新后的结果,导致累加失效。
解决方案
方案1:开启Iterator顺序执行模式
通过为Iterator添加sequential="true"属性,强制迭代分支按顺序单线程执行,这样每个分支都能获取到上一次修改后的totalnote值,实现正常累加。
修改后的核心配置:
<property name="totalnote" scope="default" type="INTEGER" value="0"/> <!-- 开启顺序迭代,确保分支按顺序执行 --> <iterate expression="//etudiants/etudiant" sequential="true"> <target> <sequence> <property expression="json-eval($.etudiant.note)" name="note" scope="default" type="INTEGER"/> <log level="custom"> <property expression="get-property('note')" name="msg"/> </log> <script language="js"><![CDATA[ var i = parseInt(mc.getProperty("note")); var totalnote = parseInt(mc.getProperty("totalnote")); totalnote += i; mc.setProperty("totalnote", totalnote.toString()); ]]></script> <log level="custom"> <property expression="get-property('totalnote')" name="ms"/> </log> </sequence> </target> </iterate> <respond/>
方案2:使用Aggregate Mediator聚合计算
若需保留Iterator的并行处理性能(适合数据量大的场景),可在迭代分支中收集单个成绩,最后通过Aggregate Mediator汇总所有成绩并计算总和。
示例配置:
<property name="totalnote" scope="default" type="INTEGER" value="0"/> <iterate expression="//etudiants/etudiant" id="studentIterator"> <target> <sequence> <property expression="json-eval($.etudiant.note)" name="note" scope="default" type="INTEGER"/> <log level="custom"> <property expression="get-property('note')" name="msg"/> </log> <!-- 将当前成绩封装为JSON消息,供聚合器收集 --> <payloadFactory media-type="json"> <format>{"note": $1}</format> <args> <arg evaluator="xml" expression="$ctx:note"/> </args> </payloadFactory> <send> <endpoint><default/></endpoint> </send> </sequence> </target> </iterate> <!-- 聚合所有分支结果并计算总和 --> <aggregate id="studentIterator"> <completeCondition> <messageCount max="-1" min="-1"/> </completeCondition> <onComplete expression="//jsonObject"> <script language="js"><![CDATA[ var noteList = mc.getPayloadJSON().jsonObject; var total = 0; noteList.forEach(function(item) { total += parseInt(item.note); }); mc.setProperty("totalnote", total.toString()); ]]></script> <log level="custom"> <property expression="get-property('totalnote')" name="最终成绩总和"/> </log> <respond/> </onComplete> </aggregate>
方案对比
- 方案1:配置简单,单线程执行无并发问题,适合数据量较小的场景
- 方案2:保留并行处理能力,聚合阶段统一计算,性能更优,适合数据量大的场景
内容的提问来源于stack exchange,提问作者rania ben salem
相关产品推荐
相关产品推荐

