首页 文章 Java基础 如何设计和开发运行在 WPS 上的可重用 Human Task

邮件订阅

如何设计和开发运行在 WPS 上的可重用 Human Task E-mail
用户评价: / 0
好 
作者:Administrator   
2009-01-08 00:50

引言

WebSphere Process Server(WPS)致力于完成企业系统集成。然而在实际的应用中,会频繁使用到 Human Task 来构造复杂的工作流程。通常的实现步骤是定义 BPEL 流程,为每个 Human Task 定义接口,设计每个 Human Task 的呈现界面,处理对于每个 Human Task 的操作。但是,一旦在项目实施的工作流程中需要对工作流程进行修改,添加或者删除 Human Task,则必须重新修改或增加接口,同时为新的 Human Task 设计用户界面。这对于结构复杂,Human Task 繁多的工作流程来说,无论是设计还是维护方面都有很大的工作量。

本文从可重用的角度出发,分析了使用 WPS 实现工作流程管理的各个步骤,提出了简单易行的实现方法,使得在 WPS 上实现的 Human Task 的管理在多个层面上能够进行方便的定制,从而达到迅速的重用。该实现的主要特点包括:

  • 基于 SOA 的构造理念,实现了分解的 Service 以支持重用
  • 定义了 Human Task 的常用模式,实现了通用的 Human Task 的接口,呈现以及操作,并考虑了个性化的配置需求
  • 提供丰富的配置信息,可以快速配置各式各样的工作流程,最大程度减少了代码量(有时甚至不需要编程)
  • 把对 Human Task 的处理(Claim, Complete 等操作)和对业务对象的处理(编辑更改等操作)进行分离,从而使得 Human Task 的重用更加方便

WPS 在定义工作流程执行逻辑方面有非常丰富的功能,但在 Human Task 处理方面则需要较多的实现。因此本文中不再对工作流程的执行逻辑进行阐述,而侧重于 Human Task 的定义、操作、呈现,以及 Human Task 与业务对象的关联处理。





回页首


实现思路

在 WPS 中实现工作流程的 Human Task,需要从以下几方面入手:

  • 定义流程逻辑(BPEL)
  • 设计 Human Task 呈现界面(UI)
  • 定义 Human Task 接口(Interface)
  • 定义 Human Task 的操作,如完成任务

定义工作流程逻辑仍旧使用 BPEL 进行,本文不再赘述,而主要从其它三个方面来逐步实施可定制的可重用的 Human Task。

考虑以下工作流程场景,如图 1:


图 1:简单的工作流程场景

这可以看作是一个简单的新闻稿件的评审流程。新闻记者准备好稿件后就提交上去,评审经理对稿件进行审阅,并给出审阅结果。下面从流程参与者 (Participant) 的角度来分析 Human Task 应该具有的元素。

任务名称:即“Prepare and Submit”或“Approve”,是 Human Task 的基本元素。

任务说明:描述该任务需要做什么,如何做。对于“Prepare and Submit”任务,可以这样写:“1. 检查新闻稿完整并且内容准确;2. 确认无误后点击 完成任务 按钮提交评审。”而对于“Approve”任务,可以这样写:“1. 详细阅读提交的新闻稿;2. 在评审意见一栏里输入您的评审意见;3. 确定是否批准该稿件;4. 完成上述事项后点击 完成任务 。”

业务对象:即新闻稿。该任务页面上只显示新闻稿的链接。对新闻稿的操作如更新等则由新闻稿显示页面上的相关操作来完成。

评审意见:这是个信息显示区或者输入区。对于“Prepare and Submit”任务来说,这是个显示区域。当新闻稿被经理驳回重做的时候,新闻记者可以参考这儿显示的评审意见对新闻稿进行修改。而对于“Approve“任务来说,评审经理需要在这儿输入他对于这篇新闻稿的意见。

评审结果:仅用于“Approve”任务,决定流程的路由信息。这应该是个单选按钮 (Radio Button)。评审经理决定是否批准该新闻稿。如果批准,流程就结束;如果驳回,则流程回到前一个任务,要求对新闻稿进行修改。

