Tuesday, May 22, 2012

True dynamic routing with OSB 11g

Forget all the Oracle documentation and blog posts you see out there. In this walkthrough, I describe exactly how to do true dynamic routing with OSB.


Use Case:

Let's say you have 3 external web services, each having the same exact interface:
http://us.ipnweb.com:7777/Helloworld1/helloworld_client_ep?wsdl
http://eu.ipnweb.com:8888/Helloworld2/helloworld_client_ep?wsdl
http://in.ipnweb.com:9999/Helloworld3/helloworld_client_ep?wsdl
My requirements are as follows:
  • I want to be able to accept an input of country code, and based on that input, route to one of the three services.
  • I want to be able to add additional endpoints without having to change the code.
For example, if I submit this payload with an input of "EU", I expect it to route to the second web service on the list above:
<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:hel="http://xmlns.oracle.com/SOA11g/HelloWorld/HelloWorld">
  <soapenv:Header/>
  <soapenv:Body>
    <hel:process>
      <hel:input>EU</hel:input>
    </hel:process>
  </soapenv:Body>
</soapenv:Envelope>

Steps:

1. Create an XML file called HelloWorldMap.xml with the following contents (using the endpoint, not WSDL). This is essentially an XML Resource which maps the country code to the endpoint.
<routing>
  <row>
    <country>US</country>
    <endpoint>http://us.ipnweb.com:7777/Helloworld1/helloworld_client_ep</endpoint>
  </row>
  <row>
    <country>EU</country>
    <endpoint>http://eu.ipnweb.com:8888/Helloworld2/helloworld_client_ep</endpoint>
  </row>
  <row>
    <country>IN</country>
    <endpoint>http://in.ipnweb.com:9999/Helloworld3/helloworld_client_ep</endpoint>
  </row>
</routing>

2. Create an OSB project by logging in to the OSB Console at http://osb.ipnweb.com:7001/sbconsole

3. Click on Project Explorer

4. Click on Projects

5. Enter a New Project Name (e.g., HelloWorldDynamicRouting) and click Add Project


6. Click on HelloWorldDynamicRouting

7. Create Resource of type XQuery, and browse for and import the XML file (e.g., HelloWorldMap.xml)


This file is the mapping between country code and endpoint. Once you understand the logic in these steps, you can actually use any type of mapping such as a database table or DVM.

8. Create Resource of type Resources from URL and enter one of the WSDLs up top and enter a Resource Name


This is used as the WSDL for my business service. Essentially, you will have only 1 business service in the entire project, regardless of how many actual endpoints may exist. This WSDL is also used as the interface for my proxy service.

9. Create Resource of type Proxy Service, give it a name (e.g., HelloWorldPS), and browse for and import the WSDL Web Service that was just imported in the step above
 

10. Create Resource of type Business Service, give it a name (e.g., HelloWorldBS), and browse for and import the WSDL Web Service in the project


11. Edit Message Flow of the proxy service and Add Pipeline Pair

12. In the Request Pipeline, Add Stage then Edit Stage

13. Add an Action > Message Processing > Assign

14. Click on Expression

15. Click on XQuery Resources

16. Browse for and select the XML Resource (e.g., HelloWorldMap)


17. Save this and assign this to the variable MyMap

18. Add 2 more actions, with the expression and variable as follows:
Expression:    $body/hel:process/hel:input
Variable:        MyInput

Expression:    $MyMap/row[country/text()=$MyInput]/endpoint/text()
Variable:        MyMapResult
Your stage should now look like this:


19. Click on your pipeline pair and Add Route > Edit Route > Add an Action > Communication > Routing

20. Click on Service and choose the business service (e.g., HelloWorldBS) and operation

21. Under Request Actions, Add an Action > Communication > Routing Options and enter a URI expression as $MyMapResult


Your message flow should look like this:



References:


Ahmed Aboulnaga

5 comments:

Gaurav said...

Hi Ahmed, can this approach be used for file polling as well.

like I have a source dir and target dir. I poll on source and moving file to target dir.

now source and target dirs going to have 3 sub directories. so can I still continue polling on parent source dir and based on sub directory name file will be placed to relevant target sub directory ?

Aqib memon said...

Very Helpfull , your effort is appreciated!

Juan Pablo Leiva said...

only it works for me, if the data put into the URI as follows in your example: data($MyMapResult). This is because the routing to Business Service returns the error "Illegal character in path at index XXXX" because for some reason does not interpret the rare characters like '/' in the String URI. The function data () adapts and magic.

Ahmed Aboulnaga said...

Thanks for sharing your feedback Juan!

Anonymous said...

Thanks for the case. Very Helpfull.