Sunday, October 16, 2011

Working with the Human WorkList api and create your own WorkList application

In this blogpost I will explain what is possible with the IWorkflowServiceClient ( HumanTask java client )  so you can integrate this in your own Custom WorkList application.  This way you don't need to use the standard BPM worklist application, add some extra functionality and also don't need to create HumanTask ADF Task Flow and deploy this to the SOA Suite server.

This demo shows you the power of Fusion Middleware where you can combine SOA Suite workflow to your own ADF applications.

At the end of this blogpost I will show you the link for this demo application which also contains the BPEL to create the HumanTasks.

Here are some pics of the demo application. You will get an overview of the tasks assigned to the weblogic user ( normally this will be replaced by the user of the application ). The user can search on certain field, change the ordering and control the maximum rows.


And in combination with the ADF UIShell template of Oracle you can make a multi task handling application. Every task you click on will have its own Tab. Here you can also lookup the extra information which is necessary to the user so it can handle this task.



Time to go back to the code.

I will start with a BPEL which invokes a HumanTask and to make my life easy I will use the flexible text , date or url fields of the HumanTask for my own important data so I don't need to examine payload.
This way you can search on these fields and use it in your own task entity.



And map the payload fields to the flex fields in a Assign activity. These fields are located in the systemMessageAttributes element.


Next is to retrieve these tasks from the java / ejb client. Todo so I need two libraries bpm-infra.jar and bpm-services.jar. Copy these jars from the soa server so you don't get serial id versioning errors.

I will use on behalf of so I don't need to have the password of the user and I can do all the actions of behalf of this user.

Start with a property file or you can set some java parameters

soa.properties
soaserver=soaps3.alfa.local:8001
humantask.user=weblogic
humantask.password=weblogic1

or set these java parameters on the project
-Dhumantask.url
-Dhumantask.user
-Dhumantask.password

For the tasks I will connect to the HumanTask EJB and for the Identities I need to connect the Identity SOAP Service.


We need to have an IWorkflowContext which I can use for the query operation on the Task bean. I will first authenticate with the superuser and then on behalf of the user of my application.

In this query on the human task I can control which attributes I want to use in my application.

List<String> queryColumns = new ArrayList<String>(); queryColumns.add(TableConstants.WFTASK_TITLE_COLUMN.getName());

And if I want to have the payload or the comments, I need to do this.
List<ITaskQueryService.OptionalInfo> optionalInfo =
    new ArrayList<ITaskQueryService.OptionalInfo>(); optionalInfo.add(ITaskQueryService.OptionalInfo.COMMENTS); optionalInfo.add(ITaskQueryService.OptionalInfo.PAYLOAD);

Do ordering on the tasks.

Ordering taskOrdering = null;
if ( "PRIO".equalsIgnoreCase(orderBy) ) {
 taskOrdering = new Ordering(TableConstants.WFTASK_PRIORITY_COLUMN, true,false);
 taskOrdering.addClause(TableConstants.WFTASK_TASKNUMBER_COLUMN, true,false);
} else if ("ID".equalsIgnoreCase(orderBy) ) {
  taskOrdering = new Ordering(TableConstants.WFTASK_TASKNUMBER_COLUMN, false,true);
} else if ("ESC_DESC".equalsIgnoreCase(orderBy) ) {
  taskOrdering = new Ordering(TableConstants.WFTASK_EXPIRATIONDATE_COLUMN, false, false);
} else if ("ESC_ASC".equalsIgnoreCase(orderBy) ) {
  taskOrdering = new Ordering(TableConstants.WFTASK_EXPIRATIONDATE_COLUMN, true, false); }
}

It is also possible to do a search and add a fixed where condition. For this we need to have a Predicate where we can add the states we want to see.

List<String> correctStates = new ArrayList<String>(); correctStates.add(IWorkflowConstants.TASK_STATE_ALERTED); correctStates.add(IWorkflowConstants.TASK_STATE_ASSIGNED);

Predicate predicateBasic = new Predicate(
  TableConstants.WFTASK_STATE_COLUMN,
  Predicate.OP_IN,
  correctStates);

predicateBasic.addClause(Predicate.AND,
 TableConstants.WFTASK_STATE_COLUMN,
 Predicate.OP_NEQ,
 IWorkflowConstants.TASK_STATE_STALE);

This Predicate can be combined to an other Predicate with an other AND / OR and finally added to the queryTasks method of the workflowServiceClient.getTaskQueryService()


To make your life easier try to convert the tasks to your own entity  so you can use your own attributes instead of using text1 etc.

You can download, fork or improve the Demo application at github https://github.com/biemond/soa11g_examples/tree/master/HumanTaskListApp