任务完成按钮:参与者完成任务要求的内容后点击该按钮来确认完成,该 Human Task 就会从参与者的“To Do List”中消失。

Human Task 的用户界面实现

从以上的分析我们就可以大致规划 Human Task 的用户界面示意如图 2:


图 2:Human Task 的用户界面

其中“任务名称”,“任务说明”,“业务对象”以及“完成任务”按钮区域是必需的,而评审意见和评审结果是否显示和如何显示将取决于配置文件的定义。

下面来介绍用于定义 Human Task 页面呈现内容的配置文件。以图 1 的工作流程为例,可以有下面的配置文件:


清单 1:配置文件
    <HumanTask>
		<Type>PrepareHumanTask</Type>
                <Name>准备稿件</Name>
		<Instruction>
                1.检查新闻稿是否完整并且内容准确 ;
		2.确认无误后点击完成任务按钮提交评审。
		</Instruction>
		<Variables>
			<Variable>
                           <Name>评审意见</Name>
		           <Type>Read-Only</Type>
			   <Source>Global</Source>
			</Variable>
		</Variables>
	</HumanTask>

	<HumanTask>
		<Type>ApprovalHumanTask</Type>
                <Name>审批稿件</Name>
		<Instruction> 
                1.详细阅读提交的新闻稿;2.在评审意见一栏里输入您的评审意见;
                3.确定是否批准该稿件;4.完成上述事项后点击完成任务。
		</Instruction>
		<Variables>
			<Variable>
                           <Name>评审意见</Name>
			   <Type>Writable</Type>
			   <Source>Global</Source>
			</Variable>
		</Variables>
		<Routing>
                <Name>评审结果</Name>
			<Choice>
                            <Label>通过</Label>
			    <Value>1</Value>
                        </Choice>
			<Choice>
                            <Label>拒绝</Label>
		            <Value>2</Value>
			</Choice>
		</Routing>
	</HumanTask>

关于 <Variables> 部分, Type 表明该变量是用来显示的,还是用来输入的。而 Source 表明该变量是只隶属于当前活动,还是隶属于整个流程。Global 值表示该变量是流程的全局变量,也就是在某个活动输入的变量值其它活动可以获得。而 Local 表示该变量只隶属于特定的任务。其它活动无法获得。<Routing> 部分表示评审结果选项。

在流程运行过程中,会产生一些用户输入信息,比如上面例子中输入的评审意见,选择的评审结果等。而活动之间也有可能交换这些信息。在本实现方式中,只把路由选择信息通过任务的接口进行传递,而将其它用户输入信息使用第三方的存储如数据库进行存储和传递,这样可以保证 Human Task 接口的一致性,其数据结构 ProcessData 如下:

Element:记录是什么样的数据,是 Variables 呢还是 Routings。

Name:数据名称

ProcessID: 记录过程实例的 ID。

TaskID:记录 Human Task 实例的 ID。

Value:变量或者 Routing 的值。

举例来说,如果 Approve 任务中,评审者输入的评审意见是“Not good.”,选择的评审结果是“Redo”,则表中会插入两条记录(假定 ProcessID 是 P10080, TaskID 是 T55555)


表 1:Sample 工作流程中 Human Task 的属性
Element Name ProcessID TaskID Value
Variables 评审意见 P10080 T55555 Not good.
Routing 评审结果 P10080 T55555 Redo

呈现任务界面时,必须首先读取任务的配置信息,再根据配置信息从 ProcessData 中读取相应的数据。比如,当新闻稿被驳回要求重做时,“Prepare and Submit”会生成新的实例。编辑者打开该任务时,首先读取配置文件,知道该任务有一个只读变量“评审意见”需要显示,因为它是“Global”的,则首先取得当前流程的 ProcessID,按照 ProcessID 和变量名称“评审意见”从 ProcessData 中得到评审意见的值,并显示在页面上。

Human Task 的接口实现

既然使用了 ProcessData 来保存流程运行生成的数据,那么 Human Task 的接口就可以非常简单,输入输出只传递业务对象就可以了。究竟是传递业务对象的 ID 还是整个对象,可以视具体应用来确定。

Human Task 的操作实现

