Search code examples
iteratorwso2wso2-micro-integrator

Iterate mediator in now working sequentially with sequential="true"


I have this input

<uList>
    <user>
      <id>12</id>
    </user>
    <user>
      <id>13</id>
    </user>
    <user>
      <id>14</id>
    </user>
    <user>
      <id>15</id>
    </user>
</uList>

I want to iterate this list and call to scim GET API. But I want to do this in sequentially. (One by one API call)

I used below iterate mediator. But still it is working in parallel. What is the issue here?

 <iterate expression="//*[local-name()='user']" sequential="true">
              <target>
                 <sequence>
                    <property name="uri.var.uuid" expression="//*[local-name()='scimId']" scope="default" type="STRING"/>
                    <log level="custom">
                       <property name="uri.var.uuid" expression="//*[local-name()='scimId']"/>
                    </log>
                    <property name="NO_ENTITY_BODY" value="true" scope="axis2" type="BOOLEAN"/>
                    <header name="Content-Type" scope="transport" action="remove"/>
                    <call>
                       <endpoint>
                          <http method="GET" uri-template="https://run.mocky.io/v3/ebc2eef8-6012-4fbb-b0b5-d063b68c6400"/>
                       </endpoint>
                    </call>
                    <property name="userName" expression="json-eval($.userName)" scope="default" type="STRING"/>
                    <payloadFactory media-type="json">
                       <format>{"responses":{ "username":"$1", "scimId":"$2"}}</format>
                       <args>
                          <arg evaluator="xml" expression="$ctx:userName"/>
                          <arg evaluator="xml" expression="$ctx:uri.var.uuid"/>
                       </args>
                    </payloadFactory>
                    <script language="js">java.lang.Thread.sleep(5000);</script>
                 </sequence>
              </target>
           </iterate>

Solution

  • The issue you're facing is likely due to the fact that although you've set sequential="true" in the iterate mediator, the HTTP calls inside the iteration are still happening concurrently because the default behavior of the call mediator is asynchronous.

    To make the HTTP calls sequential within the iteration, you need to explicitly make them blocking calls. You can achieve this by adding blocking="true" attribute to the call mediator.

    If you're using a blocking call mediator within an iterate mediator, the flow will indeed wait for each iteration to complete before proceeding to the next step. In this case, if you want to aggregate the responses from each iteration, you won't be able to do it directly after the iterate mediator because the flow will not reach there until all iterations are complete.

    To address this, you can utilize a loopback mediator within each iteration to send the response back to the out sequence, where you can aggregate the responses after all iterations are complete.

    Here's how you can modify your sequence.

        <iterate expression="//*[local-name()='user']" sequential="true">
            <target>
                <sequence>
                    <!-- Your existing logic for making HTTP call -->
                    <!-- Remember to set blocking="true" in the call mediator -->
                    <call blocking="true">
                        <endpoint>
                            <http method="GET" uri-template="https://run.mocky.io/v3/ebc2eef8-6012-4fbb-b0b5-d063b68c6400"/>
                        </endpoint>
                    </call>
                    <!-- Store response in a property -->
                    <property name="responseBody" expression="$body" scope="default" type="STRING"/>
                    <!-- Loopback mediator to send response back to main sequence -->
                    <loopback/>
                </sequence>
            </target>
        </iterate>
    
    
    
    <!-- Aggregate responses in the out sequence -->
    <outSequence>
        <!-- Iterate through the stored responses -->
        <iterate expression="//property[@name='response_*']">
            <target>
                <sequence>
                    <!-- Add each response to the aggregate mediator -->
                    <aggregate>
                        <completeCondition>
                            <messageCount min="-1" max="-1"/>
                        </completeCondition>
                        <onComplete expression="$body">
                            <!-- Your aggregation logic here -->
                        </onComplete>
                    </aggregate>
                </sequence>
            </target>
        </iterate>
    </outSequence>