Saturday, 8 October 2011

BPEL Human Workflows

Let's talk about Human workflows. I have given an introduction to Human workflows in one of my previous posts and I will like to start from where I had left there.
The utility of Human workflows is huge because of the worklist associated with it. Worklist is a list of tasks which need a user’s immediate attention. It is an out of the box feature of BPEL. Every user in an application has his worklist and the worklist is controlled by a set of functions defined in the Task service. Task service is another out of the box feature of BPEL. It is coupled with human workflows and is added to your BPEL code as soon as you drag a Human work flow into your BPEL composite
Now the bad news, there is not too much of documentation available on the functions defined in the task service and if you are implementing human workflows for the 1st time then you might struggle a bit to find the correct method of invocation. This is because of the fact that there are too many parameters for some of the functions in the services associated with human workflows. Most of these parameters are optional and atleast I had a lot of trouble figuring out the right combination to make a particular function work

I want to focus on 2 important things in this article:

      1.       I want to jot down the process of creation of Human workflows
      2.       I want to talk about some of the most common functions of the task service and the mechanism of using them. I believe this discussion will give you a hint of using other functions as well

I recommend that you go through my 1st article on BPEL before reading this because I will assume that you know

      a.       The process of deploying the code
      b.      About component palette and the process to drag activities and adapters in the right places in the implementation
      c.       The process of creation of an empty asynchronous BPEL process
      d.      The process to create a copy operation

Let’s get started:

1.       Let’s start by creating a simple asynchronous BPEL process and drag a human workflow activity in it and click on the ‘Create Task Definition’ button as shown below

2.       A wizard pops up

3.       Clicking on ‘OK’ button brings you to a page where you get to define the task service.

There are a lot of configurable parameters of the task service, the most important being the ‘Assignment and Routing Policy’. It lets you chose the type of approval process. You can either chose to have a group vote with a certain cutoff percentage defining the amount of required voting or may have a single approver or may chose from many of the other available options
It will take another 5 to 6 articles to describe the configuration of the task service and they will not add any value. The documentation in the below link is good enough to give detail info on the configuration of the .task file.

I have chosen to create a very simple task configuration. My configuration consists of the following

               a.       A single approver with ‘APPROVE’ and ‘REJECT’ as the 2 possible outcomes of the task.
               b.      /task:task/task:systemMessageAttributes/task:textAttribute2 set in the Assignment and Routing

         Point (b) holds a lot of value. We will put a user id in this field and the value held by /task:task
         /task:systemMessageAttributes/task:textAttribute2 variable will be the one who will be the 1st
         owner of the task which means that if you try to delegate the task using other ids, you will get the
          following error

4.    If you click on the green icon on the extreme right of ‘Assignment and Routing Policy’, you will be directed to a page which lets to fix the following 2 values
              a.       The type value: Type drop down lets you pick from the number of approval mechanisms available

           b.      The dynamic user XPath
Click the highlighted icon under ‘Dynamic User Xpath’ to specify the person who can take an action on the task. This icon takes you to an expression builder which helps you with the syntax of framing the correct path.

Click on ‘OK’ after doing all this and save your task service configuration. Switch to your .bpel file, which should now look like the following

Yes it is pretty and colorful

5.       Now let’s create a custom table to store the handle of the human tasks. This table can also be joined with other custom tables to find out human workflow tasks corresponding to each user request. Below is the definition of my table but you can make this as elaborate as you want

6.       If you expand the green colored human task in step 4 then you will see the below
If you cannot see the links between initiateTask_HumanTask1_1, recieveCompletedTask_HumanTask1_1 and the Task Service then, flip between the source and the diagram tab which are immediately below the this window

7.       Now create 2 copy operations, as shown below, in HumanTask1_1_AssignTaskAttributes assign activity.

Assign this expression to textattribute1 of the task service as shown below.

Similarly assign the input string to textattribute2.

8.       Drag a database adapter

Select insert operation from the wizard and select the column in which you intend to insert. Since our custom table only has 1 column so we select that and finish the creation of the database adapter to insert in the custom table

9.       Your implementation will now look like the following

10.   Now drag an invoke activity from the component palette and put it between initiateTask_HumanTask1_1 and  recieveCompletedTask_HumanTask1_1

Connect this invoke to the newly created adapter and select the insert operation. Also create the input variable to this db adapter by clicking on the highlighted icon. Let us now assign a value to this variable

11.    Drag an assign activity just above this invoke activity. Perform an assignment using the copy operation as shown below. This wizard opened after we selected the copy operation in the newly dragged assign activity

12.   Lets now move to the switch case below the recieveCompletedTask_HumanTask1_1 activity

Delete the ‘otherwise’ branch. The 1st 2 correspond to ‘APPROVE’ and ‘REJECT’ outcomes configured in the task service

Click the remaining 2 assign activities and put the following assignments in both of them

13.   Your implementation will look like the following

14.   Most of the job is done. Deploy this code on the BPEL server now

15.   Go to the newly deployed process. It should be visible in the dashboard tab under the domain in which you have deployed your process

16.   Enter your userid whom you intend to make the owner of the human  task and click on ‘Post XML Message’ button. I entered ‘E061096’. This value will be assigned to textattribute2 because of the copy operation created in step 7. Again we had assigned textattribute2 in the Assignment and Routing policy section of the .task file. So the value passed here will have the privilege to be the 1st owner of the task. ‘E061096’ is configured in my identity manager. You will have to integrate your OID with the identity service of BPEL to use the users and roles defined in your OID. Below links gives good info on this configuration

