1
votes

I have an endpoint in wso2 integrator, wich receive some parameters, call some rest apis, and produce a new response.

I created a sequence for each rest api call, wich will get the properties and make the specific call. Then with a script mediator, i'm creating a new payload with the response, and putting it in a property. Example: myResponseA, myResponseB, myResponseC.

My main endpoint have an IN sequence with only a clone mediator and a loopback tag. The clone mediator have a target for each sequence described above, like:

<clone continueParent="false" sequential="true">
    <target sequence="mySequenceA">
    </target>
    <target sequence="mySequenceB">
    </target>
</clone>

<loopback />

My main endpoint have an OUT sequence with a payloadFactory and a send tag, like:

<payloadFactory media-type="json">
    <format>
        <![CDATA[
            {
                "myResponseA": $1,
                "myResponseB": $2
            }
        ]]>
    </format>
    <args>
        <arg expression="get-property('myResponseA')"/>
        <arg expression="get-property('myResponseB')"/>
    </args>
</payloadFactory>

<property name="HTTP_SC" scope="axis2" type="STRING" value="200"/>
<send/>

The problem is, the OUT sequence is called multiple times, one for each sequence in Clone mediator.

I tried to use the Aggregate mediator with no luck, 'coz my apis is restful and i don't know how to use the aggregate expression. I dont even need it, because i put the responses in different properties and read it in my payloadFactory.

How to execute my OUT sequence only one single time when all my sequences return in clone mediator? or there is another mediator i should use?

Obs.: I have to call those apis in parallel, because each one will take some time, and i will call 5~10 each time.

2

2 Answers

3
votes

Can you try this as a startup :-D

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="PoCCloneAggregate"
       transports="http"
       startOnLoad="true"
       statistics="enable"
       trace="enable">
   <description/>
   <target>
      <inSequence>
              <property name="enclosing_element" scope="default"> 
                <result xmlns=""/> 
              </property>
              <clone continueParent="false" sequential="true">
                    <target>
                        <sequence>
                           <log level="custom">
                             <property name="CLON" value="clon 1"/>
                           </log>
                           <payloadFactory media-type="json">
                            <format>
                              {"data":
                               {"temperatura":"10",
                               "id":"1"}}
                            </format>
                            <args>
                            </args>
                           </payloadFactory>
                           <loopback/>
                         </sequence>
                    </target>
                    <target>
                        <sequence>
                           <log level="custom">
                             <property name="CLON" value="clon 2"/>
                           </log>
                           <payloadFactory media-type="json">
                            <format>
                             {"data":
                              {"temperatura":"20",
                               "id":"2"}}
                            </format>
                            <args>
                            </args>
                           </payloadFactory>
                           <loopback/>
                        </sequence>
                    </target>
                    <target>
                        <sequence>
                           <log level="custom">
                             <property name="CLON" value="clon 3"/>
                           </log>
                           <payloadFactory media-type="json">
                            <format>
                             {"data":
                              {"temperatura":"30",
                               "id":"3"}}
                            </format>
                            <args>
                            </args>
                           </payloadFactory>
                           <loopback/>
                        </sequence>
                    </target>
                </clone>
      </inSequence>
      <outSequence>
         <log level="full"/>
         <aggregate>
            <completeCondition>
              <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete  expression="$body/jsonObject" xmlns:s12="http://www.w3.org/2003/05/soap-envelope" 
xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" enclosingElementProperty="enclosing_element">
               <log level="custom" separator=",">
                  <property name="MessageFlow" value="======================= Respuestas Agregadas. ==============="/>
               </log>
               <log level="full" separator=","/>
               <send/>
            </onComplete>
         </aggregate>
      </outSequence>
      <faultSequence/>
   </target>
</proxy>
2
votes

You have to use aggragate mediator, the goal is to route each response to a single sequence containing this aggregate.

For example, if you use send mediator inside mySequenceA and mySequenceB, define the "receive" attribute to route the response in a dedicated sequence with <send receive="myResponseSequence"> (the same "myResponseSequence" must be used in mySequenceA and B).

If you use call mediator, then call a dedicated sequence with <sequence key="myResponseSequence"> (the same "myResponseSequence" must be used in mySequenceA and B)

inside myResponseSequence, use aggregate mediator :

  • the completeCondition can be let to default, the ESB will wait to receive the same number of response than the number of targets in your clone mediator. It gives you someting like :

    <completeCondition> <messageCount min="-1" max="-1"/> </completeCondition>

  • the onComplete contains the mediation sequence that will be executed as soon as all the responses will be there : this sequence must contain the send mediator that will send a single response to the caller. The "expression" attribute on this "onComplete" node will contain an xpath that tell which node from the response must arrive inside the onComplete sequence.

  • inside the onComplete sequence, you can use payloadMediator to compose your single response

    <onComplete xmlns:ns="http://org.apache.synapse/xsd" expression="//values"> <payloadFactory media-type="xml"> <format> <myCustomResponse> <result>$1</result> </myCustomResponse> </format> <args> <arg evaluator="xml" expression="//values"/> </args> </payloadFactory> <send/> </onComplete>

The fact that your api is restful should not be a problem with aggregate mediator. Perhaps the format is json and not xml : use json-eval if you want for the xpath or media-type=json" inside payloadFactory