内容


使用 WebSphere BPM V6.2 动态检索和映射人工任务信息

简介

为了实现灵活性,业务流程管理通常需要动态人工任务分配。在 WebSphere Process Server 中,可将人工角色动态分配给每个流程实例的人工活动,在设计时加以指定。但是,在流程模板中进行运行时人工任务分配是不可能的。换言之,仅可在设计时或运行时在实例级分配人工任务角色,但是不能从模板中随时分配。

在本文中,您将了解如何基于流程模板人工活动动态分配人工任务角色。对于在运行时需要流程模板与其用户配置动态映射的 BPM 应用来说,该方法很有用。本文提出的解决方案是一种松耦合的用户角色安全集成解决方案。

本文主要面向业务流程专家、架构师和精明的业务用户。您应当对 Business Process Execution Language (BPEL)、WebSphere Business Process Choreographer (BPC)、WebSphere Integration Developer 和 WebSphere Process Server 有一个基本的了解。此外,您应当对 Java™ 2 Platform Enterprise Edition (J2EE) 安全角色集成和用户配置有基本的了解。

解决方案场景

在一些业务应用程序中,用户角色分配是独立于业务流程人工角色分配进行的。在建模一个业务流程时,不为人工活动分配用户角色或仅仅给定一个默认值。之后基于集中维护的用户配置存储库将人工任务角色映射到业务流程。在运行时,一个用户角色服务(人工任务分配)负责分配用户角色给流程实例人工任务活动,其中存储库中有相应的映射关系。

本文描述的场景在以下情况下适用:

  • 人工任务角色分配是高度动态的且需要版本控制。
  • 用户角色和流程人工任务映射可以可视地加以管理。
  • 用户配置是集中维护的,且包含 LDAP 域以外的信息。

图 1 说明了解决方案的架构。

图 1. 解决方案架构
解决方案架构
解决方案架构

在解决方案中有 4 个部分:

  • Development Environment:这是一个产生 BPEL 的开发工具环境,比如 WebSphere Integration Developer,从 WebSphere Business Modeler 这样的建模工具中导入或修改。通常,对于这个基于流程模板的解决方案,用户角色不是在设计时分配的。定义的流程模板(没有角色分配)被送入流程服务器中,同时流程模板在 User Role Provisioning 组件中创建一个模板克隆,或者如果已经有模板存在,就更新该模板。
  • User Role Provisioning:这是一个应用程序或组件,处理用户角色安全与业务流程的映射,产生一个具有人工任务角色映射的版本化流程模板。一名用户(通常具有职称和/或头衔)与一个组织中的一个组相关联,一个组通常与业务流程中的一个用户角色相对应。用户角色与流程模板人工任务之间的映射类似于在设计时的人工角色指定。版本化的流程模板获取由管理员或业务用户在运行时确定的已分配人工任务角色。
  • Human Task Assignment:这是一个用户角色服务组件,负责分配人工任务给流程实例。它要么基于用户角色配置发送人工服务角色给流程实例,要么使用 BPC Human Task Manager API 动态处理人工任务分配。
  • Process Server:这是一个部署环境,包含最新的流程模板和从模板产生的流程实例。

总而言之,从 Development Environment 中的 BPEL 生成工具发展而来的业务流程(模板级)被送入 Process Server 运行时,并与 User Role Provisioning 组件中的流程模板快照同步。这能够让用户通过一个可视映射 GUI 动态地映射业务流程人工任务角色,该 GUI 对用户角色组织之间的关系和人工任务角色与业务流程之间的关系提供清晰的视图。流程模板快照与流程服务器部署中的最新流程模板同步。这一同步是通过事件处理或轮询或用户端触发等其他首选方式实现的。人工任务分配(User Role Service 组件)处理人工任务角色安排或对每个流程实例的分配。

测试环境

该解决方案基于 WebSphere BPM V6.2(WebSphere Process Server V6.2 和 WebSphere Integration Developer V6.2),它在运行时不支持人工任务模板配置。

实现解决方案

在本节中,您将了解如何实现解决方案。基本上,您需要实现三个编程任务,如图 2 所示。

图 2. 实现组件
实现组件
实现组件

解决方案的 “Process Template Update & Sync” 组件获取最新的流程模板信息并同步化 User Role Mapping 组件中的模板快照,然后该组件根据业务规则、由业务用户或管理员通过 GUI 访问映射流程模板到人工任务角色。Human Task Assignment 组件负责实例级的人工角色映射。

以下部分描述实现细节并提供编码示例。

更新和同步化流程模板

根据流程模板变更的触发机制,有不同的编码可实现运行时的流程模板与用户角色映射期间的模板快照之间的及时同步。您首先需要做的是获取流程模板信息,包括其人工任务节点活动。任务模板是版本化的模型,包含任务规范,使用输入、输出和错误来描述传递给来源于模板的任务的数据和执行任务后产生的数据。

在该场景中,您需要从模板获取用户角色分配信息。但是,流程模板 API y 上没有现成可用的用户角色属性(通过 Microsoft® 在 WebSphere Integration Developer 等开发人员环境中的 IntelliSense),不过您可以看到其他通用模板属性的列表。

