List all BPM Processes for a user

Hello again,

I have blogged (this time) on bpmtech on the above topic.

Happy coding.

Posted in Uncategorized | Leave a comment

Where our readers come from

Just a curiosity for those interested in such things – WordPress has just given us bloggers the ability to see where our readers are coming from.  Hopefully they will provide a widget so that we can put this on our site with up to date data, but for now, here is a snapshot of where our readers come from, covering all visits since the blog was set up until today:

Let us take this opportunity again to thank you all for visiting and we hope you found something useful here!

Posted in Uncategorized | 2 Comments

Using Oracle BPM Activity Guide APIs

We have recently heard of the usage of the ‘Process Driven UI’ pattern fairly often (particularly with Oracle BPM 11 banking customers). I hope to be able to write up more about this pattern in a later blog. But the crux of the pattern is: BPM processes drive what UI screen needs to be painted next. As you can imagine, latency is all too important a criterion along with back-end processing for successful implementation of that pattern.

For now, my endeavour was to use the Activity Guide APIs to generate the data seen on the workspace Activity Guide tab. This is hopefully useful for customers who want to write their custom UI equivalent to the default Activity Guide tab off the default BPM workspace.  The screenshot is below. Please notice that my BPM process has two milestones and one Human Task under each milestone.

Assuming you have gotten the workflow context etc., fastforwarding to the meat of the issue: Using the PS4FP Activity Guide APIs, one needs to:

  • Get all Activity Guide instances for a given user (API call: agQuerySvc.queryAGDisplayInfos)
  • Iterate through the list of AGDisplayInfos and get an AGInstanceId
  • For each AGInstance Id, get the agDisplayInfo (agQuerySvc.getAGDisplayInfoDetailsById)
  • For each AGInstance Id, get the corresponding milestone (agDisplayInfo.getMilestoneDisplayInfo)
  • For each Milestone, get the taskList in that milestone (milestoneDisplayInfo.getTaskDisplayInfo)
  • For each task, fetch details, say status and title in this example (taskDisp1.getTask)

I have used the standard workflow java sample in Authenticate.java and enhanced it for this purpose. That is an easy starting point!
Please note the following in that context:
1. The build.xml needs another few jar files other than the one that is packaged with workflow java samples
2. As usual, the wf_client_config has connection details.
3. The bpm project MultipleTasks Project has 2 human tasks have been created, 2 milestones and each of these tasks belong to 1 milestone. The Process.Owner role is granted to jstein after deployment.

While the AGAPIs for PS4FP have been documented, please note that there are a few documentation bugs currently being worked on, including on the sample therein.
Caveat: Some code refactoring in terms of moving some constants to different jar files is expected. And so, the jars referenced here are likely to change in PS5 and beyond.

I am going to try putting the source code: The BPM Process and the java code on java.net..(If for whatever reason I cant, I will be sure to blog source code here soon…)

Happy exploring AG APIs.

(Editing post for source code etc. below)


import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.List;
import oracle.bpel.services.workflow.WorkflowException;
import oracle.bpel.services.workflow.client.IWorkflowServiceClient;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;
import oracle.bpel.services.workflow.query.ITaskQueryService;
import oracle.bpel.services.workflow.task.impl.TaskUtil;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.verification.IWorkflowContext;

import oracle.bpel.services.bpm.common.IBPMContext;

import oracle.bpel.services.workflow.IWorkflowConstants;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.verification.IWorkflowContext;
import oracle.bpel.services.workflow.query.impl.TaskQueryService;
import oracle.bpel.services.workflow.client.WorkflowServiceClientContext;
import oracle.bpel.services.workflow.metadata.config.ResourceBundleInfo;
import oracle.bpel.services.workflow.activityguide.query.IAGQueryService;
import oracle.bpel.services.workflow.activityguide.query.impl.AGQueryUtil;
import oracle.bpel.services.workflow.activityguide.query.*;
//import oracle.bpel.services.workflow.activityguide.query.impl.AGQueryService;
import oracle.bpel.services.workflow.activityguide.query.model.AGDisplayInfo;
import oracle.bpel.services.workflow.activityguide.query.model.MilestoneDisplayInfo;
import oracle.bpel.services.workflow.activityguide.metadata.IAGMetadataService;
import oracle.bpel.services.workflow.activityguide.metadata.impl.AGMetadataService;
import com.oracle.bpel.activityguide.instance.model.MilestoneInstanceType;
import oracle.bpel.services.workflow.activityguide.query.model.TaskDisplayInfoType;
import sun.security.util.Password;

