Thursday, July 14, 2011

Querying Oracle BPM Process Instances

This is the first in a series of posts related to the BPM 11g Java API. As far as I know, as of this writing, there is no official Oracle BPM 11g Java API documentation that is being release yet, but the corresponding jars are already present on a standard JDeveloper installation (probably after installing BPM Extension).
The purpose of this post is to show simple runnable classes so readers can easily have an acquintance with the BPM 11g APIs, without needing to setup a complex web project.

We can manipulate BPM processes through a BPMServiceClient that we can acquire from a BPMServiceClientFactory. Below is a utility class that I set to easily acquire a client instance for my testing. This class need the following jars in the classpath: Oracle.bpm.client.jar, Oracle.bpm.project.model.jar, and Oracle.bpm.runtime.jar which are present inside the BPM folders in "MIDDLEWARE_HOME\jdeveloper\soa\modules" directory.
package soadev.bpmclient;

import java.util.HashMap;
import java.util.Map;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.client.IWorkflowServiceClient;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;

import oracle.bpm.client.BPMServiceClientFactory;
import oracle.bpm.services.client.IBPMServiceClient;

public class Fixture {
    private static String url = "t3://localhost:8001";
    
    public static BPMServiceClientFactory getBPMServiceClientFactory() {
     Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String> properties =
            new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String>();

        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                             WorkflowServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY
                            .EJB_PROVIDER_URL,url);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY
                                      .EJB_INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        return BPMServiceClientFactory.getInstance(properties, null, null);
    }

    public static IBPMContext getIBPMContext(String username,
                                             String password) throws Exception{      
        return getBPMServiceClientFactory().getBPMUserAuthenticationService()
                                      .authenticate(username, 
                                                    password.toCharArray(),
                                                    null);
    }

    public static IWorkflowServiceClient getIWorkflowServiceClient() {
        return getBPMServiceClientFactory().getWorkflowServiceClient();
    }
    
    public static IBPMServiceClient getBPMServiceClient(){
        return getBPMServiceClientFactory().getBPMServiceClient();
    }
}


Below is a sample class that demonstrate querying of BPM process instances. It shows how to compose Predicate, Ordering, and IInstanceQueryInput objects.
package soadev.bpmclient;

import java.util.ArrayList;
import java.util.List;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.repos.Column;
import oracle.bpel.services.workflow.repos.Ordering;

import oracle.bpel.services.workflow.repos.Predicate;
import oracle.bpm.services.instancemanagement.model.IProcessInstance;
import oracle.bpm.services.instancequery.IColumnConstants;
import oracle.bpm.services.instancequery.IInstanceQueryInput;
import oracle.bpm.services.instancequery.IInstanceQueryService;
import oracle.bpm.services.instancequery.impl.InstanceQueryInput;

public class GetProcessInstances {
    
    public static void main(String[] args) {
        GetProcessInstances client = new GetProcessInstances();
        client.testGetProcessInstances();
    }
    
    public void testGetProcessInstances(){
        try {
            IInstanceQueryService queryService =
                Fixture.getBPMServiceClient().getInstanceQueryService();
            IBPMContext bpmContext = 
                Fixture.getIBPMContext("pino", "password1");
            List<Column> columns = new ArrayList<Column>();
            columns.add(IColumnConstants.PROCESS_ID_COLUMN);
            columns.add(IColumnConstants.PROCESS_NUMBER_COLUMN);
            columns.add(IColumnConstants.PROCESS_STATE_COLUMN);
            columns.add(IColumnConstants.PROCESS_TITLE_COLUMN);
            columns.add(IColumnConstants.PROCESS_CREATOR_COLUMN);
            columns.add(IColumnConstants.PROCESS_CREATEDDATE_COLUMN);

            Ordering ordering = new Ordering(IColumnConstants.PROCESS_NUMBER_COLUMN,
                                             true,true);  
            Predicate pred = new Predicate(IColumnConstants.PROCESS_STATE_COLUMN,
                   Predicate.OP_EQ,
                   "OPEN");
            IInstanceQueryInput input = new InstanceQueryInput();
            input.setAssignmentFilter(IInstanceQueryInput.AssignmentFilter.MY_AND_GROUP);
            
            List<IProcessInstance> processInstances =
                queryService.queryInstances(bpmContext, columns, pred, ordering,
                                                   input);
            System.out.println("ProcessId\tProcess#\tState\tTitle\t\t\t\t\tCreator\tCreadedDate");
            for (IProcessInstance instance : processInstances) {
                System.out.println(instance.getSystemAttributes().getProcessInstanceId()
                                   + "\t" + instance.getSystemAttributes()
                                                              .getProcessNumber() 
                                   + "\t" + instance.getSystemAttributes().getState() 
                                   + "\t" + instance.getTitle()
                                   + "\t" + instance.getCreator()
                                   + "\t" + instance.getSystemAttributes()
                                                        .getCreatedDate().getTime());
            }
            if (processInstances.isEmpty()){
                System.out.println("no result");
            }
        } catch (Exception e) {
            // TODO: Add catch code
            e.printStackTrace();
        }
    }
}

