Identifying HumanTask TaskId from IdentificationKey using XREF
By kyap on Feb 27, 2014
Since Oracle BPM PS4FP there is an activity task called UpdateTask, which is able to alter a task within the process. By using it, we can Withdraw, Suspend or Resume a task based on the name of the task (implicitly using the activityId), all instantiated tasks within the process(generally used when we want to terminate the process), or using explicitly the instantiated task id.
Problem: when multiple instances of the same task (instantiated within a multi-instance subprocess for example), how can I withdraw a specific instance only? On the paper, as mentioned above we can use the TaskId option in the UpdateTask to achieve this goal... but how to get the TaskId?
For once, the documentation could not be any help... it mentions that we can provide a "custom" TaskId during the Human Task instantiation, but without any further indication. So after multiple attempts, including modifying the execData/systemAttributes/taskId directly, I gave up the idea of trying to set my own TaskId. Instead, I explored another direction by checking how I can leverage the IdentificationKey that I have full control on, and when set properly I can definitely end up with a clean one-to-one mapping with the TaskId. The challenge is then to extract the mapping out.
Long story short, I will skip all the detail steps I went through before coming up with the following solution. I can only say that I initially start with using Event Task/Mediator to capture the IdentificationKey/TaskId couple, then creating a XREF definition and an utility service to handling the data lifecycle in the XREF map... A long, but necessary journey to end up with this final and clean solution, which can be considered as a generic pattern for others usages.
And as usual, you can download the complete project of the solution before hand here.
1. First of all, create a simple process with correlation including a multi-instance subprocess with parallel mode, so that we can instantiate multiple instances on a same Human Task at once. Of course, make sure that each instance can be uniquely identified by the IdentificationKey. In my case, I append the correlationId with the pre-defined variable loopCounter. (it is important to have the correlationId in the IdentificationKey, I will explain later)
2. Create an event subprocess to take an input argument the IdentificationKey, from which we can extract the correlationId by leveraging the "#" character I specify above
3. Now we need to create a XREF definition file. This XREF definition will contain 2 columns - IdentificationKey & TaskId
4. In the XREF editor, check the option Optimize to "Yes", then "Generate Table DDL" By doing so, you will see a DDL statement to be executed into your SOAINFRA database. This table will be used as a key-value map, accessible via the out-of the box XREF XPath functions (more detail on XREF here)
5. This is the tricky part: DO NOT EXECUTE the ddl statement as it!
XREF is a generic feature for developer to temporary store process data directly into the SOAINFRA, shareable across multiple processes running from different context. In our case, the data are already present in the SOAINFRA schema, via the WFTASK table. So, we do not need to create the table, to populate, to lookup or to delete data into it. We just need to convert the CREATE TABLE ddl statement into a CREATE VIEW ddl statement to map out the IdentificationKey/TaskId (or any other process/task metadata that you would like to access from the BPM repository from your own process !!!).
6. Here's the CREATE VIEW that I used, but you can amend the WHERE condition to better fit your specific need. Run the view creation ddl into your database:
CREATE OR REPLACE VIEW XREF_TASKIDREF
AS SELECT IDENTIFICATIONKEY, TASKID
AND IDENTIFICATIONKEY IS NOT NULL;
7. To finish, configure your UpdateTask activity by extracting the TaskId by using the XREF function with IdentificationKey as argument, and you are done !
Now, let's do a simple testing creating a process with 4 tasks instantiated together:
Then, just select one of the tasks to withdraw by selecting the withdrawTask operation and using the IdentificationKey as argument