和 Human Task 的通常处理方式有些区别的是,当用户发出“完成”的指令时,系统需要根据当前 Human Task 的配置确定那些数据需要从页面上获得并保存在 ProcessData 中。以“Approve”任务为例,当发出“完成任务”指令时,从配置信息中得知,当前任务页面上有一“Writable”变量和一个“Routing”的输入信息,事件响应程序需要据此读取页面上的输入信息并且写回 ProcessData 中。

可重用的部件分析

从上面的描述可以看出,使用配置文件来定义任务的呈现界面以及控制任务完成时的操作可以大大简化工作流程的定义和实现。对所有 Human Task 都可以使用统一的呈现界面模板,任务接口以及统一的任务操作,而可以重用下面几方面的内容:

配置文件的解析部件:Human Task 的呈现,Human Task 的完成,以及流程路由的确定都需要读取配置文件的信息;

Human Task 的呈现部件:按照配置文件的定义来确定 Human Task 界面上需要显示的元素

Human Task 的完成部件:Human Task 完成时也需要根据配置文件的定义来确定那些元素需要从页面上采集,并保存在 ProcessData 中。

重用及定制步骤

依据本文的实现思路,如果需要在流程中定义新的 Human Task,按照如下的简单步骤做即可:

  • 修改 BPEL 以及装配图添加新的 HumanTask 组件
  • 修改配置文件 (XML) 为新添加的 Human Task 定义界面上的元素,界面上的输入输出以及路由选择
  • 测试流程

如果需要修改某个 Human Task 的界面显示或者路由选择,只需要修改 BPEL 以及配置文件即可。





回页首


设计

本章节描述如何设计上文提到的可重用部件。并设计一个例子来展示如何重用这些部件减少开发 Human Task 的工作量。

传统利用 WPS/WID 来设计 Human Task 时,我们要为每一个 HumanTask 设计它的接口(Interface)和呈现页面(WebPage),工作量无疑很大。本文的思想是把接口(Interface)和呈现页面(WebPage)设计成可重用部件。

接口(Interface)

操作名称 (Operation Name)

可以定义成一样的,例如 doMyTask

接口输入参数

输入参数只有一个,如表 3:


表 2:接口输入参数
Name Type
objectID String

Huma Task 通常是对一份文档进行审批或者对一份数据进行修改,我们把这些统称为业务对象。我们设计一个唯一的参数 objectID 来指向这些业务对象参数 1.cIDDks shi。

  • 如果这些业务对象是可以通过 URL 访问到,objectID 的值可以设计成指向这个文档或页面的 URL,如一份新闻稿。
  • 如果这些业务对象是存放在数据库里,objectID 的值是该业务对象在数据库中的唯一标识,如一个订单。

接口输出参数

接口输出参数定义一个 Human Task 的输出内容,也就是执行者在执行这个任务要做的事情。在业务流程里可能有多个 Human Task,如果定义的接口都能被这些 Human Task 重用,就需要把接口定义成能包容所有 Human Task 的输出。这看起来不可思议,不过幸运的是,经过分析,我们看到一个人在执行 Human Task 时会有两种类型的操作 : 流程操作和业务对象操作。

  1. 流程操作
    • 对一份文档或数据进行评价。比如审批或变更流程。
    • 对流程的路由 (Routing) 选择,比如“批准”或者“驳回”。
  2. 业务对象操作。如编辑,删除业务对象。此类操作可以点击如图 2 所示“业务对象 URL”打开操作业务对象的页面来完成。

对于 1,路由信息关系到流程的分支走向,我们把它设计成接口的输出参数;而对业务对象的评价信息(如评审意见)不作为输出参数,这个信息会在完成任务的操作中捕捉并以“Human Task 的用户界面实现”中设计的格式写到第三方存储位置。对于 2, 我们不把它放到输出参数里。

根据以上的分析,我们可以把输出参数定义成如表 4 所示的格式。


表 3:接口输出参数
Name Type
userChoice Int

userChoice: 记录参与者在 Human Task 的呈现页面上路由选择的结果,比如“重做”,“同意”。

呈现页面(WebPage)

