在 WebSphere Process Server 中为新的查询要求设置自定义属性

Xiang Cheng, 软件工程师, IBM
 
Zhu Liang, 软件工程师, IBM
 
Pei Jian Dong, 软件工程师, IBM
 

简介: 在您开发一个业务流程客户端程序时,您经常需要在一个流程实例内,通过某些业务数据标准来查询流程实例、活动和任务。本文向您展示了在 WebSphere Process Server 中,如何通过一个动态方法为流程实例设置自定义属性来满足新查询要求。

简介

在您开发一个业务流程客户端程序时,您经常需要在一个流程实例内,通过某些业务数据标准来查询流程实例、活动和任务。例如,您可能想要在流程实例中寻找与某个 ID 的客户相关的所有任务。

当您在 WebSphere Integration Developer(以下简称为 Integration Developer)设计流程时,可以通过为人工任务设置自定义属性来实现这个需求。然而,当流程投入使用后,如果新查询要求需要新的自定义属性,那么这招就不灵了。您当然可以使用 WebSphere Process Server(以下简称为 Process Server)提供的流程版本控制方法,在新版业务流程中增加新的自定义属性。然而,使用新的自定义属性不能对已有的旧版业务流程进行查询。

本文对熟悉业务流程开发的业务流程设计师和程序员有一定的帮助。本文假设您熟悉 Process Server 和用 Integration Developer 开发业务流程应用程序。如果您没有经验,我们建议您仔细阅读 Business Process Management 样例 & 教程 — 版本 6.1

在本文中,我们假设 Integration Developer V6.1.2 已得到合理安装。在本文 参考资料 部分,查看更多信息。

本文介绍一种动态的方法,该方法使用 Business Process Choreographer(BPC) EJB API 来为正在运行的业务流程实例设置自定义属性,从而解决此类问题。

我们将利用一个简单的命令审计流程来说明这个解决方案。样例流程工作流包括以下典型步骤:

  • 客户提交一个订单请求,其中含有用户和审计人员的信息。
  • 审计人员批准或拒绝请求。
  • 最后,当审计人员批准或拒绝请求后,系统给客户一个响应。

样例和模块将在以下几节描述。

使用准备好的业务流程按如下方式导入项目交换文件:

  1. 下载提供的 OrderDemo.zip 文件,并将其保存到一个临时目录中。
  2. 在 WebSphere Integration Developer 中,单击 File -> Import。Import 对话框打开。
  3. 选择 Project Interchange。
  4. 单击 Next。Import Project Interchange Contents 窗口打开(如图 1 所示)。

    图 1. Import 对话框
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

  5. 单击 “From zip file” 旁边的 Browse
  6. 浏览临时目录,选择第 1 步中下载的压缩文件。
  7. 单击 Open
  8. 选择您的工作空间目录作为您的 Project location root
  9. 单击 Select All
  10. 单击 Finish

您需要使用与上面相似的步骤,将提供的包含流程数据类型的 OrderDemoLib.zip 导入工作空间。您将得到如图 2 所示的项目结构。以下部分将对此做详细解释。


图 2. 流程项目结构
在 WebSphere Process Server 中为新的查询要求设置自定义属性

业务对象和 BPEL 流程

订单审计流程有两个必需的业务对象(BO):OrderRequestPersonInfo(见图 3)。OrderRequest 保存订单信息,包括客户、审计人员、状态和商品编号。PersonInfo 包含个人信息,比如 ID、姓名和地址。


图 3. 业务对象
在 WebSphere Process Server 中为新的查询要求设置自定义属性

图 4 展示了 Integration Developer BPEL 中设计的流程:

  1. Receive 活动是流程的起始点。流程从客户端收到一个消息(OrderRequest),接着开始流程。消息中的数据存储在一个流程变量(请求)中。
  2. Assign 活动执行该流程所需的数据映射。
  3. Order Info 片段打印订单信息。
  4. ApproveOrderRequest 是审计人员批准或拒绝请求的一个人工任务。
  5. Approve 选项根据审计人员的决议决定下一步。系统将使用 Approve ResponseReject Response 片段打印相应的回复。

    图 4. 流程
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

