WSO2 ESB - How to use filter inside iterate mediator
WSO2 ESB's Iterate mediator plays a very powerful role in the Splitter Enterprise Integration Pattern. Splitter Enterprise Integration Pattern is used when messages contain multiple elements that might have to be processed in different ways. The Splitter breaks out the composite message into a series of individual messages, each containing data related to one item.
WSO2 ESB Iterate mediator split the message based on a given expression and process them separately. So think about a use case like you are getting multiple order items and you want to enrich each order item, by calling another endpoint and finally we need to aggregate all the enriched items.
There you can use the Iterate mediator and after that aggregate mediator to aggregate all the enriched items.
Example:
ESB Proxy Service:
Request:
Let me expand this use case. Assume we just need to enrich some of the items only. To do that, we have to use filter mediator inside the Iterate mediator. If we update our existing code with the filter mediator logic, it will never reach to the aggregate on-complete logic. The reason is aggregate mediator waits for total messages that came into the iterate mediator, but due to the filter logic, some messages aren't supposed to be included in the aggregation. To avoid this, what we can do is, we have to define this Iterate mediator inside the In-Sequence and after all the logic inside the Iterate mediator( before the tag) you have to add a loopback mediator and need to move aggregate mediator into Out-Sequence. This will call the aggregate mediator for all the messages.
ESB Proxy Service:
<?xml version="1.0" encoding="UTF-8"?> <proxy xmlns="http://ws.apache.org/ns/synapse" name="IteService" transports="http,https" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence> <iterate id="aggregateid" preservePayload="true" attachPath="//Collection" expression="//Collection/Job" sequential="true"> <target> <sequence> <enrich> <source type="body" clone="true"/> <target type="property" property="originalRequest"/> </enrich> <payloadFactory media-type="xml"> <format> <p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org"> <in>$1</in> </p:echoInt> </format> <args> <arg evaluator="xml" expression="$body/Collection/Job/Id"/> </args> </payloadFactory> <property name="SOAPAction" value=""echoInt"" scope="transport" type="STRING"/> <call> <endpoint> <address uri="https://localhost:8243/services/echo"/> </endpoint> </call> <property xmlns:ns="http://echo.services.core.carbon.wso2.org" name="echoResponse" expression="$body/ns:echoIntResponse" scope="default" type="OM"/> <enrich> <source type="property" clone="true" property="originalRequest"/> <target type="body"/> </enrich> <enrich> <source type="property" clone="true" property="echoResponse"/> <target action="child" xpath="$body/Collection"/> </enrich> </sequence> </target> </iterate> <property name="Collections" scope="default"> <Collections xmlns=""/> </property> <aggregate id="aggregateid"> <completeCondition> <messageCount min="-1" max="-1"/> </completeCondition> <onComplete expression="$body/Collection" enclosingElementProperty="Collections"> <respond/> </onComplete> </aggregate> </inSequence> </target> <description/> </proxy>
Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <Collection> <Job> <Id>12345</Id> </Job> <Job> <Id>12346</Id> </Job> </Collection> </soapenv:Body> </soapenv:Envelope>
Let me expand this use case. Assume we just need to enrich some of the items only. To do that, we have to use filter mediator inside the Iterate mediator. If we update our existing code with the filter mediator logic, it will never reach to the aggregate on-complete logic. The reason is aggregate mediator waits for total messages that came into the iterate mediator, but due to the filter logic, some messages aren't supposed to be included in the aggregation. To avoid this, what we can do is, we have to define this Iterate mediator inside the In-Sequence and after all the logic inside the Iterate mediator( before the tag) you have to add a loopback mediator and need to move aggregate mediator into Out-Sequence. This will call the aggregate mediator for all the messages.
Example:
ESB Proxy Service:
<?xml version="1.0" encoding="UTF-8"?> <proxy xmlns="http://ws.apache.org/ns/synapse" name="IteFilterService" transports="http,https" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence> <iterate id="aggregateid" preservePayload="true" attachPath="//Collection" expression="//Collection/Job" sequential="true"> <target> <sequence> <property name="JobId" expression="string(//Job/Id)" scope="default" type="STRING"/> <filter source="$ctx:JobId" regex="[0-9]+"> <log level="full"> <property name="JobId" expression="string(//Job/Id)"/> </log> <enrich> <source type="body" clone="true"/> <target type="property" property="originalRequest"/> </enrich> <payloadFactory media-type="xml"> <format> <p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org"> <in>$1</in> </p:echoInt> </format> <args> <arg evaluator="xml" expression="$ctx:JobId"/> </args> </payloadFactory> <property name="SOAPAction" value=""echoInt"" scope="transport" type="STRING"/> <call> <endpoint> <address uri="https://localhost:8243/services/echo"/> </endpoint> </call> <property xmlns:ns="http://echo.services.core.carbon.wso2.org" name="echoResponse" expression="$body/ns:echoIntResponse" scope="default" type="OM"/> <enrich> <source type="property" clone="true" property="originalRequest"/> <target type="body"/> </enrich> <enrich> <source type="property" clone="true" property="echoResponse"/> <target action="child" xpath="$body/Collection"/> </enrich> </filter> <loopback/> </sequence> </target> </iterate> </inSequence> <outSequence> <property name="Collections" scope="default"> <Collections xmlns=""/> </property> <aggregate id="aggregateid"> <completeCondition> <messageCount min="-1" max="-1"/> </completeCondition> <onComplete expression="$body/Collection" enclosingElementProperty="Collections"> <respond/> </onComplete> </aggregate> </outSequence> </target> <description/> </proxy>
Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <Collection> <Job> <Id>AAAA</Id> </Job> <Job> <Id>12345</Id> </Job> <Job> <Id>12346</Id> </Job> </Collection> </soapenv:Body> </soapenv:Envelope>
Comments