使用 WebSphere Process Server 实现业务状态机和人工任务之间的双向交互

人工交互或干预通常是业务过程中不可或缺的一部分。例如,订单金额超过一定数额时需要经过经理的批准才能发送。WebSphere Process Server Version 6.0.1 专门针对此类情形提供了人工任务。人工任务是允许基于服务的应用程序与人进行交互的组件。在设计上,人工任务公开一个双向接口,这使得在使用 Process Server 中的业务状态机时很难直接调用这些人工任务。在本文中,我们将讨论如何结合使用业务状态机和人工任务,使用的示例是作为业务状态机实现的简化订单流程,其中需要人工审批步骤。

Geoffrey A. Beers (beersga@yahoo.com), 软件工程师, IBM 

Geoffrey Beers 是在明尼苏达州罗彻斯特市工作的IBM 软件工程师。他属于罗彻斯特 Bringup 实验室的 SWAT 团队,从事 WebSphere Process Server 的工作。您可以通过 beersga@yahoo.com 与 Geoffrey 联系。



James Carey (jecarey@us.ibm.com), 高级软件工程师, IBM 

James Carey 目前是 IBM 的系统和技术团队的高级软件工程师。James 以前是 WebSphere Process Server 体系结构小组的成员,专门研究业务状态机这一领域。



2006 年 9 月 27 日

引言

本文讨论如何在 IBM® WebSphere ®Process Server Version 6.0.1(以下称为 Process Server)中使用人工任务组件来控制业务状态机中的业务流。状态机等待操作从一个状态转换到另一个状态。这些操作可以由用户输入驱动或者由其他服务组件体系结构(Service Component Architecture,SCA)组件驱动。在本示例中,我们使用状态机实现一个简化订单流程。订单松散地基于内部订单流程,例如从中央供应部获取办公用品。实际的传统订单处理情形是在订单流程的某个环节中涉及人工干预。我们通过设定以下情形来模拟这种交互,即对于超过 100 美元的订单需要人工审批(非常类似于由经理审批)。在此情况下,我们可以很容易地得到一个红色订书机,但是要得到一台传真机则需要经过批准才行。

在订单流程中,我们使用人工任务向经理呈递请求,经理然后分析订单,并返回批准或不批准订单的决定。下面显示的图 1 是我们需要关注的订单状态机的简要表示。

图 1. 状态机的简要表示形式图 1. 状态机的简要表示形式

图中显示的第一个状态是 Building Order。这类似于使用购物车购物,可以根据需要增加或减少物品。在订单上填写要购买的所有物品之后,可以使用 order 操作将订单移动到该过程的下一个步骤。Building Order 状态有共有两种转换形式。一种形式是订单总额小于或等于 100 美元,另一种形式是订单总额大于 100 美元。当订单总额小于或等于 100 美元时,不需要经过特殊的审批,可以直接发送订单。另一方面,如果金额大于 100 美元,则订单必须经过经理批准(通过人工任务)。在处理人工任务时,经理或者批准订单或者不批准订单。如果经理批准,则可以发送订单。如果经理不批准,则订单返回 Building Order 状态,以便去掉一件或多件物品,然后重新提交订单。


设计订单流程

从设计和实践的角度来看,需要确定的第一件事是业务状态机与人工任务如何进行交互。在处理人工任务后,业务状态机需要根据人工任务的响应将人工任务作为处理操作和转换的一部分来启动。目前,业务状态机可以直接启动人工任务的唯一方法是通过双向接口;但是,使用该接口会导致业务状态机需要等待人工任务完成后才能启动它。这是无法接受的,因为业务状态机需要不停地处理操作。这意味着业务状态机始终处于两种状态之间,因此无法接受诸如请求取消订单之类的其他操作。

因此,为避免此问题,需要使用单向操作启动人工任务。这样,业务状态机便可以在它的某个操作过程中启动人工任务,然后通过回调处理来自人工任务的 approval 决定。

因此,要使我们的用例正常工作,我们需要有:

  • 一个获取必要审批的人工任务。
  • 一种在人工任务完成之后回调业务状态机的机制。

业务流程执行语言(Business Process Execution Language,BPEL)过程能够调用人工任务和其他组件,因此我们可以使用 BPEL 过程作为人工任务的包装程序。