import oracle.bpel.services.workflow.repos.Ordering;
import oracle.bpel.services.workflow.repos.Predicate;
import oracle.bpel.services.workflow.repos.TableConstants;

import oracle.bpel.services.workflow.IWorkflowConstants;
import oracle.bpel.services.workflow.client.IWorkflowServiceClient;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;
import oracle.bpel.services.workflow.repos.Ordering;
import oracle.bpel.services.workflow.repos.Predicate;
import oracle.bpel.services.workflow.repos.TableConstants;

import oracle.bpel.services.workflow.repos.PredicateConstants;

import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.verification.IWorkflowContext;
import oracle.bpel.services.workflow.activityguide.query.model.AGDisplayInfo;
import oracle.bpel.services.workflow.activityguide.query.model.MilestoneDisplayInfoType;
import com.oracle.bpel.activityguide.instance.model.MilestoneInstanceTypeImpl;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.task.model.TaskType;

public class Authenticate
{

private static IWorkflowContext ctx;
 private static ITaskQueryService querySvc ;
 private static IWorkflowServiceClient wfSvcClient;
 public static void main(String[] args) throws Exception {
 if (args.length != 3 || !("SOAP".equals(args[0]) || "REMOTE".equals(args[0]))) {
   System.out.print("Usage java Authenticate protocol(SOAP/REMOTE) user(jcooper) password(welcome1)");
   return;
 }
 authenticate(args[0], args[1], args[2]);
}

public static void authenticate(String protocol, String user, String password)
 throws WorkflowException {

System.out.println("Authenticating user " + user + ".....");

Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String> properties =
 new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String>();
 //added below and commented out from wfclientconfig.xml
 properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL, "weblogic");//weblogic username
 properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS, "welcome1");//plain pwd

 // get the client
 //IWorkflowServiceClient wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(protocol, properties, Util.getLogger());
 wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(protocol, properties, Util.getLogger());
 querySvc = wfSvcClient.getTaskQueryService();
 // IWorkflowContext ctx = querySvc.authenticate(user, password.toCharArray(), "jazn.com");
 IWorkflowContext ctx = querySvc.authenticate(user, password.toCharArray(), "jazn.com");
 if (ctx == null)
 {
   System.out.println("ctx is null");
 } else {
   System.out.println("Authenticated successfully");
   System.out.println("Authenticated user info from IWorkflowContext:");
   System.out.println("Context created time: " + (new Date(ctx.getStartDateTime())));
   System.out.println("User: " + ctx.getUser());
   System.out.println("User Time Zone: " + ctx.getTimeZone().getDisplayName());
   System.out.println("User Locale: " + ctx.getLocale());
 }

 try{
   //calling testquery
   testQueryAGDisplayInfos();
 }
 catch (Exception eee){
   System.out.println("error");
   eee.printStackTrace();
 }

 }