使用 BPC Explorer 运行样例

在嵌入 Integration Developer 的测试服务器上部署了 OrderDemoApp 之后,使用 Business Process Choreographer (BPC) Explorer 运行样例,步骤如下:

  1. 在 “My Process Templates” 页面(见图 5)上选择 OrderProcess,然后单击 Start Instance

    图 5. 流程模板
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

  2. 填写 Process Input Message 部分并单击 Submit (见图 6)。

    图 6. Process Input Message
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

  3. My To-dos 页面(见图 7)上处理 ApproveOrderRequest 人工任务工作。

    图 7. My To-dos
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

  4. 输入 Task Output Message(true 表示批准,false 表示拒绝)。单击 Complete(见图 8)。

    图 8. 处理 Task Message
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

  5. 在控制台上(见图 9),您可以看到测试结果(日志以 Java™ 片段打印)。

    图 9. 控制台
    在 WebSphere Process Server 中为新的查询要求设置自定义属性

一般来说,您需要开发一个客户端应用程序来启动和完成流程实例,而不是使用 BPC Explorer。WebSphere Process Server V6 提供 BPC EJB API 来访问和处理业务流程和人工任务。事实上,有两个独立的 API 集合:Business Flow Manager API 和 Human Task Manager API。

当我们建立流程客户端应用程序时,常常希望定位一个特定的流程实例或人工任务,其业务数据满足某个标准。例如,可能需要通过特定的订单号寻找流程实例。

这部分说明了为什么您需要为查询要求设置自定义属性。查询出任务之前,您需要启动流程实例。

您可以使用与导入流程项目的类似的步骤,将提供的 OrderProcessExport.zip 导入您的工作空间。该项目的所有代码片段在本项目后面部分都能找到。

清单 1 显示了这些使用 Business Flow Manager API 来启动一个带有输入消息的 “OrderProcess” 实例的代码片段。


清单 1. 使用 BPC EJB API 启动流程
				
// Create the input ClientObjectWrapper
com.ibm.bpe.api.ClientObjectWrapper cow = flows.createMessage(
		processTemplate.getID(), processTemplate.getInputMessageTypeName());
// Get the Input DataObject from the ClientObjectWrapper
DataObject dataObject = (DataObject) cow.getObject();
	
dataObject.setDataObject("request", OrderRequest);
//Initiate process instance
com.ibm.bpe.api.PIID piid = flows.initiate("OrderProcess", cow);

流程实例启动后,名为 “ApproveOrderRequest” 的人工任务将被启动,等待审计人员完成。完成任务之前,您需要通过订单号查询出任务。清单 2 显示了使用 Human Task Manager 通过订单号过滤任务的代码片段 。


清单 2. 通过订单号获取特定待处理任务
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", 				
 "TASK.NAME='OrderProcess$ApproveOrderRequestTask' AND 
TASK.STATE=TASK.STATE.STATE_READY", null, null, null, null);

while (instances != null && instances.next()) {
	TKIID tkiid = (TKIID) instances.getOID(1);

	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();

	if (orderNo.equals(input.getString("orderNo"))) {
		System.out.println("find!!!");
	}
}

您可以在预定义的 BPC 数据库视图上执行 SQL 查询。然而,像在输入消息(业务对象)中定义的订单号这类业务数据,在数据库视图中不能查询。您不得不通过流程的输入消息从所有待处理任务中过滤。如果审计人员有很多待处理任务,这个方法将可能导致性能问题。您也需要改进查询方法和自定义属性来满足您的需求。您可以指定业务流程自定义属性及其所有的基本活动。一个自定义属性有一个名称和一个可选值(字符串)。BPC 数 据 库 提 供一个 PROCESS_ATTRIBUTE 视图,您可以使用该视图查询流程人工任务,方法是将订单号定义为流程自定义属性。

除了性能问题之外,还有另一个重要的原因:如果在流程的输入消息中不包含查询标准,您就不能用输入消息过滤实例。然而您可以用 BPC EJB API 设置标准作为自定义属性来满足这类需求 。