Human Task 呈现页面部件包括以下元素:

  • 配置文件。如表 1 所示。
  • 页面模板。如图 2 所示。
  • 实现模块。这个模块从配置文件里解析出 Human Task 的呈现元素,并根据页面模板生成这个 Human Task 的实际呈现页面。

图 3 实现原理图

本章节将设计一个示例来解释如何使用上述接口和页面呈现模块来实现图 1 所示的审批流程,并通过添加一个新的 Human Task 来展现如何进行重用。

开发环境

我们使用的开发环境是 WebSphere Integration Developer V6.1.2,WebSphere Process Server 的版本是 6.1.2.0. 请首先安装开发环境。

定义统一的 Human Task 接口

统一的 Human Task 接口定义表 5 所示。


表 4. 接口定义
属性
Operation Name doMyTask
Input Name uniqueId
Input Type String
Output Name userChoice
Output type Int

启动 WID612 并且切换到 Business Integration 的视图,新建一个 Library 项目并命名为 CommonLib。在 CommonLib 下,新建一个 Interface 命名为 IGenericHumanTask. 此接口的属性如下:


图 4: WID 中定义的 HumanTask 接口

在下面的流程设计中,我们将使用这一个通用的 Human Task 接口完成新闻稿评审流程的设计。

定义统一的页面呈现模板

按照“Human Task 的用户界面实现”中的分析,我们定义 Human Task 页面呈现模板如图 5 所示。图 1 的审批流程对应的 Human Task 配置文件如表 1。


图 5 页面模板

创建流程

在 WID612 的 Business Integration 视图下,新建一个 Module 项目并命名为 ArticleProcess,同时引用刚才建立的 Commonlib 项目。在 ArticleProcess 项目中,为新闻稿评审流程建立一个接口,命名为 IApproval。属性如下所示


表 5. 示例流程的接口定义
属性
PortType Name IApproval
PortType Namespace http://ArticleProcess/IApproval
Operation Name Approve
Input Name uniqueId
Input Type String
Output Name Success
Output type Boolean


图 6: WID 中定义的流程接口定义

在 Process 节点下以 IApproval 做接口建立 ApprovalProcess,用这个 BPEL 来描述新闻稿评审流程。其中“Prepare and Submit”和“Approve”两个节点是对 Human Task 的调用。


图 7: BPEL 流程设计图

在 Assembly Diagram 下,新建两个 Human Task,分别命名为 PrepareHumanTask 和 ApprovalHumanTask 用于代表准备提交新闻稿和审批新闻稿两个 Human Task。将两个 Human Task 都以 IGenericHumanTask 做为接口。最后将 BEPL 和 Human Task 装配起来。


图 8: WID 中定义组装图

在 Human Task 的模板当中,需要添加一个自定义属性 htmType,页面将根据这个自定义属性从 XML 配置中查找该 Human Task 的详细信息用于页面展示。在演示程序里,我们以 Human Task 的模板名称做为唯一标识。


图 9: HumanTask 的属性定义

值得提醒读者注意的是,在这里恰恰体现了本文的思想。准备新闻稿和审批新闻稿是两个不同的 Human Task,按照传统的开发思想,需要我们分别对其做接口设计和 UI 编程。特别是 UI 部分,会花费很多的时间和精力,而且很容易产生 bug。下面本文将着重陈述如何重用 Human Task 的 UI。

4.5 创建 Web

我们要创建的 web 演示主要包含两个功能,一个是启动新闻稿审批流程。流程启动以后,就会为用户分配 Human Task。另外一个是显示当前用户任务的功能,你可以在这里看到所有的 Human Task,并且查看任务的详细信息。


图 10:例程的 Web 页面之主页

启动流程

流程的启动很简单,需要遵循以下步骤实现。

  • 获取业务流程管理接口实例。
  • 查询业务流程模板。
  • 获取流程业务起始活动。
  • 根据起始活动来创建业务流程实例。

下面的代码是示例如何通过以上步骤启动业务流程的。详细信息你可以查看附件中的 StartProcess.java。


