2011-06-21

How to define a partnerLink endpoint from an externally defined configuration ?

(or how to have the same WLI XMLCache functionality in BPEL PM)

Part one : Get the data from the cache

Source :
Excellent article from Simone : http://www.oracle.com/technetwork/topics/soa/dynamic-data-lookup-endpoints-geib-092046.html

When I read Simone’s article, I thought it was nice but I also thought that it did not go as far as I expected. In her example, she took a typical database example, with a set of data, identified by an ID. It’s a very interesting feature, but it does not meet exactly my requirement ...

That’s why I’m going to write (with Simone’s permission :D) a little addendum which will help WLI users to transpose their good old WLI XMLCache to BPEL PM DVM.
The need for such a configuration is pretty obvious : I want to be able to deploy my project in several different environments without updating the code to reflect a changing server URL : typically, in a development environment, it would be an Apache and in a production environment, it would be an Alteon or a Big-Ip, for instance.

In my case, I decided to divide my configuration into two different DVM. The first one is only composed of what’s going to change (URLs mostly …) and the other one will contain the “immutable” parts, that is to say the things that won’t change from an environment to another (context paths here).

To know how to create a DVM, please refer to Simone’s article.

Here is the first DVM :

Property Value
ServiceEntrypoint http://IPAddress:port

To get the value of the “ServiceEntrypoint” property, I will have to use a BPEL function :
dvm:lookupValue1M("environment.dvm", "Property", 'ServiceEntrypoint', "Value") which will return “http://ipaddress:port/

Here is the second one :

ServiceName ContextPath
TestWS /contextPath

By the way, pay attention to to way you are filling data : columns are lines here :)

image

To get the context of my service, the function is the same as the one we used above :

dvm:lookupValue1M("servicepaths.dvm", "ServiceName", TestWS, "ContextPath") which will return “/contextPath”

Now we have the way to retrieve our two values, we can go in our BPEL Process.

Here are the thing to perform.

1) Define variables


   <variable name="serviceEntrypoint" type="xsd:string"/>
   <variable name="contextPath" type="xsd:string"/>
   <variable name="endpoint" type="xsd:string"/>

No magic here : a endpoint value which will receive the concatenation of the serviceEntrypoint and a contextPath.

2) Define a namespace in your BPEL process

xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue"

To be able to use DVMs. And if you are copying directly the code from the article, JDev won’t import for you the “xsd” namespace, then add it manually :

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

3) Concatenate the information

In an Assign activity, concatenate the result of these two functions in a single string :


   <assign name="Endpoint">
     <copy>
       <from expression='dvm:lookupValue1M("environment.dvm", "Property", "ServiceEntrypoint", "Value")'/>
       <to variable="serviceEntrypoint"/>
     </copy>
     <copy>
       <from expression='dvm:lookupValue1M("servicepaths.dvm", "ServiceName", "TestWS", "ContextPath")'/>
       <to variable="contextPath"/>
     </copy>
     <copy>
       <from expression="concat(bpws:getVariableData('serviceEntrypoint'), bpws:getVariableData('contextPath'))"/>
       <to variable="endpoint"/>
     </copy>
   </assign>

I guess the code is clear enough …

Part two : design a test webservice

I guess you know how to do it, so I won’t spend much time explaining it.

Just design a small webservice “HelloWorld” or whatever to have something to call from our BPEL Process :)

Once deployed, get the generated contextPath by going to the WLS console, in the section deployment, the name should be “AppName-ProjectName-context-root

image

Click on the “+” next to your deployment and locate your webservice and click on it.

image

In the section “Testing”, click once again on the “+” just next to the webservice and you will have the choice to launch the TestClient or to display the WSDL.

image

In both cases, what’s important for us is the contextPath : /Blog-XMLCache-context-root/HelloWorldPort

Part three: assigning the URL to the partnerLink endpoint

Sources :

A big thanks to Deepak who provided the GoDynamic example which helped me go through that mist.

Create a simple partnerLink toward the Webservice

