Friday, May 01, 2009

BPEL Cloning

Sometime you want to have copy of your BPEL production environment to reproduce issues or test cases. Cloning an Oracle Application Server environment is not so complicated. The whole cloning procedure is described in the Oracle Manuals.

To clone the BPEL environment follow the instructions described in the manual “Oracle® Application Server Administrator's Guide 10g Release 3”, chapter 9. There are a few flavors of this document:
Make a note that the cloning approach is based on the Oracle Application Server. The whole cloning approach should work, but...

Read the document carefully, not everything is cloned. You should do some post cloning steps:
  • Check the data-sources.xml file for each OC4J container.
  • Check the oc4j-ra.xml files for each adapter to are using.
  • Check the BPEL domain and system configuration files.
After these steps you should be able to start your cloned BPEL environment, but...

When you run a BPEL process that has partner links to other BPEL processes or third-party web services, these partner links are still pointing to your 'orginal' environment. The end points of thepartner links of your BPEL process are not changed after the cloning.

There are a few solutions and work arraounds to tackle this.

You could design your BPEL process to use a UDDI to lookup the end point dynamicly. You could use the approach in Oracle AIA Foundation to use dynamic partner links. But is is not use full if you did not implment this on advance.

You could 'fake' the endpoints by setting your 'hosts' file by adding entries of the hostnames of your partnerlink servers and point them to another IP adress, this could work only if portnumbers are the same.

Another approach is to use the BPEL Java API to query the BPEL processes and change all the end points of the partner links. With this approach you get a full cloned environment, with BPEL process defintions that point to your environment.

The code of the program is here:

package osbsutils.bpel;

/**
* The OSBS tool for bpel function
*
* This Java package is able to get and set endpoints of a BPEL process
* for any or all partnerlinks within that process.
*
* @notes
*
* To change endpoints of BPEL processes is only possible if
* the process state of that BPEL process is set to 'off'. Otherwise
* it could screw up your process definition
*
* If the BPEL process is using partnerlinks, but the wsdLocation is not
* an URL (http://host:port/...) then the replacement of the endpoint
* is not working
*
* @usage See end of this file
*
* @author Marc Kelderman
* @date 28 april 2009
* @version 1.0
*
*/

import com.collaxa.cube.rm.suitcase.PartnerLinkBindingDescriptor;
import com.collaxa.cube.rm.suitcase.PartnerLinkBindingsDescriptor;
import com.collaxa.cube.rm.suitcase.ProcessDescriptor;

