Saturday, April 5, 2014

Using operations scope to hold my values while iterating

Iterator mediator breaks a message from the given xpath pattern and produces smaller messages. If you need to collect an attribute value throughout the iteration, how do you do it?

With lot of help from IsuruU, I managed to workout this solution. In here I am Iterating through this message [a], and breaking it to sub messages using this [b] pattern. I need to collect the values of '//m0:symbol' in a property and send the processed values to client and values of failed messages to failure sequence.

 [a]  - Request message
  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Body>
         <m0:getQuote xmlns:m0="http://services.samples">
            <m0:request>
               <m0:symbol>IBM</m0:symbol>
            </m0:request>
            <m0:request>
               <m0:symbol>WSO2</m0:symbol>
            </m0:request>
            <m0:request>
               <m0:symbol>AAA</m0:symbol>
            </m0:request>
            <m0:request>
               <m0:symbol>SUN</m0:symbol>
            </m0:request>
         </m0:getQuote>
      </soapenv:Body>
   </soapenv:Envelope> 
[b] xpath expression
//m0:getQuote/m0:request" 

Here is my insquence:
    <inSequence>
         <iterate xmlns:m0="http://services.samples"
                  continueParent="true"
                  preservePayload="true"
                  attachPath="//m0:getQuote"
                  expression="//m0:getQuote/m0:request"
                  sequential="true">
            <target>
               <sequence>
                  <property name="PID"
                            expression="fn:concat(get-property('operation','PID'),//m0:symbol,' ')"
                            scope="operation"
                            type="STRING"/>
                  <store messageStore="pid_store"/>
               </sequence>
            </target>
         </iterate>
         <log level="custom">
            <property name="Processed_PIDs" expression="get-property('operation','PID')"/>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <ax21:getQuoteResponse xmlns:ax21="http://services.samples/xsd">
                  <ax21:pid>$1</ax21:pid>
               </ax21:getQuoteResponse>
            </format>
            <args>
               <arg xmlns:ns="http://org.apache.synapse/xsd"
                    evaluator="xml"
                    expression="get-property('operation','PID')"/>
            </args>
         </payloadFactory>
         <respond/>
      </inSequence>


Let me explain above; With 'expression="//m0:getQuote/m0:request"' the request message will be split into different messages as I described earlier. Since my scenario was to collect a given value from each of the split message and send them to appropriate path as a single message, I have used continueParent="true" and sequential="true". By this I am making sequential processing instead of default parallel processing behaviour of iterator.

Then as a target sequence within iterator to mediate the split message, I have opened a property mediator. Using this, I am collecting the value of //m0:symbol and storing it in a variable (property name) 'PID'.

The scope of the PID property was set to scope=operations to preserve the property within iterated message flow.

Later, as per the initial requirement the message is sent to a message store. A log is printed on property for ease of tracking. Then I prepared a payload to send the message with PID as an attribute.

Fault sequence was done like this to capture faulty messages and pass their PIDs.

<faultSequence>
         <log level="full">
            <property name="MESSAGE"
                      value="--------Executing default &#34;fault&#34; sequence--------"/>
            <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
            <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
         </log>
         <property xmlns:m0="http://services.samples"
                   name="PID"
                   expression="fn:substring(fn:concat(get-property('operation','PID'),//m0:symbol,' '),1,(fn:string-length(get-property('operation','PID'))-1))"
                   scope="operation"
                   type="STRING"/>
         <log level="custom">
            <property name="Failed_PIDs" expression="get-property('operation','PID')"/>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <ax21:getQuoteResponse xmlns:ax21="http://services.samples/xsd">
                  <ax21:pid>$1</ax21:pid>
               </ax21:getQuoteResponse>
            </format>
            <args>
               <arg xmlns:ns="http://org.apache.synapse/xsd"
                    evaluator="xml"
                    expression="get-property('operation','PID')"/>
            </args>
         </payloadFactory>
         <respond/>
      </faultSequence>

The complete proxy configuration can be found here. TCPMon outputs are attached below for further clarity.












3 comments:

  1. Any idea how to append xml node to a property in operation scope under iterate?

    ReplyDelete
  2. I was able to achieve after putting last comment :)

    ReplyDelete
  3. I am using ESB 4.9.0. I set a property inside iterate mediator with operational scope. When I try to retrieve the same outside the iterate mediator the property with the operational scope value is null. Below is the code snippet. Can you please tell me whats wrong I have done?

































    ReplyDelete

Featured

Selenium - Page Object Model and Action Methods

  How we change this code to PageObjectModel and action classes. 1 2 3 driver . findElement ( By . id ( "userEmail" )). sendKeys (...

Popular Posts