根据自定义属性执行查询之前,您需要为流程实例设置自定义属性。

当启动流程实例时,您可以使用 BPEL 流程中的一个 Java 片段或 BPC EJB API 来设置自定义属性。下面将分别介绍这两种方法。

在 Integration Developer 中使用 Java 片 段设置自定义属性

您可以在流程的开始增加一个 Java 片段。输入以下设置语句,如图 10 所示:

setProcessCustomProperty(“orderNo”, orderNo);


图 10. 使用 Java 片段设置流程自定义属性
在 WebSphere Process Server 中为新的查询要求设置自定义属性

使用 BPC EJB API 设置自定义属性

流程实例启动之后,您也可以使用 BPC EJB API 将订单号设置为自定义属性,如清单 3 所示。


清单 3. 使用 BPC EJB API 设置自定义属性
				
String rderNo = request.getString("orderNo");
if (orderNo != null && !"".equals(orderNo)) {
	bfms.setCustomProperty(piid, "orderNo", orderNo);
}

流程启动之后,您可以在 BPC Explorer 中查看自定义属性,如图 11所示。


图 11. 检查现有流程实例属性
在 WebSphere Process Server 中为新的查询要求设置自定义属性

您可以使用预定义的数据库视图 PROCESS_ATTRIBUTE 查询自定义属性,如表 1 所示。


表 1. PROCESS_ATTRIBUT 视图
列名 类型 注释
PIID ID 含有一个自定义属性的流程实例的 ID。
NAME String 自定义属性的名称。
VALUE String 自定义属性值。

清单 4 显示了如何通过自定义属性查询待处理任务。


清单 4. 通过自定义属性查询待处理任务
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", 
 "WORK_ITEM.OBJECT_ID = TASK.TKIID AND WORK_ITEM.ASSOC_OID = PROCESS_ATTRIBUTE.PIID AND  
 PROCESS_ATTRIBUTE.NAME= 'orderNo' AND PROCESS_ATTRIBUTE.VALUE ='" + orderNo + "' AND 
 (TASK.STATE = TASK.STATE.STATE_READY OR TASK.STATE = TASK.STATE.STATE_CLAIMED ) AND 
 TASK.SUSPENDED = FALSE AND WORK_ITEM.REASON=1 AND WORK_ITEM.OBJECT_TYPE=5 ", 
 null, null, null, null);
			 
if (instances.size() > 0) {
	instances.first();
	TKIID tkiid = (TKIID) instances.getOID(1);
	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();
	
}

您可以使用查询、通过自定义属性直接获取订单号的任务 ID。这将会产生较好的性能。

如果在业务流程运行之后,出现一个新的查询要求,此时,您该做什么?例如,您想要根据 customerId 而非 orderNo 查询流程实例。您需要添加一个新的名为 “customerId” 的自定义属性来支持新的查询要求。如您所知,样例流程是一个长期流程,就是说,可能有多个实例运行在生产服务器上。这意味着您需要添加新的自定义属性, 不仅要为新启动的流程实例添加,也要为服务器上已存的实例添加。

为新启动的流程实例设置新自定义属性

有两种方法来实现这个要求。您可以实现一个新版业务流程,在 Java 片段中添加新的自定义属性。对于版本控制方法,参见 Versioning business processes and human tasks in WebSphere Process Server。另一种方法是,为新启动的流程实例添加新的自定义属性 customerId。对于第二种方法,您不需要进行流程版本控制。

从这个角度来看,使用 BPC EBJ API 比在 BPEL 流程中设置自定义属性要好一些。有了 API,您可以根据需求变化动态地添加新的客户属性,而不需要对 BPEL 流程进行版本控制。清单 5 显示了如何使用 BPC EJB API 设置一个新的自定义属性。


清单 5. 为新启动的实例设置自定义属性
				