The structure of the identity service and its WSDL are
You will see the below screen after passing the userid and clicking the ‘Post XML Message’ button

17.    Clicking on the visual flow link will display the following. The process has stopped at the receiveComplete activity. This is because this activity expects one of the possible outcomes i.e. either ‘APPROVE’ or ‘REJECT’.

18.   Let us now check the worklist for 3 users. The worklist is a jsp page and can be customized depending on the need. I have picked my own columns and we have complete freedom to pick any column of the wftask table and we also have the freedom to display it the way we like. We can do all this by editing the jsp of the worklist. Wftask table is in the ORABPEL schema. It is a system table used for the maintainance of tasks. This table stores all the necessary values of the human task.It also has a number of message columns like textattribute1 etc. which can be used to store custom values. These custom values can be used to join the task table with some of our own tables.
Let me explain you the role of the 3 users, I am talking about.
      a.       E061096: This id has been passed from the console. So this becomes the governing user who becomes the 1st owner of the task
      b.      Bpeladmin: We are sending webservice calls from the BPEL server and we have logged-in in the BPEL server using this id
      c.       E253010: We will delegate the task to this user and bpeladmin. We are doing this to check the mechanism of delegating the task to multiple assignees
At this point we see that the assignment is only in E061096’s worklist.

19.    Lets now delegate the task to bpeladmin and E253010 using delegateTask function of the task service. We will have to use the token of E061096. Using the token of any other user will result in the following error. I will explain the ‘token’ in the end. Talking about the token here will break the flow

Oh .. and I want you to have a look at the current values for some of the columns in the wftask table. There is not too much to explain in these columns but I want you to observe, how these values change in the lifecycle of this human workflow

Let’s also check the value in our custom table. This custom table was only created to show the mechanism of inserting task values like process id in custom tables.

Time for the delegateTask call.

If you delegation is successful then you should see the below message

Let’s now check the worklist of all the 3 users

As you can see the task is removed from the worklist of ‘E061096’ and is added to the worklists of ‘bpeladmin’ and ‘E253010’.

Let’s check wftask table now. Note that the value of ‘assigneeusers’ column has changed

20.   Lets us now try to finish the task. To finish the task, one of the 2 users i.e. ‘bpeladmin’ or ‘E253010’ will have to acquire the task. Acquiring of task is not required in case of single assignee.
Acquiring is done using the acquireTask function of the task service. Any of the 2 assignees or ‘E061096’ can acquire the task.  It is important to uncheck the checkbox next to ‘task’ and ‘credential’. Unchecking is required to frame the correct soap envelope. Task id is a unique reference for the task and token is a return message of the authenticate function (We will discuss this in detail after the current example finishes). Since these 2 are sufficient inputs to execute the function, so we uncheck the optional other parts.
Note that no change has happened in the selected columns of wftask table

Let’s also check the state of the instance in the ‘view flow’.

21.       Let us now complete the task. We should use the updateTaskOutcome function of the Task service and pass either ‘REJECT’ or ‘APPROVE’ request (These were configured in the .task file) to the receiveComplete activity. Below function call completes this BPEL instance. This function can be executed either by ‘E253010’ (The one who acquired the task) or by ‘E061096’ (The value in textattribute2, which is configured in the .task file under ‘Assignment and routing policy’) but not by ‘bpeladmin’

Note the change in the outcome and state columns and also note that the task has been removed from the worklist of all the users

We can see below that the instance has completed

Let me briefly tell you about the token.

Token is a context id returned by the authenticate function. Authenticate function accepts the oc4j admin userid, oc4j admin password, realm and the userid whose token is required. This process is similar to impersonation in some other tools. Since this token is returned after the authentication process, so it can be used in every place where we require the user to be authticated. Instead of authticating the user, we just past the token. I have been using soapUI to generate the tokens

Authenticate function is defined in the task query service. Below are the urls
http:// <webserverIPAddress>:<webserverPort>/integration/services/TaskQueryService/TaskQueryService

Final comments:

I have used a few functions here, but if you get a good hold of these then using other functions should not be tough. I have shown the xml envelope for the delegateTask function and the html form for the other functions. This xml envelope can be passed from almost all tools which work on either PL SQL or Java or give freedom to code any one of these two. An example of calling a webserivce from pl sql code is in my previous post at step 40.  

Share your thoughts and let me know if you need more info on this topic. I do not have an access to BPEL environment anymore, so I will not be able to come up with more case studies but I can definately help you with my learning in BPEL


Anonymous said...

Brilliant, I spend more nights to implement all this Human Workflow process. You made so many buddies life easy.. Keep up the good Work..

Balaji S

Vishal Pathak said...

Many thanks for your valuable comment Balaji. I seek your thoughts and guidance in the future as well :)


Anonymous said...

Great article vishal. Keep up the good work.

Harris M.

Vishal Pathak said...

Thanks a lot, Harris

PS: Screenshots have been taken by deploying my code on your servers :). Please don't escalate :)


Balaji Subramaniam said...

Sweet things are easy to Buy, Sweet words are easy to Say. But sweet people like HARRIS MIR are very difficult to find :)

Anonymous said...


Excellent article. I have one question. Oracle worklist api has token based authentication (getWorkflowContext(String ctxToken)), so how do I generate the token on the fly (programatically). Please share your inputs.


Vishal Pathak said...

'authenticate' function returns workflow context. We can call this fuction from a PL SQL procedure.

The below article shows how to call webservice function from pl sql function

So make a call to authenticate rom PLSQL proc. Call this proc on the fly


Aamir said...

Hi Vishal

I really appropriate you work and to shared with us.