因此,从业务状态机调用人工任务的设计模式如下所示:

  1. 业务状态机调用 BPEL 过程,该过程包括一个内嵌的人工任务活动(为什么需要将人工任务活动内嵌到该过程中将在下文讨论)。
  2. 在经理批准或拒绝订单之后,BPEL 过程将通过调用业务状态机上的一个操作把人工任务的结果返回到业务状态机。这相当于一个回调机制,它在我们从业务状态机直接调用人工任务的设计方法中是没有的。因此,业务状态机实际上是调用一个长时间运行的 BPEL 过程,而该过程进而调用人工任务。
  3. 在人工任务完成之后,BPEL 过程将调用业务状态机,并且状态机逻辑将继续执行。下面的图 2 显示了此设计模式的装配图。

图 2. 人工任务调用的装配图图 2. 人工任务调用的装配图

注意,应将客户端操作和回调操作分别安排在不同的接口上。在我们的 BSMOrder 示例中有两个接口:BSMOrderInterfaceBSMOrderCallbackInterfaceBSMOrderCallbackInterface 提供 BPEL 过程的回调操作,BSMOrderInterface 提供业务状态机的客户端接口。


设计业务状态机

业务状态机的设计基于订单的各个状态和这些状态之间的转换。图 3 显示了 BSMOrder 业务状态机的设计。

图 3. BSMOrder 业务状态机图 3. BSMOrder 业务状态机

BSMOrder 业务状态机:当对 BSMOrder 业务状态机调用 create 操作(由齿轮图标标识)时将创建该状态机的实例。在本例中,我们仅传递了 orderId 和一个 totalAmount 就创建了业务状态机实例。实际应用程序需要的信息要多得多,例如构成订单的各个订单行。

Building Order 状态:在创建业务状态机之后,将进入 Building Order 状态。在该状态中,我们可以更新订单(使用 updateOrder 操作),也可以下订单(通过 order 操作)。

updateOrder 操作允许更改订单的总金额。在实际的应用程序中,此操作应支持更复杂的修改,其中包括添加或删除订单中的订单行。

order 操作用于下订单,并可以根据业务状态机逻辑中定义的条件(由钻石图标标识)采取两种转换之一,如图 4 所示。

图 4. 状态机条件转换图 4. 状态机条件转换

Approved 状态:如果订单总额小于或等于 100 美元,则不需要经理审批订单,业务状态机将转换到 Approved 状态,在该状态中将等待发送订单。不过,如果订单总额大于 100 美元,则需要通过人工任务由经理审批。

这可以通过对 order 操作产生的转换定义条件来实现。这些条件可以使用返回布尔值的 Java™ 代码片段来定义。对于 Approval Needed? Yes 条件,Java 代码为:

return totalAmount.compareTo( new Float( 100.00f )) > 0;

我们对 Approval Needed? No 条件使用相同的代码片段,不过,在这里使用了将结果取反的选项。在实际的应用程序中,这些条件要复杂得多,并且可能需要在应用程序运行过程中进行更改。例如,在需要审批时能够更改作为审批依据的金额。对于某个条件,业务状态机可以调用另一组件来执行条件检查。该组件可以是 Process Server 的 Business Rule,它允许在应用程序运行期间更改值(如我们的示例中的 100 美元)。

Awaiting Approval 状态:在需要经理审批时,Request Approval 操作(由风车图标标识)将调用 OrderApproval BPEL 过程。由于此过程是异步调用的,业务状态机将转换到 Awaiting Approval 状态,在该状态中将等待经理批准或不批准订单。在处理后,OrderApproval 实例对于审批结果将调用业务状态机的 approvalResponse 操作,然后结束进程。如果经理批准订单,则业务状态机将转换到 Approved 状态并等待发送。"Approve" 条件的 Java 代码是:

return ( approvalResponse_Input_approvalResponse.equals("approve") );

变量 approvalResponse_Input_approvalResponse 包含 approvalResponse 操作中传入的审批响应值。它由业务状态机从操作中填入,并用于与该操作相关的条件和操作。

另一方面,如果订单未被批准 ("disapprove"),则订单会被返回到 Building Order 状态,用户可以在该状态更改订单金额。用于 "Disapprove" 条件的 Java 代码稍微复杂一些:

String response = approvalResponse_Input_approvalResponse;
return response.equals("disapprove") || !response.equals("approve");