First thing of all, we need to define a partnerLink. To do so, drag a partnerLinkfrom the palette in the right swimlane. It will start an assistant : just fill the information and enter the WSDL location :

http://localhost:7001/Blog-XMLCache-context-root/HelloWorldPort?WSDL

Click elsewhere and as soon as JDev detects the mouseOut event, it will display the WS port. Select the partnerRole and you’re done.

Drag and drop an “Invoke” activity and wire it to the partnerLink :

image

Once done, JDev may complain since the input var has not been initialized. Add a copy operation in the Assign activty, for instance :

image

But it doesn’t really matter, especially since I didn’t define any input for my webmethod. Anyway.

Update the partnerLink endpoint

To be able to change dynamically the endpoint of your partnerLink, we will need to use a XML element “EndpointReference”. That element is defined in a specific XSD which you need to import.

 

1) Import the ws-addressing.xsd in your XSD directory

This file is located in your JDev home :
[JDEV_HOME]/jdeveloper/integration/seed/soa/shared/common/ws-addressing.xsd

For instance, if you’re using the VB appliance, this file will be there :
/oracle/jdevhome/jdeveloper/integration/seed/soa/shared/common/ws-addressing.xsd

 

2) Define a namespace in your BPEL process

xmlns:dpl="http://schemas.xmlsoap.org/ws/2003/03/addressing"

 

3) Define an import in the WSDL of your BPEL process

<import namespace="http://schemas.xmlsoap.org/ws/2003/03/addressing" schemaLocation="xsd/ws-addressing.xsd"/>

4) Declare a variable, matching your namespace prefix

<variable name="endPointReference" element="dpl:EndpointReference"/>

5) Define an “Assign” activity

In a Assign activity, define those operations :

   <assign name="PartnerLink">
     <copy>
       <from>
         <EndpointReference xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:ns1="http://services.sap.com">
           <Address/>
           <ReferenceProperties/>
           <ServiceName/>
         </EndpointReference>
       </from>
       <to variable="endPointReference"/>
     </copy>
     <copy>
       <from variable="endpoint"/>
       <to variable="endPointReference" query="/dpl:EndpointReference/dpl:Address"/>
     </copy>
     <copy>
       <from variable="endPointReference"/>
       <to partnerLink="HelloWorldService"/>
     </copy>
   </assign>

Where “endpoint” is the wanted URL (in my case, I constructed it from a double DVM lookup)

6) Call your partnerLink through an Invoke activity

Everything is in the title :)

Now, you should have a BPEL process like that :

image

And from the composite view :

image

 

To sum up, we have a start node, then the first Assign activity, which gets the configuration information from the cache (DVM). Then a second assign activity that creates an empty “Endpoint” and copies the result of the previous assign (a concatenated string, representing the endpoint of our webservice) in the “address” property of the “Endpoint” variable.

Part four: testing our BPEL process

Okay, let’s roll ! Please note that I replaced “/contextPath” by the real context path of my service in the “ServicePaths.dvm” file.

As my project is hybrid (composed of a webservice & of a BPEL process), you will have to deploy it twice. Once as a webservice project and the other one … ok, I guess you see the point.

image

 

Once done, go on the EM and test your BPEL process.

Normally, you should have a successful test :

image

But now, if we change the server port to “8001”, in the “environment” DVM (either directly in the code, or through the SOA Composer), let’s see what’s happening :

image

Or if we take a closer look to the “DynamicPartnerLink” :

image

 

So, WLI users, here is a “simple” way to replace your good old XMLCache ! Hope it will help some WLI fellows :)

 

1 comment:

Anonymous said...

Hi,

Nice article. Just found it when looking for an article to refer to on setting the endpointURI.

However, how you describe it, is how it worked in SOASuite 10g. I wrote an article about that too: http://blog.darwin-it.nl/2008/11/dynamic-partnerlinks-made-simple.html. But from 11g onwards this can be done much simpler by just setting the endpointURI in the invoke to a variable.

Good luck with your work.

Regards,
Martien