Monday, July 27, 2015

Array creation in BPEL

Most of the time, the input/requests we get in BPEL responses are not simple one line values. They can be complex xsd files where , data schema are used. In a situation like that, you need to handle the input payload, manipulate the content and present the values in the form of arrays.  So let us consider this example below.



In this example, I'm getting an input from the client/user (which will be a multiple set of string values). I need to get this list of values, loop through them (you can add your additional business logic/conditions here) and finally create an array with that value set.

In the first assign step I will be initializing a counter variable in order to loop the values ,and inside the while loop I'm adding each property to an array(Assign1) and incrementing the counter variable(Assign2).  Let us see how we can add the logic to these steps.

1.  These are my request and response properties. (Which are considered in receiveInput and replyOutput steps accordingly)

  <element name="ArrayCheckRequest">
                <complexType>
                    <sequence>
                        <element name="input" type="string" maxOccurs="unbounded"/>
                    </sequence>
                </complexType>
            </element>

            <element name="ArrayCheckResponse">
                <complexType>
                    <sequence>
                        <element name="result" type="string" maxOccurs="unbounded"/>
                    </sequence>
                </complexType>
            </element>

What you need to remember here is that since I'm expecting a multiple set of values( set of string values in this case) I need to make sure that I allow the input property to have multiple values. This is done by setting the maxOccurs property to unbounded.  I have done the same for my final response as well, since i will be sending out an array.

2. Assign :   In the first assign step property details, I'm initializing a counter variable so that I can loop through the values later. In the second copy element, I'm initializing the result variable of the final response.

<bpel:assign validate="no" name="Assign">
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>1</bpel:literal>
                </bpel:from>
                <bpel:to variable="counter"></bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <tns:ArrayCheckResponse xmlns:tns="http://wso2.org/bps/sample"
                            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <tns:result>tns:result</tns:result>
                        </tns:ArrayCheckResponse>
                    </bpel:literal>
                </bpel:from>
                <bpel:to part="payload" variable="output"></bpel:to>
            </bpel:copy>
        </bpel:assign>
Things to Note: I was wasting lot of time when i first created this sample, because I missed out two points.

*. In xpath, array indexing starts from 1 instead of 0 as our usual understanding in Java. So when initializing a counter variable make sure it starts from 1.
*. Before, I was initializing the result variable within the while loop. Because of this, my final response always included only the last value, as it was getting reinitialized at every loop instance. So make sure that this is done outside and before the while loop.

3. While: Following is the condition of the while loop. Again note, since indexing is happening from 1, you need to add = sign as well. I'm using the xpath function count() to get the total occurrence of the input list.

$counter <= count($input.payload/tns:input)

4.Assign1 : Here we are using an ODE xpath function, which requires Xpath 2.0. So make sure you add xpath Language and expression language definitions as it is done below. Else this ode method will not be recognized.


<bpel:copy>
                        <bpel:from expressionLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath2.0"
                            queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath2.0">
                            <![CDATA[ode:insert-as-last-into($output.payload/tns:result, $input.payload/tns:input[round($counter)])]]>
                        </bpel:from>
                        <bpel:to part="payload" variable="output">
                            <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:result]]></bpel:query>
                        </bpel:to>

Also make sure you add the namespace for ode at the top of bpel process definition.

xmlns:ode="http://www.apache.org/ode/type/extension"

5.Assign2 : In this step you need to increment the counter variable like below.

<bpel:assign validate="no" name="Assign2">
                    <bpel:copy>
                        <bpel:from expressionLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
                            <![CDATA[$counter + 1]]>
                        </bpel:from>
                        <bpel:to variable="counter"></bpel:to>
                    </bpel:copy>
                </bpel:assign>



No comments:

Post a Comment