要获取详细的任务模板信息,您必须首先获取流程模板 ID,然后将流程模板 ID 与任务容器上下文 ID 关联起来。下面是从模板中获取所需人工任务节点信息的步骤:

  1. 同时初始化 Business Flow Manager 和 Human Task Manager,如清单 1 所示。
清单 1. 初始化 BusinessFlowManager 和 HumanTaskManager
Context context = new javax.naming.InitialContext();

//Lookup the Local Home Interface
LocalHumanTaskManagerHome taskHome = (LocalHumanTaskManagerHome) 
context.lookup("java:comp/env/ejb/LocalHumanTaskManagerHome");
//Access the humantask manager local interface
taskManager = taskHome.create();
//Lookup the Local Home Interface
LocalBusinessFlowManagerHome processHome = (LocalBusinessFlowManagerHome) 
context.lookup("java:comp/env/ejb/LocalBusinessFlowManagerHome");
//Access the businessflow manager local interface
processManager = processHome.create();
  1. 获取流程模板 ID,如清单 2 所示。
清单 2. 通过 BusinessFlowManager 查询流程模板 ID
//input the process template name.  eg, creditRequestProcess
String whereClause  = "PROCESS_TEMPLATE.NAME = 'creditRequestProcess'";
ProcessTemplateData[] processTemplate = processManager.queryProcessTemplates(whereClause,
(String)null, (Integer)null, (TimeZone)null);
int processOfInstances = processTemplate.length;
PTID ptid = null;
String ptidString = null;
String processName = null;
if (processOfInstances == 1){
	ptid = processTemplate[0].getID();
	ptidString = ptid.toString();
    processName = processTemplate[0].getName();
}
  1. 现在使用流程模板 ID 联接任务模板视图与流程模板视图,并查询人工任务活动的任务模板,如清单 3 所示。>
清单 3. 使用 HumanTaskManager 查询任务模板信息
whereClause = "TASK_TEMPL.CONTAINMENT_CTX_ID = ID('"+ptidString+"')";
TaskTemplate[] taskTemplates_temp = taskManager.queryTaskTemplates(whereClause,
(String)null, (Integer)null, (TimeZone)null);
for (int i = 0;i < numOfInstances;i++) {
	//you can get taskTemp API from taskTemp: 		
	TaskTemplate taskTemp = taskTemplates_temp[i];
String taskTempName = taskTemp.getName();	
}

欲了解详细的任务模板 API 信息,参阅 WebSphere Business Process Management V6.2 Information Center 中的 Interface TaskTemplate 主题。

映射用户角色

接下来,您需要将人工任务角色映射到一个或多个业务流程活动。该流程与业务流程应用松散地耦合,并充当中央用户安全配置存储库。详细的映射和 GUI 设计超出了本文的范围。

下面是 User Role Mapping 表的一个示例。您可以扩展示例来包含您组织的真实映射关系。

CREATE TABLE "DB2ADMIN"."TASK_MAPPING_GROUP” (
		  "PROCESS_NAME" VARCHAR (256) NOT NULL,
		  "TASKTEMP_NAME" VARCHAR (256) NOT NULL,
		  "GROUP_NAME" VARCHAR (256) NOT NULL)
		 IN "USERSPACE1”;

其中:

  • PROCESS_NAME:流程模板名称
  • TASKTEMP_NAME:任务模板名称
  • GROUP_NAME:组名称或角色名称

在运行时分配人工任务角色

在运行时,BPC API 基于用户配置存储库中的映射动态地将人工角色分配给流程实例。我们来看一下动态角色分配的两种方法:上下文变量和后处理器插件。

上下文变量方法

因为内联人工任务可以访问流程上下文,它们可以访问流程上下文变量。在开发一个流程时,您可以使用 wf:variable 动态地将角色信息分配给任务,如图 3 所示。

图 3. 任务模板开发
任务模板开发
任务模板开发

如图 3 所示,task1 是一个流程变量。您可以在流程开始时初始化该变量。如图 4 所示,task1task2 流程变量在 Init 脚本中得到初始化。

图 4. 任务变量赋值
图 4. 任务变量赋值
图 4. 任务变量赋值

您可以将 group BO(业务对象) 用作流程输入变量的一部分。该业务对象的初始值是在流程开始时定义的,如清单 4 所示。

清单 4. 通过任务模板名称和流程模板名称查询 ROLE_NAME
processName = … // get value from listing 2
taskTempName = …//get value from listing 3
String sql = "select distinct GROUP_NAME from DB2ADMIN.TASK_MAPPING_GROUP 
where PROCESS_NAME = " + processName +" and TASKTEMP_NAME = " + taskTempName + ";
ResultSet ret = statement.executeQuery(sql);
If(ret.next())
  groupName=ret.getString(“GROUP_NAME”);
…………………………
HashMap groupNames = …..// Because we would get at least one task template from 
                        // Listing 3, there is at least one group name, 
                        // In the HashMap, the key is  
                        // taskTempName and the value is the groupName
