Saturday, March 22, 2008

Programatically controlling the length of expiration/escalation on BPEL Human Task

By default Oracle BPEL lets you expire or escalate tasks on a pre-determined duration basis. But consider the situation where you want the task duration to be 8 working hours before expiration, and working hours are only the time between 8 am an 5 pm, Monday through Friday -- how can you do this?

The options in the standard task dialog don't really accommodate this, but you can work around it. You can provide a variable to the task that has this information. Here are the five basic steps to making this work:

1) Create a BPEL variable of type string. For this example I use "strExpirationMinutes". This will hold the number of minutes to wait before expiring a task.

2) In your human task definition, define a parameter of type string. For this example let's call it "ExpirationTime"

3) In your human task block, assign the value of strExpirationMinutes ( bpws:getVariableData('strExpirationMinutes') ) to the parameter ExpirationTime

4) In your human task definition, set the expiration/escalation policy to be "By Expression" and provide the XPath to reference the passed in parameter. For this example the XPath would be: /task:task/task:payload/task:ExpirationTime

5) Prior to the human task block in the BPEL flow assign a value to strExpirationMinutes of the form "PTxM" where x is the number of minutes before expiration. I typically do this via a embedded Java block.

Here is the Java code for our example:

String tmp = "PT";   
int iMins = 0;
int hrs8 = 60*8;
int hrs23 = 60*23;
int hrs24 = 60*24;

java.util.Calendar calNow = java.util.Calendar.getInstance();

int hours = calNow.get( java.util.Calendar.HOUR_OF_DAY );
int minutes = calNow.get( java.util.Calendar.MINUTE );
int dow = calNow.get( java.util.Calendar.DAY_OF_WEEK );

// if a M-T
if (dow>=2 && dow<=5) {
// if starting before 8 am - add 8 hours plus the interval between now and 8 am
if (hours<8) {
iMins = (60-minutes) + ( (8-hours-1)*60 )+ hrs8;

// if starting between 8 am and 9 am - just add 8 hours
} else if (hours==8 || ( hours==9 && minutes==0) ) {
iMins = hrs8;

// if starting between 9 am and 5 pm - just add 23 hours
} else if (hours>=9 && (hours<17 || (hours==17 && minutes==0)) ) {

iMins = hrs23;

// if starting after 5 pm - add 8 hours plus the interval between now and 8 am
} else {
iMins = (60-minutes) + ( (24-hours-1)*60 ) + hrs8 + hrs8;
}

// if Fri
} else if (dow==6) {
// if starting before 8 am - add 8 hours plus the interval between now and 8 am
if (hours<8) {
iMins = (60-minutes) + ( (8-hours-1)*60 )+ hrs8;

// if starting between 8 am and 9 am - just add 8 hours
} else if (hours==8 || ( hours==9 && minutes==0) ) {
iMins = hrs8;

// if starting between 9 am and 5 pm - add 23 hours plus the two we days
} else if (hours>=9 && (hours<17 || (hours==17 && minutes==0)) ) {

iMins = hrs23 + hrs24 + hrs24;

// if starting after 5 pm - add 8 hours duration plus the interval between
// now and 8 am saturday, plus the 2 we days
} else {
iMins = (60-minutes) + ( (24-hours-1)*60 ) + hrs8 + hrs8 + hrs24 + hrs24;
}

// if Sat
} else if (dow==7) {
// add 8 hrs duration, plus the time between now and midnight sat, plus
// all of sunday, plus 8 hrs for monday before 8 am
iMins = (60-minutes) + ( (24-hours-1)*60 ) + hrs8 + hrs8 + hrs24;

// if Sun
} else {
// add 8 hrs duration, plus the time between now and midnight sun,
plus
// 8 hrs for monday before 8 am
iMins = (60-minutes) + ( (24-hours-1)*60 ) + hrs8 + hrs8;
}

// finish build the time string
tmp = tmp + iMins + "M";

// save the string to bpel proc and audit
setVariableData("strExpirationMinutes", tmp);
addAuditTrailEntry("strExpirationMinutes:",tmp);

No comments: