Friday, April 3, 2009

How to setup dynamic routing of endpoints in Oracle SOA Suite 10g

Here we describe in detail how to create an ESB service to parse an incoming message, and based on the input, route to the appropriate endpoint which may not be defined during design time and which may also be updated dynamically as needed.
    Why use dynamic routing?

    The reason for considering dynamic routing of endpoints is illustrated in the example below. For instance, you may have an ESB service designed as shown. Here, all customer creation requests are routed to some endpoint:

    In the future, you may decide to route U.S. customers to one server while routing European customers to another one (for the purpose of distributing load or handling them differently on the backends).


    As you can see on the left, the ESB project will have to be modified every time a new endpoint is added. Dynamic routing solves the problem by allowing you to add endpoints without having to update your ESB services.
The advantage of dynamic routing is that no modifications to the ESB service is needed if a new SOAP service is added which has the same WSDL but a different endpoint. The disadvantage is that it is not possible through ESB Control to show which of the endpoints the request was actually routed to.

The example detailed below uses the the country code in the input payload (in my example, stored in /imp1:Datas/imp1:Data/imp1:Application) to lookup the actual endpoint. The XSL mapper file will perform a DVM lookup via the orcl:lookup-dvm function, and store the result in the outbound header via the ehdr:setOutboundHeader function. The ehdr:setOutboundHeader function overrides the actual endpoint of the external SOAP service. As a result, although you have one external SOAP service defined in your ESB project, it can be overriden at runtime.

Step 1: Create a DVM

Create a DVM manually, or import the following XML through ESB Control:
    <?xml version = '1.0' encoding = 'UTF-8'?>
    <dvm name="Endpoints" isNew="null">
    <description>Dynamic endpoints for all systems</description>
    <columns>
    <column name="System"/>
    <column name="Endpoint"/>
    </columns>
    <rows>
    <row><cell>US</cell><cell>http://usaserver.itconvergence.com:7777/createCustomer</cell></row>
    <row><cell>EU</cell><cell>http://europeserver.itconvergence.com:80/createCustomer</cell></row>
    <row><cell>SA</cell><cell>http://southamericaserver.itconvergence.com/createCustomer</cell></row>
    </rows>
    </dvm>
This creates a DVM called Endpoints with 2 columns. The first column System denotes a region code (e.g., US), while the second column Endpoint denotes the actual endpoint URL. As new endpoints are defined, they can be dynamically added to the DVM at runtime without having to update the ESB code.

Step 2: Create the ESB service

Create a simple ESB service consisting of:
- Inbound file adapter
- Routing service
- Outbound SOAP service









Only one outbound external SOAP service is required, even though there are actually several endpoints. The WSDL of this SOAP service may have a hardcoded SOAP address location of any one of the external services. For example:
    <soap:address location="http://southamericaserver.itconvergence.com/createCustomer"/>
This SOAP address location will be overriden at runtime though.

Step 3: Create mapper file

Create a new mapper file (i.e., XSL transformation) between the routing service and the SOAP service.

Step 4: Transform the outbound header

Utilize the header transformation extension function setOutboundHeader to update the outbound header and override the SOAP address location that is hardcoded in the WSDL. Click on "Source" to view the source of your XSL file just created, and immediately before the statement <xsl:template match="/">, add the following:
    <xsl:variable name="LocationIn" select="orcl:lookup-dvm('Endpoints', 'System', /imp1:Datas/imp1:Data/imp1:Application, 'Endpoint','')"/>

    <xsl:variable name="LocationOut" select="ehdr:setOutboundHeader('/shdr:ESBHeader/shdr:location', $LocationIn, 'shdr=http://xmlns.oracle.com/esb;')"/>

What this does is use the country code /imp1:Datas/imp1:Data/imp1:Application to perform a lookup on the Endpoints DVM and returns the Endpoint column, storing it in the $LocationIn variable. This variable is then used by the ehdr:setOutboundHeader function to set the outbound location in the header. The design will look similar to the following:










That's it!

2 comments:

Anonymous said...

Hi Ahmed,
Thank you very much for the wonderfull blog, You have done provided us with solution for most of the problem on Oracle10gR3.

keep it up.

Thanks and Regards
NK

Anonymous said...

Good Post

Thanks,
Bala