private static void testQueryAGDisplayInfos()
 throws Exception
 {
   List agQueryColumns = new ArrayList();
   // agQueryColumns.add("MILESTONE_STATE");
   // agQueryColumns.add("DEFINITION_ID");
   //List agQueryColumns = new ArrayList();
   agQueryColumns.add("IDENTIFICATION_KEY");
   agQueryColumns.add("TITLE");
   agQueryColumns.add("CREATOR");
   agQueryColumns.add("CREATION_DATE");
   agQueryColumns.add("STATUS");
   IAGQueryService agQuerySvc = wfSvcClient.getAGQueryService();
   System.out.println("after AGQuerySVC");
   //Ordering order = new Ordering(TableConstants.WFTASK_INSTANCEID_COLUMN, false, true);

   // Query for all AG instances belonging to user say jstein
   List agDisplayInfoList =
   agQuerySvc.queryAGDisplayInfos(IAGQueryService.AG_PROCESS_TYPE_BPM, ctx,
   new ArrayList(),
   IAGQueryService.AGAssignmentFilter.ADMIN,
   null, //agPredicate,
   null, //ordering,
   0,
   0);

   List taskList=null;
   for (int a=0; a<agDisplayInfoList.size();a++)
   {
     String instanceId = ((AGDisplayInfo) agDisplayInfoList.get(a)).getInstanceId();
     //AGDisplayInfo agDisplayInfo = (AGDisplayInfo) agDisplayInfoList.get(a);
     AGDisplayInfo agDisplayInfo = agQuerySvc.getAGDisplayInfoDetailsById(IAGQueryService.AG_PROCESS_TYPE_BPM,
     ctx,
     new Long(instanceId), new ArrayList(),
     IAGQueryService.AGASSIGNMENT_FILTER_ADMIN);
     System.out.println("******for AGInstancID :"+instanceId+"********");

     System.out.println("AG title:" + agDisplayInfo.getTitle());

     System.out.println("milestone display info list size:" + agDisplayInfo.getMilestoneDisplayInfo().size());
     //MilestoneDisplayInfo msDisplayInfo = (MilestoneDisplayInfo)agDisplayInfo.getMilestoneDisplayInfo();

     for (int i=0; i< agDisplayInfo.getMilestoneDisplayInfo().size(); i++)
     {
       MilestoneDisplayInfo milestoneDisplayInfo = ((MilestoneDisplayInfo) agDisplayInfo.getMilestoneDisplayInfo().get(i));
       System.out.println("-----------------for milestone name :"+milestoneDisplayInfo.getTitle()+"---------");

       System.out.println("Milestone title: " + milestoneDisplayInfo.getTitle());
       System.out.println("Milestone Name: " + milestoneDisplayInfo.getName());

       List<TaskDisplayInfoType> taskDisplayInfoList = milestoneDisplayInfo.getTaskDisplayInfo();
       System.out.println("Total number of tasks: " + taskDisplayInfoList.size());
       for(int j=0; j< taskDisplayInfoList.size();j++)
       {

         TaskDisplayInfoType taskDisp1 = taskDisplayInfoList.get(j);
         TaskType task1 = taskDisp1.getTask();
         System.out.println("^^^^^^^^^^^^^^^^^^for task Id:"+task1.getSystemAttributes().getTaskNumber()+"^^^^^^^^^^^^^^^^^^");
         System.out.println("Task Status: "+task1.getSystemAttributes().getState());
         System.out.println("Task Title: "+task1.getTitle());

       } //taskDisplayInfoList

     } //MilestoneDisplayInfoList
   } //agDisplayInfoList
 } //method
} //class

Note: the classes in build.xml (for the most part the same as in the Workflow Java samples)


<path id="client.classpath">
 <pathelement path="${bea.home}/wlserver_10.3/server/lib/wlfullclient.jar"/>
 <pathelement path="${bea.home}/wlserver_10.3/server/lib/wlclient.jar"/>
 <pathelement path="${bea.home}/oracle_common/webservices/wsclient_extended.jar"/>
 <pathelement path="${bea.home}/Oracle_SOA1/soa/modules/oracle.soa.fabric_11.1.1/bpm-infra.jar"/>
 <pathelement path="${bea.home}/Oracle_SOA1/soa/modules/oracle.soa.fabric_11.1.1/fabric-runtime.jar"/>
 <pathelement path="${bea.home}/Oracle_SOA1/soa/modules/oracle.soa.workflow_11.1.1/bpm-services.jar"/>
 <pathelement path="${bea.home}/Oracle_SOA1/soa/modules/soa-startup.jar"/>
 <pathelement path="${bea.home}/Oracle_SOA1/soa/modules/oracle.soa.bpel_11.1.1/orabpel.jar"/>

