Posts Tagged ‘PAPI’


Creating Oracle BPM PAPI Clients

February 17th, 2010 by Mark Peterson • 1 Comment »

To interface Oracle BPM 10g (or AquaLogic BPM 6.x or Fuego) to external systems you may want to use PAPI.  PAPI is the name for the BPM API. It is a carry over from the Fuego days and stood for Portal API.  This is a good name for the API  since the Portal (or workspace) uses PAPI to interface with the BPM engine. This API is available for you to use as well.

Since the workspace uses it, anything you can do from the workspace you can do through PAPI. Likewise most things you can do from the Process Administrator, you can do from PAPI as well. Some common things you can do through PAPI.

  • Create a new process instance or work item.
  • Pause, suspend and resume process instances.
  • Interact with an external UI activity from an external UI.
  • Notify a process that some event occurred and pass in arguments to the process.
  • Create user, roles and assign users to roles.

PAPI is the most versatile tool to use to interface client apps to BPM.  If you just want to notify an instance, you can expose the process and notification waits using BPM web-services. You just have to set a switch to do this and use the WSDL to interface with the process. But you can’t do much more than this with BPM web-services. If you need more functionality, you will need to use PAPI.

I will give you the basic tools to do these things and more from a PAPI client. At the end of this blog, you will find a sample PAPI client Java code. I’ve used this client object to develop client applications. Over the years I’ve added some functionality and taken some away. This has most of what you’ll need.

Running a PAPI Client against Enterprise Standalone

It is difficult to use PAPI to interact with a process running in Studio. You will need to deploy your process to Enterprise Standalone or WebLogic. If you deploy your process to Enterprise Standalone, you will be able to connect to PAPI simply by referring to a copy of directory.properties file.  This file is located in the BPM installation directory.  Before you copy this file be sure it is valid.  This file is created by the Admin tool when it creates and configures the directory.  If you can connect to the directory and processes are being deployed and working then you have a valid directory.properties file.

Running a PAPI Client against a Weblogic Server

If  you’re trying to connect to a process running inside WLS, you need to provide a JNDI name and context factory. All you need to do is include the weblogic.jar file (or wlclient.jar)  with your PAPI client code and specify the connection properties.  The connection properties are stored in a file and referenced by the JNDI context using the following JRE system property.

-Dfuego.j2ee.initialctx.file=c:\bea\config\papiJndi.properties

Place these contents into the referenced file; i.e. papiJndi.properties.  You’ll need to modify the host name and port number according to the Weblogic container settings used by the BPM engine.

# Weblogic JNDI configuration to connect to the weblogic server
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://localhost:7001
# example java.naming.provider.url=t3://localhost:7001

You will also need to do this if your PAPI client is running in a different container than where the PAPI engine is running.  To make this work all you have to do is modify the setDomainEnv.cmd file by adding the JRE system property. This file is located next to the startWeblogic script,  in the user_projects/domains/<your-domain>/bin directory.

Sample PAPI Client Code (Java)

Here’s an example Java client class I find helpful getting started. It contains methods for connecting to PAPI,  searching for instances, executing global activities, and call-back methods for interacting with external interactive activities.  This code will compile if you include the fuegopapi-client.jar file with your code.

</code>

package com.ssglimited.businessServices;

import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import fuego.lang.ConnectionPassport;
import fuego.papi.Arguments;
import fuego.papi.BatchOperationException;
import fuego.papi.Comparison;
import fuego.papi.Filter;
import fuego.papi.InstanceInfo;
import fuego.papi.OperationException;
import fuego.papi.ProcessService;
import fuego.papi.ProcessServiceSession;
import fuego.papi.SearchScope;
import fuego.papi.VarDefinition;