//Initiate the process instance as usual
com.ibm.bpe.api.PIID piid = flows.initiate("orderProcess", cow);
//Set custom property after process instance is initiated.
flows.setCustomProperty(piid, "orderNo",“000001”);
flows.setCustomProperty(piid, "customerId",“C00001”);

现在,您可以根据新的自定义属性 customerId 来查询待处理任务,从而满足新的需求。

为运行中的流程实例设置新自定义属性

通过使用 BPC EJB API,您可以搜索运行中的流程实例,并为其添加一个新自定义属性。清单 6 显示了如何为运行中的实例添加一个新自定义属性。


清单 6. 为运行中的实例设置自定义属性
				
QueryResultSet instances = flows.query("DISTINCT PROCESS_INSTANCE.PIID", 
 "PROCESS_INSTANCE.STATE = 2  AND PROCESS_INSTANCE.TEMPLATE_NAME
  ='OrderProcess' ", "", null, null);

while (instances .next())
{
	PIID piid = (PIID) result.getOID(1);
	flows.setCustomProperty(piid, "customerId", customerIdValue);
		 
}

根据自定义属性查询待处理任务

就像根据 orderNo 查询待处理任务那样,现在,您可以根据 customerId (见清单 7)执行查询。


清单 7. 根据新的自定义属性查询待处理任务
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", "WORK_ITEM.OBJECT_ID 
 = TASK.TKIID AND WORK_ITEM.ASSOC_OID = PROCESS_ATTRIBUTE.PIID AND 
 PROCESS_ATTRIBUTE.NAME= 'customerId' AND PROCESS_ATTRIBUTE.VALUE ='" + customerId 
 + "' AND (TASK.STATE = TASK.STATE.STATE_READY OR TASK.STATE = TASK.STATE.STATE_CLAIMED ) 
 AND TASK.SUSPENDED = FALSE AND WORK_ITEM.REASON=1 AND WORK_ITEM.OBJECT_TYPE=5 ", null, 
 null, null, null);
if (instances.size() > 0) {
	instances.first();
	TKIID tkiid = (TKIID) instances.getOID(1);
	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();
	System.out.println("find customerId:" + customerId	+ " orderNo: 
     " + input.getString("orderNo"));
}

您可以测试 OrderProcessExport 项目,这是一个实现了流程实例的启动和查询的 Java 客户端应用程序。将两个模块 OrderDemoOrderProcessExport 部署到 Integration Developer 中的测试服务器之后,您可以在 Integration Developer中使用测试模块测试该项功能。


图 12. 在 Integration Developer 中测试客户端应用程序
在 WebSphere Process Server 中为新的查询要求设置自定义属性

您可以参考函数描述(表 2)来执行测试。


表 2. PROCESS_ATTRIBUTE 视图
方法名 功能
initProcess 启动一个新的流程实例。
initProcessWithOrderNo 启动一个新的流程实例并为该实例设置自定义属性 orderNo。
initProcessWithCustomerId 启动一个新流程实例,并为该实例设置自定义属性 customerId。
queryTodoTaskByOrderNo 根据请求的 orderNo 查询特定待处理任务。
queryTodoTaskByCustom
PropertyWithOrderNo
根据自定义属性 orderNo 查询特定待处理任务。
queryTodoTaskByCustom
PropertyWithCustomerId
根据自定义属性 cusomerId 查询特定待处理任务。
addCustomPropertyFor
RunningProcess
为运行中的流程实例添加新的自定义属性。

基于业务流程的应用程序包括长期实例,这种实例可以运行几周、几月、甚至几年。业务需求随时间而变化。WebSphere Process Server V6.1 提供一个称为 “流程版本控制” 的技术,来帮助升级基于业务流程的应用程序,以满足新环境和业务需求。然而,您还需要修改已有的实例来满足新的查询要求。本文介绍了一种动态方法,它使用 Business Process Choreographer EJB API 来为新流程实例和运行中的实例设置自定义属性,从而满足新的查询要求。使用这种方法,您不需要更新流程来添加一个新的自定义属性。

原文链接:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1006_cheng/1006_cheng.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14789789/viewspace-671385/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14789789/viewspace-671385/