I’m pretty well known for carrying everything I think I need on a project in my backpack. I carry dry erase markers, an extension cord, several thumb drives (I’m always losing them), a network cable and even beef jerky to survive the meal deficient flights. To paraphrase the comedian George Carlin - I simply feel more comfortable carrying all my stuff everywhere I go.
On a recent Oracle BPM project, I noticed that a customer adhered to a similar philosophy. While I’m a fan of having a single BPM Object instance variable store the work item instance’s information throughout the life of the process, having this object store everything including a Swiss army knife is going a bit overboard. You should suspect that you’ve got too much stuff when your instance variable uses a BPM Object that has over two groups or there are a hundred attributes.
Here’s an example of too much stuff. A healthcare company might have a work item instance in a process that involves a patient. At one step in the process, the patient’s medical history needs to be looked up. Instead of storing just the just the basic patient information (e.g. patient name or patient id, name, date of birth), 30 years of medical history is now stored with the work item. One argument I hear for carrying the patient’s entire medical history is that the time required to re-read the information downstream in the process using a web service or database is too high. What the developer does not realize is that they have put their project and Oracle BPM engine at risk by doing this and that there is a simple fix.
The “too much stuff” syndrome quickly degrades the Oracle BPM engine’s performance once in Production. You only have so much memory on any machine or VM environment. To work around the problem when testing, a developer will sometimes bump their engine’s maximum instance size setting from 16kb to 1024kb to accommodate the bloated instances flowing through their processes. The problem multiplies when you’re using either Split or Multiple activities, every copy generated by these automatically produces duplicates of the memory sucking bloated instances. Once deployed to production, the engine will quickly tire from all the stuff you’re making it carry.
Here are a few simple recommendations that project managers and developers should follow:
-
- Code Review - Early in the project, conduct a code review that includes a review of the primary instance variable used throughout the process.
-
- Use an Outside Database - Many times an outside database should instead be used to persistently store the information instead of the Oracle BPM engine’s database. The megabyte of information stored in the instance variable does not need to be read in every activity of the process and the information is not updated in every activity of the process. Oracle BPM assumes, however, that this is the case with normal instance variables - your instance megabyte is read from and written to the engine’s database at the beginning and end of each activity’s execution even if it is not displayed or updated. If you instead store the id in the instance variable, this id could be used to easily and quickly read or update the information in the outside database when necessary. The bottom line is to not treat your instance variable as the database of record. Use an outside database for this.
- Throttle Down the Engine's Maximum Instance Size - Strive to keep the maximum instance size setting on the Engine throttled down to 128 or 256kb. Keep this setting the same for your DEV, QA / UAT and PROD Oracle BPM engines. Projects deployed to these engines will be caught immediately.
- Use Separated Instance Variables - Instance variables have a property called “Category”. As you are creating Instance variables, you usually leave the category set to the default - “Normal”. If you feel it is necessary to store large BPM Objects in an instance variable (again – all your stuff), always set the instance variable’s category property to “Separated”. Although there is no easy way to detect the size of an instance variable, if you believe the instance variable will store a large amount of information (10 Kb or more) go ahead and mark it as separated. As the name implies, during runtime Oracle BPM automatically stores these variables separately in the database to avoid performance problems. They are only read when the instance needs to either display their value in the activity. They are only written back to the Engine’s separated instance table when the information has been changed inside the activity. This differs from the normal instance variable’s behavior where normal instance variables are always read and written to the engine's database.
- Set Unneeded Variables to Null - Inside a Multiple activity always set the copy’s unneeded instance variables and attributes to null. This will cause the copies of the instance generated to consume less memory than the original work item instance.
Comments
Separated Variables retrieval at PAPI client
Hi,
We are one requirement where we have instance variable "insApplicationDetails" which is of BPMObject which may hold huge data, so we have changed the category from "Normal" to "Separated" since the size may go above 50KB.
We have written PAPI client code and trying to retrieve the value of "insApplicationDetails".
If the instance variable is of type "Normal", the underlying code is able to retrieve the instance variable details.
Code:
Properties configuration = new Properties();
configuration.setProperty(ProcessService.DIRECTORY_ID, "default");
configuration.setProperty(ProcessService.PROJECT_PATH,"C:
Documents and Settings\\Administrator\\OracleBPMWorkspace
ExceptionHandling_AKBank1");
configuration.setProperty(ProcessService.WORKING_FOLDER, "/tmp");
try {
ProcessService processService = ProcessService.create(configuration);
// ///////////////// Establish a session ///////////////////
ProcessServiceSession session = processService.createSession("Administrator", "", null);
DynamicObject dym = (DynamicObject) session.instanceGetVariable(
"/ExceptionHandlingUsage1#Default-1.0/1/0",
"insTechnicalException");
}
catch(Exception e)
{
e.printstacktrace();
throw e;
}
This code is running successfully and we are getting all values which we require at PAPI.
Now, If the instance variable is changed to type "Separated", the underlying code is throwing the below exception.
Error-Trace:
Exception in thread "Main Thread" java.lang.ClassCastException: fuego.lang.Void
at PapiClient.main(PapiClient.java:51)
Please suggest what can be the probable resolution for the issue.
If we have instance variables as "Separated", what is the technique to retrieve its value at PAPI client.
Thanks in advance,
Abhishek
A must follow best practice
Dan,
You've brought out a very important point with very specific example. It complements my post "Do not treat Process Solutions as Applications" perfectly. It's critical to leave the process layer light weight, not overburden it with the application type personality that the heavy UI emphasis and data processing brings. You have covered the context of Oracle BPM, but the same applies also to Savvion, iProcess, Lombardi, Pega, Appian, IBM... so a must read and must follow best practice...
- Ashish
http://ashishbhagwat.wordpress.com
Independent data layer
You shouldn't need to move data around; data should be in an independent data layer that is shared and re-used by the process layer (except for few activity specific variables).
To avoid duplicating and replicating information, this data layer should be virtual and access the appropriate information from the legacy systems while guaranteeing integrity and performance.
Data is not a Swiss army knife: many processes will use simultaneously the same information.