Search code examples
wso2wso2-enterprise-integrator

WSO2 Enterprise Integrator iterate and aggregate, issue with aggregation


I want to perform parallel API calls in iterate mediator then to group the responses using the aggregate mediator. The format is JSON. I am using this code:

 [...code in iterate]
<script language="js">var c = mc.getProperty("account");
                                  
                                    print("Value : "+ c );
                                    mc.setProperty("concatValue", c);
                                    mc.setPayloadJSON({"result":{"account" : c}});</script>
                                    
<log>
                 <property expression="json-eval($)" name="JSON-Payload in sequence"/>
              </log>
              

             </sequence>
       

        </target>
     </iterate>
        
    <property name="Aggregated_Responses" scope="default" value = "{}"/>
        
    <aggregate id="it1">
        <completeCondition>
          <messageCount max="-1" min="-1"/>
        </completeCondition>
        <onComplete expression="json-eval($)" enclosingElementProperty="Aggregated_Responses">
             <log>
                 <property expression="json-eval($)" name="JSON-Payload in oncomplete"/>
              </log>
        </onComplete>
   </aggregate>
  <loopback/>
</sequence>

The aggregation is not working, if i add loopback isnide the on complete, it will return one json and the second one will print a message in the logs saying that the response was already sent. Can someone help me solve this issue? And an additional question: do the work inside the iterate is usually done in parallel or in series?


Solution

  • Final working solution with some explanation:

    <payloadFactory media-type="json">
    <format>
                {               
                    "payloadss": [{
    "account":"99999999999"
                        
                    },{
    "account":"6666666666"
                        
                    }]
                }
                </format>
    <args/>
     </payloadFactory>
    <iterate attachPath="json-eval($.payloadss)" expression="json-eval($.payloadss)" 
     id="iterate-over" preservePayload="true" continueParent="false">
    <target>
        <sequence>
            <property expression="json-eval($.payloadss.account)" name="accounte" scope="default" type="STRING"/>
            <call-template target="call_template_a">
                <with-param name="url" value="/getaccount"/>
                <with-param name="method_type" value="get"/>
            </call-template>
                [.. apply error check etc .. ] 
       
            </sequence>
    </target>
    </iterate>
            [ use same id as the iterate otherwise it wont work ]
             <property name="Aggregated_Responses" scope="default">
                <jsonObject/>
             </property>
         <aggregate description="iterate-over" id="iterate-over">
       <completeCondition timeout="120">
         <messageCount max="-1" min="-1"/>
       </completeCondition>
    
       [ use expression like this otherwise it wont work, you can even add at the end / 
          your field name if needed ]
    
    <onComplete xmlns:ns="http://org.apache.synapse/xsd" expression="$body/*[1]" 
       enclosingElementProperty="Aggregated_Responses">
    
      [ here the json will be as payload, optionnally you can have a script mediator 
      to map the value and change in their names, otherwise you can just return the 
          result and it
         will be aggregated together]
    
      <property expression="json-eval($)" name="bbbb"/>
        <script language="js"><![CDATA[
      var dataFull = JSON.parse(mc.getProperty('bbbb')); 
                var responseList = [];
            var newJson = JSON.parse("{}");
    
                for (i = 0; i < dataFull.length; i++) {
           
                    item = dataFull[i];
                    newJson.newAccountNumber = item.accountNumber;
                            responseList.push(newJson);
                }
                
                mc.setProperty("responseList", JSON.stringify(responseList));
                ]]></script>
        <payloadFactory media-type="json">
            <format>
                                {
                                        "data": $2
                                }
    
                            </format>
            <args>
                <arg evaluator="xml" expression="get-property('responseList')"/>
            </args>
        </payloadFactory>
    
    [ the send should be at this level, the code just after will not be executed] 
        <send/>
    </onComplete>