11 comments:

  1. Its very interesting post .How did u converted the task to entity? I mean whats the starting point for Task project.

    ReplyDelete
  2. Hi Edwin,

    We are just starting a project yhat uses BPM 11 and ADF. I'd lik to know your opinion about approach to integrations thes technologies. Oracle advocates to use adf taskflows inside BPM Workspace. In my opinion this is good aproach for small application with small form to update process data. Except this, all data should be stored in database, so in fact we develope large business components based application. I think, that better way would be create generic adf application (BC + ADF RC) with custom worklist as started page as you described in this post. What is your opinion ?
    I also thing that approaches to build Human Tasks based ADF apps is a good issue for discuss on EMG.

    ReplyDelete
  3. Hi,

    in https://github.com/biemond/soa11g_examples/blob/master/HumanTaskListApp/Tasks/src/nl/whitehorses/fcforms/tasks/services/HumanTaskClient.java

    I convert theses task in List getHumanTasks of the HumanTaskClient class

    and in TaskConvertor I do the transformation

    https://github.com/biemond/soa11g_examples/blob/master/HumanTaskListApp/Tasks/src/nl/whitehorses/fcforms/tasks/utility/TaskConvertor.java

    thanks

    ReplyDelete
  4. Hi Jakub,

    Mostly users don't want to go to a different application ( or a few times a day ), that's why oracle also made it possible in webcenter.

    Mostly you already have a web application where you can integrate this and this application already have all the data the user needs to decide.

    We use a human task textattibute for the taskflow type and some others for the primary keys. With this we can start the specific Task flow and the generic one ( for approval , comments etc)

    this works great and the users think that the workflow is part of the application.

    I know for sure that fusion apps does the same.

    thanks

    ReplyDelete
  5. Hi Edwin,

    thanks for response. We have a dillema between two options:

    1) Build an adf applcation contains BC Model and deploy as a part of BPM Proces Workflow - Oracle suggests this way - in my opinion it's good for small applicatiosn without tabs and complex menu and complex BC model (we need this to persis process data into DB)

    2) Build independent adf application and on the start page display for user his tasks using way you show in this blog post. In my opinon this is the better approach. All we need to get from BPM is task ID, availabe actions and payload (in fact only ID of user application - anyway rest of data we have to get from database not from process).

    Your opinion would be appreciated.

    ReplyDelete
  6. Hi,

    It depends , are you using SOA or bpm with SOA. I heard good things about the new bpm ps4 , where you can customize the work list app.

    But I know you, so you should be able to build the app but if you don't have java web developers go for option 1

    Thanks

    ReplyDelete
  7. Thanks for response Edwin. We are not planning to use SOA - only BPM. It's true - bundeled Worklist is customizable. My doubts affect communication between BPM and ADF. Using Oracle way we generate task flow for all human task, but:
    1) For all human task JDev generates also separate data control stack (in my opinion it should be only one communication point between BPM and all ADF app)
    2) In all task flows there are automatically registered a lot of page flow scope beans and params (not described anywhere - documentation is not asset of BPM 11 :))

    My key doubt is that using oracle approach we unnecessarily will create to complex application.
    As I mentioned before, we will persist process data using BC, so only data we need form payload is ID of master-level row.

    P.S. I think we should invite Andrejus for this discussion and move it to EMG :)

    ReplyDelete
  8. Suppose that in your SOA composite you assign certain human tasks to a group. Then a user belonging to that group wants to acquire a task thru its taskId. Is it correct that you first call TaskService.releaseTask(ctx, taskId) and then acquireTask(ctx, taskId)? It does not work for me if I try to use the same user context (new task owner) in both cases. It remains assigned to group. How are you supposed to create IWorkflowContext for a group? It's supposed to represent a user having a password etc..

    ReplyDelete
  9. is there API for the process? not only human workflow. e.g. I can suspend/resume the process instance even if it is not in human task stage. thanks.

    ReplyDelete
  10. Hi,

    Suppose that in your SOA composite you assign certain human tasks to a group. Then a user belonging to that group wants to acquire a task thru its taskId. Is it correct that you first call TaskService.releaseTask(ctx, taskId) and then acquireTask(ctx, taskId)?

    if it is not acquired then you can acquire it. if it is then you need to have permission to release it and acquire.

    It does not work for me if I try to use the same user context (new task owner) in both cases. It remains assigned to group.

    it will always be assigned to this group. only acquire is changed. but you can assigned it to an other group or person.

    How are you supposed to create IWorkflowContext for a group?

    not possible , a person can belong to a group.

    thanks

    ReplyDelete
  11. Yeah,no need to not call release if a task is assigned to group:-)

    I also realized the importance of acquiredBy attribute. If a user acquires a task which was originally assigned to a group, the acquiredBy field can serve as an indicator of that. The assignee lists and task state ( ASSIGNED) do not change in that case.

    ReplyDelete