/**
*
* Provide convenience for creating ALBPM PAPI Web Service objects needed
* to utilize External Task functionality.
*
* @author Mark Peterson
*
*/
public class PapiServiceHelper {

//    private static final Log log = LogFactory.getLog(PapiServiceHelper.class);
//    private ProcessService service = null;
private String endPointUrl = "", userId="", password="";
private ProcessServiceSession session = null;
private String directoryFile;

/**
*
* Construction will initialize the necessary PAPI objects for subsequent usage
*
* @param String containing URL of ALBPM engine SOAP server
* @param String containing userid for PAPI connection
* @param String with password
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException as a consequence of using PAPI service
* @throws OperationException
*/
public PapiServiceHelper (){

}

/**
*
* Initializes the necessary PAPI objects for subsequent usage
*
* @return ProcessService used in subsequent operations
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException as a consequence of using PAPI service
* @throws OperationException
*/
private void initSession() throws RemoteException, OperationException {

// Creates the properties to create the ProcessService.
Properties properties = new Properties();

// Set the directory Id that we use.
properties.setProperty(ProcessService.DIRECTORY_ID, "default");

// Set the directory file that we use, this file is in the classpath.
// The directory properties can either be in the classpath, or be a file location.
properties.setProperty(ProcessService.DIRECTORY_PROPERTIES_FILE, "C:\\workspace\\papiSample\\config\\directory.properties");

// Set the maximum size of the instance cache per process.
properties.setProperty(ProcessService.INSTANCES_CACHE_SIZE, "50000");

// Set the folder where PAPI will store catalogs and temporary files.
properties.setProperty(ProcessService.WORKING_FOLDER, "c:\\bea\\temp");

// Set that the sessions will be notified when an instance is updated.
properties.setProperty(ProcessService.UPDATE_SESSIONS_VIEWS, "true");

System.out.println("ProcessService properties=\n"+properties);
// Creates the ProcessService.
ProcessService processService = ProcessService.create(properties);

// Creates the passport for the user which will connect.
ConnectionPassport passport = processService.createPassport(userId);

// Sets the passpord of the user.
passport.setPassword(password);

// Completes the given passport for authentication purposes.
passport.fillPassport();

// Creates a new session.
// The arguments are the passport of the user and the host where the user is connected from.
session = processService.createSession(passport, "localhost");

}

public Map runGlobal(String processId, Map params) throws RemoteException, OperationException {
if (session==null) initSession();

Arguments args = Arguments.create();
Iterator itParams = params.keySet().iterator();
while(itParams.hasNext()) {
String key = (String)itParams.next();
args.putArgument(key, params.get(key));
}

session.runGlobalActivity(processId, args);

Map returnMap = new HashMap();
String[] argNames = args.getArgumentsName();
for(int i=0;i<argNames.length;i++){
returnMap.put(argNames[i], args.getArgument(argNames[i]));
}
return (Map)returnMap;
}

public List getCodes( String type ) throws OperationException, RemoteException {
if (session==null) initSession();

Arguments args = Arguments.create();
args.putArgument("type", type);

session.runGlobalActivity("/StaffReviewProcess/GetCodes", args);

List codesList = (List) args.getArgument("codesList");
System.out.println("CodesList="+codesList);
return codesList;
}

/**
*
* The PAPI <code>prepareExternalActivity</code> service is invoked for the input instance/activity.
*
* @param String containing instance ID
* @param String containing External Task activity name
* @param KeyValuePair array with input arguments of prepare method
* @return KeyValuePair containing PAPI session ID
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException passed along from PAPI
* @throws OperationException
*/
public Arguments runPrepare(String instanceId,String activityNm,Arguments inArgs) throws IllegalStateException, RemoteException, OperationException {

if (session==null) initSession();
Arguments outArgs = session.prepareExternalActivity(instanceId, activityNm, inArgs);
return outArgs;
}

/**
*
* The PAPI <code>commitExternalActivity</code> service is invoked for the input instance/activity.
*
* @param String containing instance ID
* @param String containing External Task activity name
* @param KeyValuePair array with input arguments of commit method
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException passed along from PAPI
* @throws OperationException
*/
public InstanceInfo runCommit(String instanceId,String activity,Arguments inArgs) throws IllegalStateException, RemoteException, OperationException {
if (session==null) initSession();
return session.commitExternalActivity(instanceId, activity, inArgs);
}

public InstanceInfo[] findInstanceByFilter(String activity) throws BatchOperationException, RemoteException, OperationException {
if (session==null) initSession();
String[] processes = session.getProcessIds();
System.out.println("Processes="+processes);
// Search instances which begin with a specific string in an external variable value and
// stay in a specific activity.
Filter filter = ProcessService.createFilter();
SearchScope searchScope = new SearchScope(fuego.papi.ParticipantScope.PARTICIPANT_ROLES,
fuego.papi.StatusScope.ALL);
filter.setSearchScope(searchScope);
filter.setMatchAll(true);
//         filter.addAttribute(session.getVar("MyExternalVariable"), Comparison.BEGIN_WITH, "Fuego");
filter.addAttribute(session.getVar(VarDefinition.ACTIVITY_ID), Comparison.IS, activity);

// Search instances.
InstanceInfo[] instances = session.getInstancesByFilter(processes, filter);
//         instances[0].getVar(arg0, arg1)
return instances;
}

}

