Thursday, August 21, 2008

Remotely invoking clustered BPEL Worklist application

Oracle BPEL PM provides a Java API -the BPEL Worklist API- to connect to its Worklist application. There are several blogs that provide sample code on how to use it.

In production-like environments, components invoking the Worklist application can run on different servers for reasons of scalability and failover. This is also the case in one of our projects, where we have a SOA Suite cluster running ESB and BPEL, and another cluster running the ADF and WebCenter front-end. A custom front-end component presents task-related information to the users through a portlet. Tasks are queried and refreshed frequently and a user can have access up to several thousand tasks -not only user-assigned tasks are displayed but also tasks assigned to groups they belong to.

For remotely connecting to the BPEL Worklist application from the front-end components we considered the SOAP and RMI clients that are provided with the Worklist application. The type of client can be specified in the Java code accessing the Worklist application:

WorkflowServiceClientFactory.getWorkflowServiceClient(
WorkflowServiceClientFactory.REMOTE_CLIENT)


or

WorkflowServiceClientFactory.getWorkflowServiceClient(
WorkflowServiceClientFactory.SOAP_CLIENT)


Note that when using a SOAP client you have to add the statement Predicate.enableXMLSerialization(true) to make sure that predicate information for querying tasks is marshalled and sent to the Worklist application.

The actual configuration containing the information for the client on the Worklist web service endpoints and Worklist Java application is in the wf_client_config.xml file. That file is located in %ORACLE_HOME%/bpel/system/services/config.

One of the advantages of the SOAP client is that we can use WebCache as software load-balancer for HTTP requests. WebCache is already used in the project to load-balance and failover HTTP calls to external web services, ESB services, BPEL composite services and processes, etc. During stress-testing we found out that using a SOAP client -instead of RMI- roughly results in a 1.5 seconds response time penalty when querying 1500 tasks. That does not include other operations such as rendering tasks. The delay is most likely caused by XML marshalling and de-marshalling. RMI serializes object variables, but does not use the verbose XML format nor does it have to build a DOM tree in memory.

One of the questions that arises is whether failover is achievable using an RMI client. We don’t want a front-end component to be “tied” to only one SOA Suite runtime instance. It turns out this is possible by correctly configuring the wf_client_config.xml file. The serverUrl element in the configuration file defines the location of the Worklist application. You can use a comma-separated list of locations like you do when building an RMI initialcontext: java.naming.provider.url = "server1,server2".
The following piece of code from the wf_client_config.xml file achieves failover when using an RMI client to a clustered Worklist application:

<ejb>
<serverurl>
opmn:ormi://server01:6003:oc4j_soa/hw_services, opmn:ormi://server02:6003:oc4j_soa/hw_services
</serverurl>
<user>oc4jadmin</user>
<password>welcome1</password>
<initialcontextfactory>
oracle.j2ee.rmi.RMIInitialContextFactory
</initialcontextfactory>
</ejb>


For reasons of standardization a SOAP client is preferable. However low response times and other performance issues are important for good user-interaction. An additional delay of 1.5 seconds every time a user retrieves his or her tasks isn’t acceptable. Instead of using RMI -that is a less standardized protocol- to improve response times, you can also use the Worklist API to not query the entire collection of tasks, but only a certain range. This can then be used in combination with a SOAP client while maintaining acceptable reponse-times. The front-end component does need some modification though to handle navigation and iteration through these task subsets.