Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wso2 ESB : Split / Gather Pattern - Single Response

This is not a question but rather an answer. I am quite new to wso2 ESB and wanted to make a test run implementing the split/gather EIP as part of a POC. I followed the examples I found and immediately got a working config that returned a single response. However to get all the responses back took quite some amount of time to figure out. Most given samples seemed to create the same unexpected result. I hope that if you run into the same kind of problem these lines will be helpfull to you.

Setup

I used the soapUI sample service (search operation) as service backend. I sent a combined message searching for two items to the proxy server (see artefact below) The iterate mediator splits the message and forwards it to the endpoint that's calling the soapUI mockup. The aggregate mediator waits for all responses and tries to put it into one result message.

Problem

Although the splitter was working correctly, the aggregator returned only one result element not a list of elements as expected. All logs showed that everything was fine, several requests were sent to the corresponding endpoints but still only the first response that returned was visible in the final response.

Solution

After setting the log level of the proxy to TRACE I realized that the aggregator worked just fine, only it created a message that wasn't really SOAP conform. All aggregated elements were added directly beneath the soap body. So the question was how to add one root element between body and result tags. I tried XSLT first but it also could read only the first child element of the body. Finally I found some deeply buried hint to use the enrich mediator (or rather a series of that) and that did the trick. The following list explains the part of the config (code shown below) that is not to be found in most examples.

  1. Use first Enrich to capture all relevant items into a property
  2. Forget about the current message - rewrite the complete envelope with the body containing only the new payload root element
  3. Attach the elements stored in the property to the new payload root.
  4. If required capture the soap header into a property and attach it into the new msg (not in the config below)

Artefacts

Demo Request

<body>
   <sam:multisearch xmlns:sam="http://www.example.org/sample/">
      <sam:search>
         <sessionid>123</sessionid>
         <searchstring>Item 1</searchstring>
      </sam:search>
      <sam:search>
         <sessionid>123</sessionid>
         <searchstring>Item 2</searchstring>
      </sam:search>
   </sam:multisearch>
</body>

Config

<proxy xmlns="http://ws.apache.org/ns/synapse" name="test.multisearch" transports="https,http" statistics="enable" trace="enable" startOnLoad="true">
   <target>
      <inSequence>
         <iterate xmlns:sam="http://www.example.org/sample/" expression="//sam:multisearch/sam:search">
            <target>
               <sequence>
                  <send>
                     <endpoint key="soapUI_Mockup"/>
                  </send>
               </sequence>
            </target>
         </iterate>
      </inSequence>
      <outSequence>
         <aggregate>
            <completeCondition>
               <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://www.example.org/sample/" expression="//sam:searchResponse">
               <enrich>
                  <source clone="true" xpath="$body//item"/>
                  <target type="property" property="ResultItems"/>
               </enrich>
               <log level="custom">
                  <property name="ResultItems" expression="get-property('ResultItems')"/>
               </log>
               <enrich>
                  <source type="inline" clone="true">
                     <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">                        
                        <soapenv:Header/>                        
                        <soapenv:Body>                           
                           <sam:GenericDataResponse/>                        
                        </soapenv:Body>                     
                     </soapenv:Envelope>
                  </source>
                  <target type="envelope"/>
               </enrich>
               <enrich>
                  <source type="property" clone="true" property="ResultItems"/>
                  <target action="child" xpath="//sam:GenericDataResponse"/>
               </enrich>
               <send/>
            </onComplete>
         </aggregate>
      </outSequence>
   </target>
   <description></description>
</proxy>

Finally a question

If someone could hint me to some documentation or give me some working config for the correlateOn attribute of the aggregate mediator I'd really appreciate it.

like image 934
dreamer Avatar asked Jul 27 '13 22:07

dreamer


2 Answers

What you need to do is, mention any id in the iterator mediator (refer iterator mediator docs) and refer the same id in aggregator mediator as the correlation id. That's it. –

like image 73
Subash Chaturanga Avatar answered Oct 31 '22 20:10

Subash Chaturanga


The aggregate mediator supports an attribute enclosingElementProperty which surrounds the responses with a single parent element. This simplifies your enrich trick:

<property name="ROOT" scope="default">
    <root:rootelement xmlns:root="www.wso2esb.com"/>
</property>
<aggregate>
    <completeCondition>
        <messageCount min="-1" max="-1"/>
    </completeCondition>
    <onComplete expression="//dummy" enclosingElementProperty="ROOT">
    </onComplete>
</aggregate>
like image 38
Jeroen van Veldhuizen Avatar answered Oct 31 '22 21:10

Jeroen van Veldhuizen