Tuesday, July 21, 2015

How to get WSO2 ESB iterate mediator's iteration count

WSO2 ESB's iterate mediator is very useful to implement the Splitter Enterprise Integration Pattern.
It splits the message based on a given expression and process separately.

This sample shows how to get the iteration count.

Sample request

<symbols>
   <symbol>WSO2</symbol>
   <symbol>MSFT</symbol>
   <symbol>IBM</symbol>
   <symbol>ADBE</symbol>
   <symbol>AAPL</symbol>
   <symbol>ORCL</symbol>
   <symbol>RHT</symbol>
   <symbol>FB</symbol>
   <symbol>TWTR</symbol>
   <symbol>LNKD</symbol>
</symbols>

Sample proxy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="count_iterate"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <property name="it_count" value="0" scope="operation"/>
         <iterate expression="//symbols/symbol" sequential="true">
            <target>
               <sequence>
                  <property name="synapse_it_count" expression="get-property('operation', 'it_count')"/>
                  <script language="js">var cnt_str = mc.getProperty('synapse_it_count');
     var cnt = parseInt(cnt_str);
     cnt++;
     mc.setProperty('synapse_it_count', cnt.toString());</script>
                  <property name="it_count" expression="get-property('synapse_it_count')" scope="operation"/>
                  <aggregate>
                     <completeCondition>
                        <messageCount min="-1" max="-1"/>
                     </completeCondition>
                     <onComplete expression="//symbol">
                        <log level="custom">
                           <property name="number of symbols" expression="get-property('operation','it_count')"/>
                        </log>
                        <respond/>
                     </onComplete>
                  </aggregate>
               </sequence>
            </target>
         </iterate>
      </inSequence>
   </target>
   <description/>
</proxy>                               

Idea behind this sample is, using the 'operation' scope property[line 10]to increment the count in each iteration. The operation scope property cannot be read inside the script mediator (it supports only the synapse scope property) so introducing a synapse scope property[line 14] to be used inside the script mediator. After script mediator the value is assigned again to the operation scope property [line 19].
If we didn't use the operation scope property the value will not be remain in the next iteration. Also please note that the iterate mediator is in the sequential mode.

Getting the count like this method is useful when we have to map two different array based on its indexes. But please note if you want to only get the number of nodes in the message you can use the XPath function 'count' as follows

<property name="total_symbols" expression="count(//symbol)"/>


UPDATE on 28/09/2018:
The proxy can be simplified as follows by using the XPATH's number() function. Instead of using the script mediator to increment the count
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="count_iterate"
       startOnLoad="true"
       statistics="disable"
       trace="disable"
       transports="https,http">
   <target>
      <inSequence>
         <property name="it_count" scope="operation" value="0"/>
         <iterate expression="//symbols/symbol" sequential="true">
            <target>
               <sequence>
                  <property expression="number(get-property('operation','it_count') +1)"
                            name="it_count"
                            scope="operation"/>
                  <aggregate>
                     <completeCondition>
                        <messageCount max="-1" min="-1"/>
                     </completeCondition>
                     <onComplete expression="//symbol">
                        <log level="custom">
                           <property expression="get-property('operation','it_count')"
                                     name="number of symbols"/>
                        </log>
                        <respond/>
                     </onComplete>
                  </aggregate>
               </sequence>
            </target>
         </iterate>
      </inSequence>
   </target>
   <description/>
</proxy> 

To get rid of the decimal place in the result, we can use the string() and round() XPATH functions as follows

<property expression="string(round(get-property('operation','it_count')))" name="number of symbols"/>

5 comments:

  1. Thank you. This is very helpful video. You save my time. Keep it up

    ReplyDelete
  2. Hey Sir/mam
    I have senario like I have post message,

    5


    based on that count value I should call itterator
    I have tried Like storing bookCount value in property Meditor like this


    and Calling itterator like

    I am Getting error like
    ERROR - SynapseXPath Evaluation of the XPath expression get-property("Count_Book") resulted in an error

    can please address where i am going Wrong
    ;;




    ReplyDelete
    Replies
    1. i got null values it_count ### = null

      Delete
    2. Hello,
      Did you use the xpath expression or the property with operation scope method. Please share me your configuration.
      Further as I remember this was tested with ESB 4.9.0 or 5.0.0, So might have to do small changes with newer versions

      Delete