清单 2:启动流程的代码
// get the reference of business flow manager
BusinessFlowManager bfm = ApiHelper.initializeBFM();
	// create where clause
	String whereClause = "PROCESS_TEMPLATE.NAME = 'ApprovalProcess'";
	// query using template
	ProcessTemplateData[] processTemplates = bfm.queryProcessTemplates(
whereClause, null, null, null);
ProcessTemplateData processTemplate = null;
if (processTemplates.length == 1) {
		processTemplate = processTemplates[0];
	}
	// Get the startActivity
	// In general you get the starting activities and based on
	// portTypeName, portTypeNamespace
	// and operation you chose the starting activity you want.
	// The sample 'ArticleProcess' has only one starting activity.
ActivityServiceTemplateData startActivity = null;
if (processTemplate != null) {
		ActivityServiceTemplateData[] startActivities = bfm
					.getStartActivities(processTemplate.getID());
				startActivity = startActivities[0];
	}
	// get the input message
ClientObjectWrapper input = null;
if (startActivity != null) {
		input = bfm.createMessage(startActivity.getServiceTemplateID(),
				startActivity.getActivityTemplateID(), startActivity
						.getInputMessageTypeName());
		// set the initial values in the input message
if (input.getObject() != null
&& input.getObject() instanceof DataObject) {
			DataObject inputMessage = (DataObject) input.getObject();
MyTrace.trace(inputMessage);
			// set the initial values in the input message
			String request = "uniqueId";
inputMessage.setString(request, "1");
		}
	// create a process instance
	PIID piid = bfm.sendMessage(startActivity
			.getServiceTemplateID(), startActivity
			.getActivityTemplateID(), input);

查询任务

流程启动以后,WPS 将会产生 Human Task 实例。此时,可以使用 Human Task API 对任务进行查找。要查找 Human Task 请遵循以下逻辑:

  • 获取 Human Task 管理接口。
  • 使用 query 方法按条件进行查询。在示例中,我们需要查找处于 ready 状态的 Human Task。

下面的代码片断示例了如何根据以下逻辑实现 Human Task 的检索,详细信息可以查看附件的 ListMyWork.java 和 ListMyWork.jsp。


清单 3:查询任务的代码
HumanTaskManager htm = ApiHelper.initializeHTM();
	String selectClause = " DISTINCT TASK.TKIID ";
String whereClause = null;
	// retrieve the activities of the ApprovalProcess
	// that are in state ready and for which the current user is a
	// potential owner
	// in order to work on (claim) it
	whereClause = // " PROCESS_TEMPLATE.NAME = 'ApprovalProcess' "
	  " TASK.KIND IN ( TASK.KIND.KIND_HUMAN, TASK.KIND.KIND_PARTICIPATING )"
		+ " AND TASK.STATE = TASK.STATE.STATE_READY"
	        + " AND WORK_ITEM.REASON = WORK_ITEM.REASON.REASON_POTENTIAL_OWNER";
	        QueryResultSet result = htm.query(selectClause, whereClause,
(String) null, (Integer) null, (TimeZone) null);
tasks = new ArrayList();
while (result.next()) {
TKIID tkiid = (TKIID) result.getOID(1);
Task task = htm.getTask(tkiid);
		//do your logic
	}

经过查询以后的 Human Task,就可以以列表的形式列在页面上了。如下图所示:


图 11:例程的 Web 页面之任务列表

动态显示

按照本文的思想,当用户点击任务 ID 时,处理逻辑如下所示:

  • 根据任务 ID 查找 Human Task 的自定义属性 htmType。
  • 由 htmType 从 XML 获取用户所定义的 Human Task 的详细信息。
  • 将详细信息交给页面逻辑动态显示。

在新闻稿的审批流程当中,准备稿件和审批稿件是两个不同的 Human Task。准备稿件流程只需要用户进行查看以后填写备注提交即可,而审批流程则需要用户做一个选择,然后填写备注。所以,页面上应该有这样的逻辑进行区分。


图 12:例程的 Web 页面之“准备稿件”任务说明和处理页面


图 13:例程的 Web 页面之“审批稿件”任务说明和处理页面

上图中展示了准备稿件页面和审批页面,当用户由任务列表页面进入些页面时,我们取得了它的唯一 ID 并通过 Human Task 管理接口(HumanTaskManager)该任务的 htmType 值,并且根据这个值与 XML 中的值时行匹配。而在 XML 文件中,我们已经定义了该 Human Task 的显示元素。对于提交新闻稿任务,页面将展现任务名称、任务说明、业务对象和备注,而对于审批任务,页面还将呈现操作选择元素。

我们的示例代码中,HumanTaskXMLConfigLoader 负责根据 htmType 来解析查找用户所定义任务的详细信息,ShowWork.java 和 ShowWork.jsp 则负责根据查找的结果动态展现的逻辑。

当然,我们这里仅仅是一个简单的示例,它主要用于说明我们的重用思想。当你的 XML 中定义更多页面元素时,页面的处理也会相应多一些。但是,由于需求发生变更时,或者由于有新的 Human Task 添加到 BPEL 流程中时,所有的这一切都可以被后加入的新任务重用,从而使页面元素得到高度重用,甚至有可能不用再添加一行 UI 方面的代码。让你从繁杂的 UI 开发中解脱出来。

下面一节将阐述如何添加一个新的 Human Task 而不添加 UI 代码。

添加一个新任务

在图 1 的审批流程上,我们添加一个“Publish”Human Task(新闻稿审批之后的发布),如图 14 所示:


图 14 完整的例子

我们要做的是:

  • 利用与 Human Task “Prepare and Submit”,“Approve”相同的接口和页面模板。
  • 在 WID 上的 Process 画布添加新的 Human Task 节点及更新组装图。
  • 定义对应这个任务的配置如下

清单 4:“Publish”的配置
	<HumanTask>
		<Type>publishHumanTask</Type>
		<Name>发布稿件</Name>
		<Instruction>
			1.将审批通过的稿件按指定格式和位置发布在网站
		</Instruction>
		<Variables>
			<Variable>
				<Name>评审意见</Name>
				<Type>Read-Only</Type>
				<Source>Global</Source>
			</Variable>
		</Variables>
	</HumanTask>

下面将介绍在 WID 中,如何利用本系统快速的添加一个 Human Task。如下操作都是在 WID 的 Business Integration perspective 下面。

步骤 1:添加一个 HumanTask,名字为 PublishHumanTask,选择 IGenericHumanTask 为其接口;

步骤 2:为这个 HumanTask 的 Environment 添加属性 htmType,值为 publishHumanTask;

步骤 3:在 Process 画布中 Approve 节点后面添加 Invoke 节点名字为 Publish,为其 Partner 新增 Reference 名字为 IGenericHumanTask2。


图 15:新增 Publish 节点之后的 ApprovalProcess

步骤 4:在 Assembly Diagram 中,拖入 PublishHumanTask,并将 ApprovalProcess 的 IGenericHumanTask2 的 reference 连接到 PublishHumanTask。


图 16:在 Assembly Diagram 中连接 ApprovalProcess 和 PublishHumanTask

经过如上的步骤,新的 HumanTask 就已经成功添加到原有流程。在新的流程中,当 Approve 通过之后就进入了新增的“发布”任务。


图 17:新的流程中“发布”任务的用户界面

在此处点击“完成任务”,整个流程处理结束。





回页首


总结

本文提出了解决 WPS 中 Human Task 开发负担较重这个问题的解决思路,同时结合一个具体的工作流程给出了设计和实现的细节,SOA 流程管理项目中的架构师和开发人员可以参考本文的实现设计自己的可重用框架。整个示例代码作为附件提供,读者可以下载并且导入到 WID 中运行。





回页首


免责声明

为提供参考之目的,本文提供了解决方案、相关设计并在附件中提供有样本代码。如上内容是以“按现状”的基础提供的,没有任何形式的(不论是明示的 , 还是默示的)保证,包括但不限于对适销性、适用于特定用途的默示保证。IBM 及其许可方不对您使用该方案、设计及样本代码所导致的任何结果承担责任。






回页首


下载

描述名字大小下载方法
示例文件 1InitialProject.zip6336KBHTTP
示例文件 2ProjectWithPublishNode.zip6338KBHTTP
说明文件Readme.txt1KBHTTP
关于下载方法的信息


最后更新于: 2009-01-08 00:50
 

欢迎转载

本站文章欢迎转载,但请注明出处(http://www.javajia.com,Java家)

其他相关文章