Wednesday, November 9, 2016

Dynamic registry lookup in WSO2 ESB

Dynamic lookup allows for seamless data changes without any service interruption. In a dynamic lookup information is derived from the data, rather than modeled at design time. This enables you to specify the information during at runtime (dynamically). You need not define data at design time. You can achieve this in WSO2 ESB by using dynamic XPath expression.

First, we need to create the XPath expression using the property mediator.

<property name="xpathExpr" expression="fn:concat('//',$ctx:name)" scope="default" type="STRING"/>

Then we can use evaluate function as below

<property name="xpathValue" expression="evaluate($ctx:xpathExpr)" scope="default" type="STRING"/>

The result of the evaluate function is the result of evaluating the composed XPath expression. This is useful where an XPath expression needs to be constructed at run-time. Let's see how we can use dynamic XPath expression for dynamic registry lookup in WSO2 ESB.

First, store the below data as an XML file in the registry.
  • Log on to ESB management console.
  • Click the "Main" button to access the "Manage" menu.
  • Click on "Browse," in the left "Registry" menu.
  • Goto _system > config > click on the "Add Resource" link.
  • Add the following data with name as productlist.xml and Media type as application/xml.

<productlist>
   <product>
      <id>API Cloud</id>
      <plans>
         <plan>
            <name>Trial</name>
            <price>$0</price>
            <feature>10 portal users</feature>
         </plan>
         <plan>
            <name>Starter</name>
            <price>$129</price>
            <feature>100 portal users</feature>
         </plan>
         <plan>
            <name>Getting Traction</name>
            <price>$298</price>
            <feature>2000 portal users</feature>
         </plan>
         <plan>
            <name>Medium</name>
            <price>$698</price>
            <feature>7000 portal users</feature>
         </plan>
         <plan>
            <name>Large</name>
            <price>$2980</price>
            <feature>Unlimited portal users</feature>
         </plan>
         <plan>
            <name>Extra-large</name>
            <price>$9980</price>
            <feature>Unlimited portal users</feature>
         </plan>
      </plans>
   </product>
   <product>
      <id>APP Cloud</id>
      <plans>
         <plan>
            <name>Beta</name>
            <price>$0</price>
            <feature>Greater application compatibility with a separate docker container per application version</feature>
         </plan>
      </plans>
   </product>
</productlist>


Use the following proxy service to dynamically lookup on the registry and send back as a response.

 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="dynamicLookup"
       startOnLoad="true"
       statistics="disable"
       trace="disable"
       transports="http,https">
   <target>
      <inSequence>
         <property expression="//productName" name="productName"/>
         <property expression="//productPlan" name="productPlan"/>
         <property expression="get-property('registry','conf:/productlist.xml')"
                   name="cloud"
                   scope="default"
                   type="OM"/>
         <property expression="fn:concat(&#34;$ctx:cloud//product[id='&#34;,$ctx:productName,&#34;']/plans/plan[name='&#34;,$ctx:productPlan,&#34;']/price&#34;)"
                   name="priceExpr"
                   scope="default"
                   type="STRING"/>
         <property expression="fn:concat(&#34;$ctx:cloud//product[id='&#34;,$ctx:productName,&#34;']/plans/plan[name='&#34;,$ctx:productPlan,&#34;']/feature&#34;)"
                   name="featureExpr"
                   scope="default"
                   type="STRING"/>
         <property expression="evaluate($ctx:priceExpr)"
                   name="price"
                   scope="default"
                   type="STRING"/>
         <property expression="evaluate($ctx:featureExpr)"
                   name="feature"
                   scope="default"
                   type="STRING"/>
         <payloadFactory media-type="xml">
            <format>
               <product>
                  <name>$1</name>
                  <plan>$2</plan>
                  <price>$3</price>
                  <feature>$4</feature>
               </product>
            </format>
            <args>
               <arg evaluator="xml" expression="$ctx:productName"/>
               <arg evaluator="xml" expression="$ctx:productPlan"/>
               <arg evaluator="xml" expression="$ctx:price"/>
               <arg evaluator="xml" expression="$ctx:feature"/>
            </args>
         </payloadFactory>
         <respond/>
      </inSequence>
   </target>
   <description/>
</proxy>

Request :

<request>
    <productName>API Cloud</productName>
    <productPlan>Getting Traction</productPlan>
</request>

Response:

<product xmlns="http://ws.apache.org/ns/synapse">
    <name>API Cloud</name>
    <plan>Getting Traction</plan>
    <price>$298</price>
    <feature>2000 portal users</feature>
</product>

Here proxy service takes the product name & plan details from the incoming message and builds the required XPath expression at the runtime to fetch the data from the registry.

Here you can change the product/product plan details without any service interruption by modifying only the productlist.xml file in the registry.  So with the dynamic lookup in WSO2 ESB, you can facilitate the seamless integration.