<code>

package com.bea.bootcamp.businessServices;//import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;import fuego.lang.ConnectionPassport;
import fuego.papi.Arguments;
import fuego.papi.BatchOperationException;
import fuego.papi.Comparison;
import fuego.papi.Filter;
import fuego.papi.InstanceInfo;
import fuego.papi.OperationException;
import fuego.papi.ProcessService;
import fuego.papi.ProcessServiceSession;
import fuego.papi.SearchScope;
import fuego.papi.VarDefinition;

/**
*
* Provide convenience for creating ALBPM PAPI Web Service objects needed
* to utilize External Task functionality.
*
* @author BEA Professional Services
*
*/
public class PapiServiceHelper {

//    private static final Log log = LogFactory.getLog(PapiServiceHelper.class);
//    private ProcessService service = null;
private String endPointUrl = “”, userId=”", password=”";
private ProcessServiceSession session = null;
private String directoryFile;

/**
*
* Construction will nitialize the necessary PAPI objects for subsequent usage
*
* @param String containing URL of ALBPM engine SOAP server
* @param String containing userid for PAPI connection
* @param String with password
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException as a consequence of using PAPI service
* @throws OperationException
*/
public PapiServiceHelper (){

}

/**
*
* Initializes the necessary PAPI objects for subsequent usage
*
* @return ProcessService used in subsequent operations
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException as a consequence of using PAPI service
* @throws OperationException
*/
private void initSession() throws RemoteException, OperationException {

// Creates the properties to create the ProcessService.
Properties properties = new Properties();

// Set the directory Id that we use.
properties.setProperty(ProcessService.DIRECTORY_ID, “default”);

// Set the directory file that we use, this file is in the classpath.
// The directory properties can either be in the classpath, or be a file location.
properties.setProperty(ProcessService.DIRECTORY_PROPERTIES_FILE, “C:\\workspace\\FtMeade\\papiSample\\config\\directory.properties”);

// Set the maximum size of the instance cache per process.
properties.setProperty(ProcessService.INSTANCES_CACHE_SIZE, “50000″);

// Set the folder where PAPI will store catalogs and temporary files.
properties.setProperty(ProcessService.WORKING_FOLDER, “c:\\bea\\temp”);

// Set that the sessions will be notified when an instance is updated.
properties.setProperty(ProcessService.UPDATE_SESSIONS_VIEWS, “true”);

System.out.println(“ProcessService properties=\n”+properties);
// Creates the ProcessService.
ProcessService processService = ProcessService.create(properties);

// Creates the passport for the user which will connect.
ConnectionPassport passport = processService.createPassport(userId);

// Sets the passpord of the user.
passport.setPassword(password);

// Completes the given passport for authentication purposes.
passport.fillPassport();

// Creates a new session.
// The arguments are the passport of the user and the host where the user is connected from.
session = processService.createSession(passport, “localhost”);

}

public Map runGlobal(String processId, Map params) throws RemoteException, OperationException {
if (session==null) initSession();

Arguments args = Arguments.create();
Iterator itParams = params.keySet().iterator();
while(itParams.hasNext()) {
String key = (String)itParams.next();
args.putArgument(key, params.get(key));
}

session.runGlobalActivity(processId, args);

Map returnMap = new HashMap();
String[] argNames = args.getArgumentsName();
for(int i=0;i<argNames.length;i++){
returnMap.put(argNames[i], args.getArgument(argNames[i]));
}
return (Map)returnMap;
}

public List getCodes( String type ) throws OperationException, RemoteException {
if (session==null) initSession();

Arguments args = Arguments.create();
args.putArgument(“type”, type);

session.runGlobalActivity(“/StaffReviewProcess/GetCodes”, args);

List codesList = (List) args.getArgument(“codesList”);
System.out.println(“CodesList=”+codesList);
return codesList;
}

/**
*
* The PAPI <code>prepareExternalActivity</code> service is invoked for the input instance/activity.
*
* @param String containing instance ID
* @param String containing External Task activity name
* @param KeyValuePair array with input arguments of prepare method
* @return KeyValuePair containing PAPI session ID
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException passed along from PAPI
* @throws OperationException
*/
public Arguments runPrepare(String instanceId,
String activityNm,
Arguments inArgs)
throws IllegalStateException, RemoteException, OperationException {

if (session==null) initSession();
Arguments outArgs = session.prepareExternalActivity(instanceId, activityNm, inArgs);
return outArgs;
}

/**
*
* The PAPI <code>commitExternalActivity</code> service is invoked for the input instance/activity.
*
* @param String containing instance ID
* @param String containing External Task activity name
* @param KeyValuePair array with input arguments of commit method
* @throws IllegalStateException if private variables not initialized
* @throws RemoteException passed along from PAPI
* @throws OperationException
*/
public InstanceInfo runCommit(String instanceId,
String activity,
Arguments inArgs)
throws IllegalStateException, RemoteException, OperationException {
if (session==null) initSession();
return session.commitExternalActivity(instanceId, activity, inArgs);
}

/**
*
* Kill PAPI session
* @throws BatchOperationException
* @throws OperationException
* @throws RemoteException
*
* @throws RemoteException passed along from PAPI
*
*/
//    public void closeSession() throws RemoteException {

//        if (service != null && sessionId != null) {
//        service.close(sessionId);
//            log.info(“service session closed…”);
//        }

//    }
public InstanceInfo[] findInstanceByFilter(String activity) throws BatchOperationException, RemoteException, OperationException {
if (session==null) initSession();
String[] processes = session.getProcessIds();
System.out.println(“Processes=”+processes);
// Search instances which begin with a specific string in an external variable value and
// stay in a specific activity.
Filter filter = ProcessService.createFilter();
SearchScope searchScope = new SearchScope(fuego.papi.ParticipantScope.PARTICIPANT_ROLES,
fuego.papi.StatusScope.ALL);
filter.setSearchScope(searchScope);
filter.setMatchAll(true);
//         filter.addAttribute(session.getVar(“MyExternalVariable”), Comparison.BEGIN_WITH, “Fuego”);
filter.addAttribute(session.getVar(VarDefinition.ACTIVITY_ID), Comparison.IS, activity);

// Search instances.
InstanceInfo[] instances = session.getInstancesByFilter(processes, filter);
//         instances[0].getVar(arg0, arg1)
return instances;
}

/**
* @return the endPointUrl
*/
public String getEndPointUrl() {
return endPointUrl;
}

/**
* @return the password
*/
public String getPassword() {
return password;
}

/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}

/**
* @return the userId
*/
public String getUserId() {
return userId;
}

/**
* @param userId the userId to set
*/
public void setUserId(String userId) {
this.userId = userId;
}

/**
* @param endPointUrl the endPointUrl to set
*/
public void setEndPointUrl(String endPointUrl) {
this.endPointUrl = endPointUrl;
}

public String getDirectoryFile() {
return directoryFile;
}

public void setDirectoryFile(String directoryFile) {
this.directoryFile = directoryFile;
}

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
PapiServiceHelper helper = new PapiServiceHelper();
helper.setPassword(“p”);
helper.setUserId(“Colleen”);
try {
helper.findInstanceByFilter(“WorkOnTask”);
} catch (BatchOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

1 Comment »