Search code examples
jsonxmlwso2wso2-micro-integrator

WSO2 EI: How to Iterate Over JSON Array and Call API Dynamically in a Scheduled Task?


I have defined a JSON array inside a property:

    <property name="systemList" type="STRING" value='[
    {"systemName":"Vodafone", "tokenEndpoint":"https://vodafone.com/oauth/token",         "client_id":"c6VwL5qIGQAhJfmZADoR", "client_secret":"dGfk4xKTGPcZ4MvMxpl5"},
    {"systemName":"TalkTalk", "tokenEndpoint":"https://talktalk.com/oauth/token", "client_id":"xyz123", "client_secret":"abc456"},
    {"systemName":"NewSystem", "tokenEndpoint":"https://newapi.com/oauth/token",     "client_id":"newClientID", "client_secret":"newSecret"}
    ]'/>

To iterate over this array, I am using the <iterate> mediator:

<iterate expression="json-eval($.systemList)" preservePayload="false" attachPath="$">
    <target>
        <sequence>
            <log category="INFO" level="custom">
                <property name="Step" value="Fetching token for a system" />
                <property name="Current System" expression="json-eval($.systemName)" />
            </log>
            <property name="TokenEndpoint" scope="default"
                expression="json-    eval($.tokenEndpoint)" />
            <property name="Content-Type" scope="transport" type="STRING"
                value="application/x-www-form-urlencoded" />
            <property name="Accept" scope="transport" type="STRING"
                value="application/json" />
            <property name="client_id" scope="default"
                expression="json-eval($.client_id)" />
            <property name="client_secret" scope="default"
                expression="json-eval($.client_secret)" />
            <send>
                <endpoint>
                    <http method="POST" uri-template="{get-property('TokenEndpoint')}">
                        <timeout>
                            <responseAction>discard</responseAction>
<duration>30000</duration>
                        </timeout>
                    </http>
                </endpoint>
            </send>
            <enrich>
                <source clone="true" type="body" />
                <target property="fetchedToken" type="property" />
            </enrich>
            <property expression="json-eval($.access_token)" name="storedToken"
                scope="registry" type="STRING" />
            <property expression="json-eval($.systemName)" name="systemName"
                scope="default" type="STRING" />
            <property name="registryTokenKey"
                expression="concat('storedToken_', get-property('systemName'))"
                scope="default" type="STRING" />
        </sequence>
    </target>
</iterate>

Should I use a different looping mechanism to iterate over the JSON array?


Solution

  • You can't directly iterate over a body. First you have to populate the message body with the contents of the property using a PayloadFactory mediator.

               <property name="systemList" type="STRING" value='[
                {"systemName":"Vodafone", "tokenEndpoint":"https://vodafone.com/oauth/token",         "client_id":"c6VwL5qIGQAhJfmZADoR", "client_secret":"dGfk4xKTGPcZ4MvMxpl5"},
                {"systemName":"TalkTalk", "tokenEndpoint":"https://talktalk.com/oauth/token", "client_id":"xyz123", "client_secret":"abc456"},
                {"systemName":"NewSystem", "tokenEndpoint":"https://newapi.com/oauth/token",     "client_id":"newClientID", "client_secret":"newSecret"}
                ]'/>
                <payloadFactory media-type="json">
                    <format>$1</format>
                    <args>
                        <arg evaluator="json" expression="$ctx:systemList"/>
                    </args>
                </payloadFactory>
                <log level="full"></log>
                <iterate expression="json-eval($)">
                    <target>
                        <sequence>
                            <log level="custom">
                                <property expression="json-eval($.systemName)" name="systemName"/>
                            </log>
                        </sequence>
                    </target>
                </iterate>