Posts Tagged ‘aqualogic’


Customizing Oracle BPM using Worklist Decorator

February 19th, 2010 by Mark Peterson • No Comments »

Customizing the Oracle BPM Worklist can be done by creating and adding a Worklist Decorator class to your configuration. There are many reasons why you may want to do this. You may want to color code low, medium and high priority work items, format a display value with an icon or image, or you may just want to alternately shade lines in the BPM workspace as shown below.

dec_worklist

Oracle BPM versions 6.x to 10g (Aqualogic BPM )  allow you to do this.  For the complete java class see WorkListDecorator Sample Code below. This code implements three methods that can be used to alter the way the work list appears these methods are as follows:

public String getCellStyle(String viewName, InstanceInfo instance, Column columnInfo, int rowNo) ;

public String getRowStyle(String viewName, InstanceInfo instance, int rowNo) ;

public String getValue(String viewName, InstanceInfo instance, Column columnInfo, Locale locale, String value, int rowNo) ;

These three methods are call-back methods used by the BPM Workspace application to get custom attributes associated with the work-list.  The input parameters contain pertinent important information you can use to decorate the work-list as required. This information is described in the table below.

Field Name Description
String viewName Name of the view. The default work-list name is unified-inbox. If you create custom views, this will be populated with the name of the custom view.
InstanceInfo  instanceInfo Contains detailed information about the instance; like activity name, instance name, instance variables and process details.
Column Contains information about the column, like column size, format and ID.
Locale locale Contains information about the locale
String value Contains the display value (String contents) of the field value.
int rowNo The row number starting with zero.

<br/>

To register your custom decorator object with your workspace, locate the workspace.properties files and modify the entry as show below. This file is located in the <BPM_HOME>/webapps/workspace/WEB-INF directory

fuego.workspace.worklist.styleResolverClassname=com.ssglimited.workspace.view.WorkListDecoratorImpl

You will need to compile your WorkListDecorator object and place the complied java object (.class) or jar file in the <BPM_HOME>/webapps/workspace/WEB-INF/classes or <BPM_HOME>/webapps/workspace/WEB-INF/lib directory. If you are using BPM in an application server like Weblogic, you will need to re-build the workspace and redeploy the workspace ear file. This can be done in the Process Administrator.

If you are having difficulty getting this to work, turn on the Workspace log. For enterprise versions, simply look in the App Server console or edit the logging in the workspace.properties file. For Studio, refer to my blog post on Workspace Logging.

WorkListDecorator Sample Code for Shading lines in the Work-list

</code>

package com.ssglimited.workspace.view;

import java.util.Locale;

import fuego.workspace.model.view.WorkListDecorator;
import fuego.papi.InstanceInfo;
import fuego.papi.Presentation.Column;
public class WorkListDecoratorImpl implements WorkListDecorator{

public String getCellStyle(String viewName, InstanceInfo instanceInfo, Column columnInfo, int rowNo) {
return "";
}
public String getRowStyle(String viewName, InstanceInfo instanceInfo, int rowNo) {
String inlineStyle="background-color: #ffff"; //White
if (rowNo % 2 > 0) {
inlineStyle="background-color: #f8f8f8"; //Gray
}
return inlineStyle;
}

public String getValue(String viewName, InstanceInfo instance, Column columnInfo, Locale locale, String value, int rowNo) {
// System.out.println("***Mark Test **** "+viewName+" column"+ arg2.getId()+"arg4"+ value +" "+rowNo);
return value;

}
}

No Comments »

 

How to Turn on Workspace Logging in Oracle BPM Studio (10g or 6.x)

February 19th, 2010 by Mark Peterson • 3 Comments »

If you are having trouble with the Workspace in Oracle BPM Studio, it is easy to turn on logging – once you know how.  You might need to do this if you are customizing the workspace or adding a custom decorator to the worklist panel.

To access the logs, locate the eclipse.ini file and add the following line to the beginning of the file. Do not add any blank lines or spaces before or after this entry. This file is located in the <OracleBPMStudioHome>/eclipse directory.

-consoleLog

Next time you restart BPM studio, a console window will open with Studio. Logging from the workspace, Tomcat and eclipse will go into the console. This works with all versions of Oracle BPM running in eclipse; Oracle BPM 10g and Aqualogic BPM 6.x

3 Comments »

 

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 »

 

The Background of BPM

April 7th, 2009 by Mark Peterson • No Comments »

Businesses look to IT to increase productivity through automated systems. Many advances have been made in this regard, but businesses also expect IT to find ways to reduce the cost to implement these systems. Over time, systems like CRM, Document Management and Inventory Control have been created and deployed using a common platform to suit business needs for a wide array of industries.
Let me give you an example of a well-known platform and its uses. Siebel/CRM systems and Documentum/document repositories are widely accepted tools in such diverse industries as Finance, Medical, Manufacturing and Telecommunications. Even though the underlying company content differs, at a task level the systems are still performing similar tasks. For instance, order entry is a process comprised of a number of tasks which can be automated. The same goes for document approval. These kinds of tasks cut across industries.
However, these applications only improve productivity for “local” or single-department business problems. I will discuss the shortcomings of this method in my next Blog entry and an alternative concept.
Next week: The Problem
Mark J. Peterson, Senior Systems Architect for SSG, has more than 25 years of experience in software design and development with a specialization in BPM. Mark spent 10 years with Oracle and Fuego as a lead solution architect and instructor in the consulting organization.

No Comments »