// create BO object and assign groups BO from groupNames variable
groupsBO = boFactory.create(“http://DynamicAssign”,”groups”);
List groups = new ArrayList();
Iterator iterator = groupNames.keySet().iterator();
While(iterator.hasNext()){
  groupBO = boFactory.create(“http://DynamicAssign”,”group”);
  String taskTempName = (String) iterator.next();
  String groupName = (String) groupNames.get(taskTempName);
  groupBO.setString(“taskname”,taskTempName);
  groupBO.setString(“groupname”,groupName);
  groups.add(groupBO);
}
groups.setList(“groups”,groups);
……………………………………….
ClientObjectWrapper inputMessage = new ClientObjectWrapper(InterfaceProcessBO);
// initiate ClientObjectWrapper here
…………………………………………
// set the groups to inputMessage variables;
…………………………………………
processManager.initiate(“process”, inputMessage);// start process

您可以选择性地使用一个事件处理程序来在运行时修改任务角色变量。例如,在开始流程并输入 task1 且您希望更改下一个任务(task2)的潜在所有者时,您可以调用事件处理程序来修改第二个任务的变量。此外,如果您不想在流程输入变量中介入组变量,可以在流程中使用一个事件处理程序来根据需要获取该信息。使用事件处理程序可以提供给您更高的灵活性。

后处理器插件方法

后处理器插件方法为 Human Task Manager 人员解析提供强大的查询功能,返回分配给特定角色的用户列表,例如,任务的潜在所有者。您可以创建插件来更改人员解析返回的人员查询的结果。图 5 展示了后处理器插件方法。

图 5. 后处理器插件
后处理器插件
后处理器插件

如清单 5 所示,使用 StaffQueryResultPostProcessorPlugin 接口来实现人员查询结果的后处理,然后可以为任务、升级、任务模板和应用组件修改该结果。

清单 5. 后处理器插件接口
StaffQueryResult processStaffQueryResult( StaffQueryResult originalStaffQueryResult, Task
task, int role, java.util.Map  context );

您可以动态地修改人员查询结果来分配任务模板角色,如清单 6 所示。

清单 6. 后处理器插件任务分配
StaffQueryResult processStaffQueryResult( StaffQueryResult originalStaffQueryResult,
                                           Task task,
                                           int role,
                                           java.util.Map context ) {

     String taskName = task.getName() ;
     String piid = task. getContainmentContextID().toString();
     String processName = processManager.query() //get processName via piid
     String sql = "select distinct GROUP_NAME from 
     DB2ADMIN.TASK_MAPPING_GROUP where PROCESS_NAME = " + processName +" 
     and TASKTEMP_NAME = " + taskTempName + ";
     ResultSet ret = statement.executeQuery(sql);
     If(ret.next())
        groupName=ret.getString(“GROUP_NAME”);
     String sql_queryUserByGroup = …..; // query the USER_ID via group_id
     ret = statement.executeQuery(sql_queryUserByGroup);
     List users = new ArrayList();
     String userId = null;
     if(“xxx”.equals(taskName)) { // xxx means special task name
        while(ret.next()){
           userId = ret.getString(USER_ID);
           users.add(staffResultFactory.newUserData(userId, Locale.getDefault(), null));
        }
        return staffResultFactory.newStaffQueryResult(users);
     }
}

欲了解详细的后处理器插件信息,参阅 WebSphere Process Server V6.2 Information Center 中的 Creating, installing, and running plug-ins to post-process people query results 主题。

您应当使用哪种方法?

当涉及到动态人工任务角色分配时,上下文变量和后处理器插件方法都适用。那么如何决定要使用哪种方法呢?

上下文变量方法在项目设置中易于使用。限制在于,人员分配标准是在开发人工任务时预定义的。例如,如果您选择 GROUP MEMBERS,变量将代表组名称值,而且不可以在运行时将其改为 USERS BY USER ID

后处理器插件方法有点更难于掌握,但是比上下文变量方法更强大。您需要实现 StaffQueryResultPostProcessorPlugin 接口,并使用 WebSphere Process Server 注册插件。该方法允许您添加或删除用户并更改用户或组信息。它还允许您更改结果类型,例如,从用户列表到组或到每个人更改结果类型。

对运行时角色分配使用后处理器插件方法时要注意:每个任务状态更改可能会触发一个功能调用事件。在大量人工任务场景中,使用自定义表或自定义视图将惟一全局 ID 与 User Role Mapping 关联起来,有助于提高性能。有关自定义表的更多信息,请参阅 WebSphere Process Server 6.1: Business Process Choreographer query() and queryAll() (PDF) 的第 11 章。

结束语

本文展示了在流程模板中启用动态人工任务分配的一种解决方案。您了解了如何将流程模板与其人工任务活动关联起来,如何使用动态映射进行人工任务角色分配,如何基于包含流程模板人工活动的用户配置存储库使用 BPC API 在运行时集成人工任务。

致谢

作者想要感谢 Renxiang Chen 和 Jine Liu 为本文所做的技术评论


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=754606
ArticleTitle=使用 WebSphere BPM V6.2 动态检索和映射人工任务信息
publish-date=08292011