import com.oracle.bpel.client.IBPELProcessHandle;
import com.oracle.bpel.client.Locator;
import com.oracle.bpel.client.delivery.IDeliveryService;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class endpoint
{
// The property that describes the endpoint in the bpel.xml file
private static String WSDLLOCATION = "wsdlLocation";

// Some pointers to the BPEL process manager
Locator locator;
IDeliveryService deliveryService;
IBPELProcessHandle processHandle;
ProcessDescriptor processDescriptor;

// A list of process handlers
IBPELProcessHandle[] listOfProcessHandles;

// Parnterlink bindings and a single binding
PartnerLinkBindingsDescriptor partnerLinksBindings;
PartnerLinkBindingDescriptor partnerLinkDesc;

// Public constrcutor
public endpoint()
{
}

public String getListOfEndpoints()
{
return "";
}

/**
* This method returns the wsdlocation of a particular proces
*
* @param pDomain - The BPEL domain
* @param pName - The name of the process
* @param pRev - The revision number
* @param pParterLinkName - the name of the partner link
* @return The 'wsdlLocation' property, as defined in bpel.xml
* @throws Exception
*/
public String getEndpoint
(
String pDomain
, String pName
, String pRev
, String pParterLinkName
)
throws Exception
{
if (locator == null) connectBPELPM(pDomain);

String domain = null;
String id = null;
String rev = null;
String wsdlloc = "";

Map<String,String> m = null;

// Get a list of BPEL processes definitions
listOfProcessHandles = locator.listProcesses();
int i = listOfProcessHandles.length;

// Loop through list list
while ((--i) >= 0)
{
// Get a sinlg handler to a proceess
processHandle = listOfProcessHandles[i];
processDescriptor = processHandle.getDescriptor();

// Get generic process info to determine if w got the right one
domain = processDescriptor.getDomainId();
id = processDescriptor.getId();
rev = processDescriptor.getRevisionTag();

if (id.equals(pName) && domain.equals(pDomain) && rev.equals(pRev))
{
partnerLinksBindings = processDescriptor.getPartnerLinkBindings();
partnerLinkDesc = partnerLinksBindings.getPartnerLinkBinding(pParterLinkName);

// a hash map to a list of partnerlink properties
m = partnerLinkDesc.getProperties();

// Get the result, even this propery does not exists
wsdlloc = m.get(WSDLLOCATION);
break;
}
}
return wsdlloc;
}

/**
* This method set the wsdlLocation of a BPEL process. It will
* Search through all the partnerlinks of that process and find the
* string 'oldUrl' and replace it with 'newUrl'
*
* @param pDomain - The BPEL domain
* @param pName - The name of the process
* @param pRev - The revision number
* @param oldUrl - the string to search for
* @param newUrl - The new string that will be used
*
* @return true when change has made, false if not
*
* @throws Exception
*/
public boolean setEndpoint
(
String pDomain
, String pName
, String pRev
, String oldUrl
, String newUrl
)
throws Exception
{
return(setEndpoint(pDomain, pName, pRev, null, oldUrl, newUrl));
}

/**
* This method set the wsdlLocation of a BPEL process. It will
* search of a particular partnerlink of that process and find the
* string 'oldUrl' and replace it with 'newUrl'
*
* @param pDomain - The BPEL domain
* @param pName - The name of the process
* @param pRev - The revision number
* @param pPartnerLinkName - the name of the partner link
* @param oldUrl - the string to search for
* @param newUrl - The new string that will be used
*
* @return true when change has made, false if not
*
* @throws Exception
*/
public boolean setEndpoint
(
String pDomain
, String pName
, String pRev
, String pPartnerLinkName
, String oldUrl
, String newUrl
)
throws Exception
{
if (locator == null) connectBPELPM(pDomain);

String domain = null;
String id = null;
String rev = null;
String wsdlloc = "";

// set the default return value
boolean result = false;
Map<String,String> m = null;

// Get the list of all processes
listOfProcessHandles = locator.listProcesses();
int i = listOfProcessHandles.length;

while ((--i) >= 0)
{
// Get a single process handler
processHandle = listOfProcessHandles[i];
processDescriptor = processHandle.getDescriptor();

// get some generic process values
domain = processDescriptor.getDomainId();
id = processDescriptor.getId();
rev = processDescriptor.getRevisionTag();

if (id.equals(pName) && domain.equals(pDomain) && rev.equals(pRev))
{
// We have the correct process and revision in the domain
// Get a list of partner links bindings
partnerLinksBindings = processDescriptor.getPartnerLinkBindings();
List l = partnerLinksBindings.getPartnerLinkBindings();
Iterator ite = l.iterator();
while(ite.hasNext())
{
// loop through all the partnerlink bindings
partnerLinkDesc = (PartnerLinkBindingDescriptor)ite.next();

// Do we have the correct partnerlink or can we ignore the partnerlink
if ((pPartnerLinkName == null) || (partnerLinkDesc.getName()).equals(pPartnerLinkName))
{
m = partnerLinkDesc.getProperties();
wsdlloc = m.get(WSDLLOCATION);

// Does the oldUrl string exists?
if (wsdlloc.indexOf(oldUrl) >= 0)
{
// Replace it
wsdlloc = wsdlloc.replaceFirst(oldUrl, newUrl);
// Set the new value
partnerLinkDesc.setPropertyValue(WSDLLOCATION, newUrl);
// Commit to BPEL PM
processHandle.updateDescriptor(processDescriptor);
result = true;
}
}
}
}
}
return result;
}

/**
* Connect to the BPEL process manager via the context properties
*/
private void connectBPELPM(String pDomain)
throws Exception
{
// properties in the classpath
Properties props = new java.util.Properties();
java.net.URL url = ClassLoader.getSystemResource("context.properties");
props.load(url.openStream());
locator = new Locator(pDomain, props);
}

public static void main(String[] args)
{
try
{
endpoint ep = new endpoint();

// if no arguments are give, call the examples
if (args.length > 0)
{
/*
* This example can be used command line:
*
* java <classpath> osbsutils.bpel.endpoint get domain bpel-process revision partnerlink-name
* java <classpath> osbsutils.bpel.endpoint set domain bpel-process revision [partnerlink-name] oldURL newURL
*
* Example:
* java <classpath> osbsutils.bpel.endpoint get default OSBSEndpointDemo 1.0 HelloWorld
* java <classpath> osbsutils.bpel.endpoint set default OSBSEndpointDemo 1.0 HelloWorld http://127.0.0.1:7777 http://linux:7777
*
*/

if (args[0].equals("get"))
{
if (args.length == 5)
{
System.out.println(ep.getEndpoint(args[1], args[2], args[3], args[4]));
}
}
if (args[0].equals("set"))
{
if (args.length == 6)
{
System.out.println(ep.setEndpoint(args[1], args[2], args[3], args[4], args[5]));
}
if (args.length == 7)
{
System.out.println(ep.setEndpoint(args[1], args[2], args[3], args[4], args[5], args[6]));
}
}
}

// if no arguments are give, call the examples
if (args.length == 0)
{
// Print the endpoint
// Search in the domain'default' for BPEL process OSBSEndpointDemo with revision 1.0
// The name of the partner link must be 'HelloWorld'
System.out.println(ep.getEndpoint("default", "OSBSEndpointDemo", "1.0", "HelloWorld"));

// Set a part of the endpoint to 'http://127.0.0.1:7777', when it contains 'http://linux:7777'
// Search in the domain'default' for BPEL process OSBSEndpointDemo with revision 1.0
// The name of the partner link must be 'WorldHello'
// Should return 'false'
System.out.println(ep.setEndpoint("default", "OSBSEndpointDemo", "1.0", "WorldHello", "http://linux:7777", "http://127.0.0.1:7777"));

// Set a part of the endpoint to 'http://127.0.0.1:7777', when it contains 'http://linux:7777'
// Search in the domain'default' for BPEL process OSBSEndpointDemo with revision 1.0
// The name of the partner link must be 'HelloWorld'
// Should return 'true'
System.out.println(ep.setEndpoint("default", "OSBSEndpointDemo", "1.0", "HelloWorld", "http://127.0.0.1:7777", "http://linux:7777"));

// Set a part of the endpoint to 'http://127.0.0.1:7777', when it contains 'http://linux:7777'
// Search in the domain'default' for BPEL process OSBSEndpointDemo with revision 1.0
// Any partner link in the BPEL process will be checked
// Should return 'true'
System.out.println(ep.setEndpoint("default", "OSBSEndpointDemo", "1.0", "http://linux:7777", "http://127.0.0.1:7777"));

System.out.println(ep.getEndpoint("default", "OSBSEndpointDemo", "1.0", "HelloWorld"));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}



The Java program is using the following runtime libraries. These libraries should be set in your classpath.

bpel jars:
  • orabpel.jar
  • oracle_http_client.jar
  • orabpel-common.jar
  • orabpel-exts.jar
  • orabpel-thirdparty.jar
  • orabpel-ant.jar
  • connector15.jar
j2ee jars:
  • ejb.jar
The Java program is also using a configuration file to connect to the BPEL server.

context.properties
orabpel.platform=ias_10g
java.naming.factory.initial=com.evermind.server.rmi.RMIInitialContextFactory
java.naming.provider.url=opmn:ormi://host-name:opmn-request-port:oc4j_soa/orabpel
java.naming.security.principal=oc4jadmin
java.naming.security.credentials=your-password


Take care of the following Metalink notes
744590.1 SOA Configuration Files Are Not Updated With New SID/Database Information After Clone Process.
760913.1 "DB Vendor Has Not Been Specified" Error While Cloning Application Server 10.1.3