<pathelement path="./config"/>
 </path>

Note: wf_client_config.xml


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <workflowServicesClientConfiguration xmlns="http://xmlns.oracle.com/bpel/services/client">
 <server default="true" name="default">
 <localClient>
 <participateInClientTransaction>false</participateInClientTransaction>
 </localClient>
 <remoteClient>
 <serverURL>t3://localhost:7001</serverURL>
 <!--userName>jstein</userName>
 <password encrypted="true">4tORP+F+3jNupTEwSeZj3A==</password-->
 <initialContextFactory>weblogic.jndi.WLInitialContextFactory</initialContextFactory>
 <participateInClientTransaction>false</participateInClientTransaction>
 </remoteClient>
 </server>
 </workflowServicesClientConfiguration>

Posted in Uncategorized | 1 Comment

Worklist build for 11.1.1.6 (PatchSet 5) released

Have just uploaded a build of the custom BPM worklist sample which is built against BPM 11.1.1.6.  You can find the download links and JavaDoc on the main worklist page.  The code is available in the subversion trunk (for now) or tag VERSION-1.6.

This is basically the same as the last version of the sample, just recompiled for the new release of BPM.  I am planning to add some significant new functionality to the sample to coincide with BPM 11.1.1.7.

I am also working on a C#/.Net version of the worklist.  See some details here if you are interested.

Posted in Uncategorized | Tagged , , | Leave a comment

Oracle Fusion Middleware on JDK 7

In case you did not notice, you may be interested to know that most of the Oracle Fusion Middleware 11g platform is now supported on Java 7.  This is effective from WebLogic Server 10.3.6 and Oracle Fusion Middleware 11.1.1.6.  You can check the details for your particular product and operating system here.

Posted in Uncategorized | Tagged , , , , , | 2 Comments

Step by step instructions on building a SOA cluster – with video

Just came across this and wanted to share – step by step video instructions on building a two node SOA (and AIA Foundation Pack) cluster!  Cool!

Posted in Uncategorized | Tagged , , | 1 Comment

Unit Testing Asynchronous BPEL Processes Using soapUI

This is a topic I have been interested in for a while.  I have seen it done by some of my colleagues, especially in AIA environments, and I have been waiting to get an opportunity to work on it and document it.

But I recently found a great article from Daniel Amadei here.  I strongly encourage you to take a look at it if you are at all interested in test automation and/or continuous integration.

I am planning to build this kind of testing into my continuous integration project here.

Posted in Uncategorized | Tagged , , , , | Leave a comment

Be aware of JDK 1.6.0_30 with BPM or SOA on Windows Server

Have not done extensive testing of this, but I have noticed on a few BPM 11.1.1.6 installs on Windows Server 2008 R2 and also on Windows 7 – both 64-bit – that BPM is very unstable with JDK 1.6.0_30 (64-bit).  By unstable I mean slow and crashes with an OutOfMemory or similar after 10-15 minutes of use.

I have found on these systems that changing to 1.6.0_26 fixed all problems and dramatically improved performance.  So that is what I did!  As I said, this is not scientific, I did not do extensive testing or work out why it was having problems – at the time I did not have the time to spare, I just needed it fixed.  But I am posting it anyway just in case it helps someone out.

Note that I have not seen this issue on any other operating system.

Posted in Uncategorized | Tagged , , , , , | Leave a comment

PS5 released

In case you missed it – Oracle Fusion Middleware 11.1.1.6 (the long awaited ‘PatchSet 5’) has been released.  You can find some info about new features in BPM here and SOA here.

The documentation is here – note that we have the new docs.oracle.com site which is also being indexed properly by Google now (so I’m told) – addressing a long time complaint about searchability of the Oracle documentation.

And of course you can download it all from OTN.

For BPM 11g customers, this release provides a full and properly supported mechanism to get all the new features that were added in the Feature Pack patch.

Posted in Uncategorized | Tagged , , | Leave a comment

