Search code examples
wso2wso2-esbwso2-enterprise-integratorwso2-micro-integrator

Why is the aggregate mediator is not working after the Iterator(for construction an json payload using Payload factory) WSO2 7.2.0 (mi-4.0.0)


When i was trying to construct an JSON payload by Iterating the JSON array by using Iterator and extracting the specific field from the payload and trying to form an Json Payload by using Payload factory inside an Iterator after Iterator i was trying to set an aggregate mediator to aggregate all the json response and trying to set into the context for transformation and responding back to the Client

Sequence for generation of Desired Output by using Iterator with Aggregate mediator

`<?xml version="1.0" encoding="UTF-8"?>
<sequence name="AGGREGATE_CHECK" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
    <iterate continueParent="true" expression="//Customers" id="line-Item-Iterator" sequential="true">
        <target>
            <sequence>
                <property expression="//Name" name="Name" scope="default" type="STRING"/>
                <property expression="//DOJ" name="Doj" scope="default" type="STRING"/>
                <payloadFactory media-type="json">
                    <format>{
                            "NAME": "$1",
                            "DOJ": $2,
                            }</format>
                    <args>
                        <arg evaluator="xml" expression="$ctx:Name"/>
                        <arg evaluator="xml" expression="$ctx:Doj"/>
                    </args>
                </payloadFactory>
                <log level="full"/>
            </sequence>
        </target>
    </iterate>
    <log>
        <property name="after iterator" value="coming out for aggregator"/>
    </log>
    <aggregate id="line-Item-Iterator">
        <completeCondition>
            <messageCount max="-1" min="-1"/>
        </completeCondition>
        <onComplete aggregateElementType="root" expression="json-eval($)">
            <property expression="$body/*" name="response" scope="operation" type="OM"/>
            <log level="full"/>
        </onComplete>
    </aggregate>
    <payloadFactory media-type="json">
        <format>$1</format>
        <args>
            <arg evaluator="xml" expression="get-property('operation','response')"/>
        </args>
    </payloadFactory>
    <log>
        <property expression="$body/*" name="Aggregated-response"/>
    </log>
</sequence>
`

Note:

  1. If I try to log the response inside the iterator logging is happening with the proper output payload
  2. Tried by changing the continueParent in iterate mediator to false as well no proper output
  3. If I tried logging inside the onComplete block we are not getting any logs inside the Aggregate mediator Needed help to understand this issue and solve it Thanks in Advance enter image description here

INPUT PAYLOAD

`{
    "data": {
        "level": "asss",
        "Info": {
            "Customers": [
                [
                    {
                        "Name": "Ram",
                        "Age": 26,
                        "city": "TX",
                        "DOJ": "26-06-2002"
                    },
                    {
                        "Name": "Shri",
                        "Age": 29,
                        "city": "TX",
                        "DOJ": "12-06-1999"
                    },
                    {
                        "Name": "Reena",
                        "Age": 25,
                        "city": "TX",
                        "DOJ": "22-06-2007"
                    }
                ]
            ]
        }
    },
    "ms": {}
}`

excepted output

[
    {
        "Name": "Ram",
        "DOJ": "26-06-2002"
    },
    {
        "Name": "Shri",
        "DOJ": "12-06-1999"
    },
    {
        "Name": "Reena",
        "DOJ": "22-06-2007"
    }
]

Solution

  • Iterate Mediator should be used when you are calling a Backend in each iteration cycle. You should be using the Foreach Mediator if you just want to Iterate over a payload.

    Having said that, for the mentioned usecase you don't really need to Iterate the Payload. You can simply use the Enrich Mediator to remove the elements you don't need.

    <enrich>
        <source clone="false" xpath="json-eval($.[*].city,$.[*].Age)"/>
        <target action="remove" type="body"/>
    </enrich>
    

    Update

    Here is the for-each solution. You can't use the aggregate mediator with the Foreach Mediator. Foreach Mediator will automatically append the Payload to its parent element.

    <foreach expression="json-eval($)" id="1">
        <sequence>
            <payloadFactory media-type="json">
                <format>{
                    "NAME": "$1",
                    "DOJ": "$2"
                    }
                    </format>
                <args>
                    <arg evaluator="json" expression="$.Name"/>
                    <arg evaluator="json" expression="$.DOJ"/>
                </args>
            </payloadFactory>
        </sequence>
    </foreach>
    

    Update 02 There are different ways to do this, the following is one way. Another way is having the Enrich after the foreach and removing the parent element.

    <enrich>
        <source clone="true" xpath="json-eval($.data.Info.Customers[0])"/>
        <target type="body"/>
    </enrich>
    <foreach expression="json-eval($)" id="1">
        <sequence>
            <log level="full"/>
            <payloadFactory media-type="json">
                <format>{
                    "NAME": "$1",
                    "DOJ": "$2"
                    }
                    </format>
                <args>
                    <arg evaluator="json" expression="$.Name"/>
                    <arg evaluator="json" expression="$.DOJ"/>
                </args>
            </payloadFactory>
        </sequence>
    </foreach>