还要对其值不是 "Approve" 的响应执行其他检查,对于任何不是 "Approve" 的响应都假定为 "Disapprove"。现在,业务状态机返回到 Building Order 状态,在这里可以更改订单金额(使用 updateOrder),然后重新尝试订单操作。如果订单仍然大于 100 美元,对 order 操作的新调用将创建一个新的 OrderApproval 实例,再次请求经理审批。


使用内嵌 ApproveOrderTask 设计 OrderApproval

上文已经讨论过,如果订单金额大于 100 美元,业务状态机中的 Request Approval 操作将异步调用 BSMOrderApproval。此过程比较简单。它从业务状态机接收 orderId,并立即调用内嵌 ApproveOrderTask 人工任务活动。由于定义了人工任务,因此 BSMOrderApproval 必须是一个长时间运行的过程。

现在可以请求 ApproveOrderTask 并继续工作。在任务完成之后,结果值将在 approvalResponse 变量中定义。在我们的示例中,人工任务没有使用安全性,并允许任何人请求或执行任务。在实际情形中,显然会对请求和审批订单施加非常严格的限制。经理或者批准订单或者不批准订单。BPEL 过程将立即接受该响应,并将其转发到业务状态机上的回调操作 approvalResponse。BPEL 过程在将订单 ID 调回业务状态机时使用所传递的 orderId。此 orderId(关联信息)可以确保回调与启动 ApproveOrder 任务相同的业务状态机。在该回调完成之后,BSMOrderApproval 结束。图 5 显示了订单审批过程。

图 5. 订单审批过程图 5. 订单审批过程


要求审批的运行示例

在创建两个组件并将它们连接起来后,让我们看一看订单业务状态机和 BPEL 审批过程(带有内嵌人工任务)的运行示例。在我们的示例中,我们使用 Business Process Choreographer (BPC) Explorer 创建和使用业务状态机,并与人工任务一起使用。

  1. 创建订单。使用与业务状态机关联的模板通过指定 orderId 和订单金额创建一个订单。orderId 用于进行关联。注意,我们指定的金额是 150 美元,这意味着需要经理的审批。

    图 6. 创建订单实例图 6. 创建订单实例

  2. 对 BSM 实例调用订单操作(事件)。注意,我们使用的 orderId 必须与创建此过程时所使用的订单 ID 相同,因为这在进行关联时很有用。

    图 7. 使用订单 ID 进行状态之间的关联图 7. 使用订单 ID 进行状态之间的关联

    由于订单金额大于 100 美元,因此为我们创建了 BSMOrderApproval 过程的实例以及 ApproveOrderTask。在创建 BSMOrderApproval 过程时我们传递了 orderId。在回调到业务状态机时,orderId 将用作参数,这样回调将指向正确的 BSM 实例。

    我们假设一个经理角色并使用 BPC Explorer 来处理审批任务,还决定不批准订单。

    图 8. 不批准订单的人工任务图 8. 不批准订单的人工任务

    这会导致调用 approvalResponse 操作和审批响应值 "disapprove"(以及用于关联的 orderId)。将检查由 approvalResponse 操作导致的转换的不同条件,"Disapprove" 条件的计算结果为 True,因此业务状态机将转换回 Building Order 状态。

  3. 注意,现在已不再运行 BSMOrderApproval 过程和 ApproveOrderTask。但是,我们的订单业务状态机仍处于活动状态并在运行,目前正在 Building Order 状态中等待。

  4. 通过调用 updateOrder 操作更改订单。输入 orderIdnewAmount。尝试将金额降低到 125 美元,以便这次能够批准订单。

    图 9. 输入新的订单金额图 9. 输入新的订单金额

  5. 因为 updateOrder 是自转换操作,所以我们仍然处于 Building Order 状态。我们需要像上文使用正确的 orderId 一样再次调用订单操作。

  6. 批准订单。我们的订单金额仍大于 100 美元,因此需要再次提请经理批准。这样,将为我们创建一个新的 BSMOrderApproval 过程和一个新的 ApproveOrderTask。希望他们这次能批准我们的订单。

  7. 我们还假设经理角色,但这次他们批准了订单。

    图 10. 批准订单图 10. 批准订单

    这会导致调用业务状态机上具有 approve 值的 approvalResponse 操作。将再次检查能够由此操作导致的所有转换条件,但这次接受与 Approve 条件关联的转换。

  8. 金额为 125 美元的订单这次被批准。BSMOrderApproval 实例不再运行,并且我们的业务状态机处于 Approved 状态。

  9. 发送订单。最后,发送订单并且业务状态机处于结束状态。