Choosing BPMN or BPEL to model your processes

With Dave Shaffer

Recently, I had a discussion with several colleagues and one of our large customers about when to use BPMN and when to use BPEL to model business processes.  I have discussed this topic before in this post but this conversation opened up an interesting new angle on the topic, which I wanted to share with you all.

First of all, let me be clear about the scenario here.  This is a large customer who is going to make extensive use of both BPMN and BPEL in their BPM/SOA environment.  They are not trying to decide which one to use exclusively – it is given that both BPEL and BPMN will be used extensively.  So the question here is about how to come up with a consistent approach to deciding which to use when – what to do with BPMN and what to do with BPEL.

The new perspective in this conversation was about how to choose the modeling language based on the fault/exception handling requirements of the process.  If you are not familiar with the options available for fault handling in BPMN and in BPEL, you should quickly review these sources:

You will notice that there are some differences in the capabilities of the products today.  If you look back over the last few releases of BPM, you will see that there has been a significant investment in adding more fault management capabilities for BPMN processes, and it would be reasonable to assume that this will continue.

But even while the Oracle platform holds the promise of equally rich fault handling in either BPEL or BPMN, one can make a case that the fault handling capabilities in BPEL are especially suitable for system to system integration, particularly when you need to use a distributed transaction or when compensation is required.  Besides, these kinds of highly technical fault handling capabilities are a task probably best suited for more technical kinds of processes and people.  And finally, the directed graph nature and ‘alter flow’ capability in BPMN can make it more difficult (or potentially impossible) to employ the same techniques.

However, the fault handling in BPMN is rather well suited to ‘business’ faults – not enough stock to fill an order, credit check failed, order line contains a discontinued product, order cancelled, things like that.

So this leads to the following suggested approach for this customer use-case:

  • Write top level (i.e. true ‘business’ processes) in BPMN,
  • Do not perform any kind of system interaction in these processes – don’t use adapters, call web services, etc.,
  • Use activities or embedded sub-processes with boundary events and event sub-processes to handle all business faults that may occur,
  • Make sure to have a ‘catch all’ event sub-process to handle any failures that are not specifically handled,
  • Theoretically there should never be a system fault in these BPMN processes,
  • Whenever there is a need to do some actual work, delegate this to BPEL, i.e. use a service activity with implementation type ‘service call’ to have BPEL go do the work,
  • Make the BPEL processes atomic, so that they can easily be retried, rolled back, etc.,
  • Use the fault management framework to control the handling of faults in the BPEL processes, and
  • Keep BPEL ‘worker’ processes in separate composites from BPMN ‘business’ processes.

This may not be perfect, but we think it offers a new, and very relevant, real-world perspective on how to decide which modeling notation is right for your processes.  We are sure interested to hear your thoughts and comments.

For a start, here are Dave’s thoughts on this idea:

First I would just like to reinforce the constraints around the scenario that this advice applies to because I think customers would come up with different approaches, and Oracle would have different best practices, when the question is asked around a greenfield project as to when to use BPEL and when to use BPMN.  In those scenarios, the advice would not be to wrap each system call in BPEL, since the unique value proposition of the Oracle platform is that the same system integration capabilities are available natively in both BPEL and BPMN.  However, I think the guidelines above make sense for a customer who will be mixing and matching BPEL and BPMN throughout their processes and applications and where it is assumed that most projects will include both.  In this case, it becomes important to strive for consistent guidelines as to where to draw the line for what to do in the BPEL part of a process and what to do in the BPMN part.  In this case, the fault handling capabilities are indeed richer in BPEL today vs what is possible in BPMN and even though they may be equivalent in the future, there are certainly many kinds of fault handling logic, compensation, etc. that will be deeper than the business would want to go.  The division of labor described above by Mark then results in not just using the best tool for the job, but also leverages the heterogeneous BPEL/BPMN architecture at this customer to make the BPMN “business view” of the process as clean as possible.

Posted in Uncategorized | Tagged , , , | 1 Comment