Below is a sample result when I run it on my machine:

You can access the sample application on this link.

Kudus

Kudus to the following blogs and OTN forum posts:

Cheers!

9 comments:

  1. Hi Pino,
    while running this application I am getting result as "no result".
    I have bpm instances in my server.Can you tell me where might be the problem.

    ProcessId Process# State Title Creator CreadedDate
    no result []

    ReplyDelete
    Replies
    1. Hi vishnu,
      1)Are you sure that those processes are not yet completed?
      2)Did you provide appropriate user and password inforamtion in the code above "Fixture.getIBPMContext("pino", "password1");"?
      3)Can you access the same processes using the same user in BP< workspace?

      Regards,
      Pino

      Delete
  2. Dear Pino,
    Thanks for this nice code.
    I have a problem in this code snippet.
    List processInstances =
    queryService.queryInstances(bpmContext, columns, pred, ordering,
    input);

    I got the following exception:

    javax.ejb.EJBException: CORBA MARSHAL 0 No; nested exception is:
    org.omg.CORBA.MARSHAL: vmcid: 0x0 minor code: 0 completed: No; nested exception is: org.omg.CORBA.MARSHAL: vmcid: 0x0 minor code: 0 completed: No
    org.omg.CORBA.MARSHAL: vmcid: 0x0 minor code: 0 completed: No
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)


    Can you help me solving this error?

    ReplyDelete
    Replies
    1. Thanks a lot I solved the problem.
      The solution is that I was importing some wrong libraries. Always use weblogic.jar and remove any other weblogic client library. This will solve the problem

      Delete
  3. Can this sample code be used in 11.1.1.6 env? I run this sample in 11.1.1.6 env then I get error message as below:
    Exception in thread "main" java.lang.NoClassDefFoundError: oracle/bpm/metadata/history/HistoryService
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:630)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:614)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:305)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
    at oracle.bpm.client.BPMServiceClientFactory.getBPMServiceClient(BPMServiceClientFactory.java:240)
    at oracle.bpm.sample.test.Fixture.getBPMServiceClient(Fixture.java:44)
    at oracle.bpm.sample.test.GetProcessInstances.testGetProcessInstances(GetProcessInstances.java:26)
    at oracle.bpm.sample.test.GetProcessInstances.main(GetProcessInstances.java:21)
    Caused by: java.lang.ClassNotFoundException: oracle.bpm.metadata.history.HistoryService
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:305)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
    ... 16 more

    Can anybody know what is going on & how to solve this?

    ReplyDelete
  4. Hi,
    Please see the running project on 11.1.1.6 at my github repo below:
    https://github.com/rommelpino/bpmclientapp

    ReplyDelete
  5. Hi,
    I have the same issue as 李加西, can you share what are the different of the source code to work with 11.1.1.5 and 11.1.1.6?

    Interestingly, if I add jar oracle.bpm.metadata-interface.jar into my project war file, then it work on on 11.1.1.6 and I can get rid of the error.

    Thanks,

    ReplyDelete
    Replies
    1. @QuyTran: Bạn là người Việt nam phải không?

      Delete
  6. Hi Pino,

    We are trying to get CompositeInstanceId , CompositeName of all the process instances with matching PROTECTEDTEXTATTRIBUTE1 value.
    But not getting the results, if we use predicate as below :

    Predicate pred = new Predicate(Column.getColumn("PROTECTEDTEXTATTRIBUTE1"), Predicate.OP_EQ, "2200");

    If we leave the predicate, then the instances are returned, but the methods
    processinstance.getSca().getCompositeInstanceId()
    processinstance.getSca().getCompositeName());
    are not returning any values.
    Could you please help?

    Regards,
    Subha

    ReplyDelete