您会注意到,在我们的示例中有些内容被标记为“log xxx”。这些内容包含使用 System.out.println 编写进度信息的 Java™ 代码片段。下面是我们刚才描述的情形的控制台输出,其中显示了下列内容的输出:

BSMOrder(3536) Created
BSMOrder(3536) State is Building Order: Amount = 150.0
BSMOrder(3536) State is Awaiting Approval
BSMOrderApproval(3536): Start Task
BSMOrderApproval(3536): Task Finished.  
                Approval Response is disapprove
BSMOrder(3536) Disapproved
BSMOrder(3536) State is Building Order: Amount = 150.0
BSMOrder(3536) State is Building Order: Amount = 125.0
BSMOrder(3536) State is Awaiting Approval
BSMOrderApproval(3536): Start Task
BSMOrderApproval(3536): Task Finished.  
                Approval Response is approve
BSMOrder(3536) Approved
BSMOrder(3536) State is Approved
BSMOrder(3536) State is Shipped

取消 OrderApprovalProcess

另一个需要支持的方面是订单取消。订单可以由经理取消(通过人工任务),也可以直接取消。这就产生了困难,因为我们的解决方案运行了两个过程实例,所以需要在这两者之间协调取消操作。我们当前的设计不支持订单取消,因此必须首先向业务状态机添加一个 Canceled 状态。

经理通过人工任务取消订单的情形比较简单。现在必须处理 cancel 的审批响应,因此添加一个从 Awaiting Approval 状态到 Canceled 状态的转换和一个在审批响应为“cancel”时的检查条件。这类似于上文描述的“approve”条件。我们还必须修改不批准的条件,这样,Java 代码片段现在变成:

String response = approvalResponse_Input_approvalResponse;
return ( response.equals("disapprove" ) || ( !response.equals("approve") && !response.equals("cancel")));

另一方面,直接取消订单的情形更为复杂一些。我们不能简单地添加一个从 Awaiting Approval 状态到由取消操作驱动的 Canceled 状态的转换。如果这样做,将不会排除人工任务,并且当 OrderApproval 过程处理来自人工任务的响应时将会遇到异常,该过程尝试执行到业务状态机的回调操作,但该状态机已不复存在。为解决此问题,我们需要向此转换添加一个操作 (Cancel Approval) 来取消人工任务。图 11 显示了更新的业务状态机:

图 11. 修改后支持取消操作的业务状态机图 11. 修改后支持取消操作的业务状态机

该操作如何取消人工任务?如图 12 所示,通过向 BSMOrderApproval 过程添加能够终止此过程的事件处理程序可以做到这一点。

图 12. BSMOrderApproval 中的事件处理程序图 12. BSMOrderApproval 中的事件处理程序

此事件处理程序由在 BSMOrderApproval 过程中调用的 cancel 操作驱动。此处理程序能够记录已发生取消操作,然后终止该过程。由于存在订单被取消的可能性(这也是需要终止人工任务的原因),因此必须内嵌人工任务。如果该任务表示为一个独立组件,则在终止 BSMOrderApproval 过程时不会终止正在运行的任务实例。但是,由于该任务是内嵌任务,因此它会同时自动终止。

如果重新运行上述示例并在步骤 (3) 取消,则输出结果是:

BSMOrder(o1) Created
BSMOrder(o1) State is Building Order: Amount = 150.0
BSMOrder(o1) State is Awaiting Approval
BSMOrderApproval(o1): Start Task
BSMOrderApproval(o1): Cancelled 
BSMOrder(o1) State is Cancel

结束语

从本文示例中我们可以看出,通过将人工任务封装在对业务状态机执行适当回调的长时间运行的独立过程中,可以执行与业务状态机的人工交互。另外,通过内嵌人工任务并让任务过程支持终止该过程和内嵌任务活动的事件处理程序,还可以支持从业务状态机取消人工任务。尽管本文重点介绍了与业务状态机的单一人工交互,但该模式也适用于与状态机进行的每个所需的人工交互。


下载

描述名字大小
Project Interchange of BSM invoking Human TaskInvokeHTfromBSM_PI.zip15KB

参考资料

学习

获得产品和技术

  • 使用 IBM 试用软件开发您的下一个项目,可直接从 developerWorks 下载这些试用软件。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=163527
ArticleTitle=使用 WebSphere Process Server 实现业务状态机和人工任务之间的双向交互
publish-date=09272006