流程可以用三种活动与外界进行交互:<invoke>、<reply> 和 <receive>。和我们在前面的文章中看到的一样,流程的伙伴之间通过使用这三种活动发生交互。通过指定 portType、操作以及伙伴,这些活动中的每一种活动标识出它所属于的 Web 服务调用。
流程用 <invoke> 活动调用伙伴提供的 Web 服务。除了 portType、伙伴和操作之外,调用还为正被调用的操作的输入和输出指定输入容器和输出容器。调用可以是同步的(请求/响应),也可以是异步的(单向)。在后一种情况中,只需要输入容器。
业务流程通过一对 <receive> 和 <reply> 活动为它的伙伴提供服务。receive 表示流程提供的 WSDL 操作的输入。如果流程需要向发送消息的伙伴返回一个应答,那么 reply 活动就是必需的。在流程中可以定义多个 reply 活动来回答该伙伴的调用;但是,一次只可能有一个匹配的 <reply> 成为激活的。适当的 reply 活动的匹配是在运行时进行的,此时流程寻找这样一个活动 — 准备运行并拥有和 <receive> 相同的 portType、操作和伙伴。例如,流程可能将接收到的消息放在某个容器(容器 A)中,如果满足某个条件就返回容器 A 中的消息,否则就返回来自另一个容器(容器 B)的消息。在这种情况下,receive 将具有两个带有该项条件的链接;这两个链接将链接到两个 reply 活动,只有其中一个 reply 活动将激活并向伙伴返回正确的消息。
流程生命周期
只有当一条消息被发送给特别标记的 <receive> 活动或 <pick> 活动时,才可能创建一个业务流程实例。几个 receive 活动指出通过将 createInstance 属性设置为真,它们就能够创建一个流程实例。<pick> 活动将拥有一个 onMessage 元素,这个元素也具有 createInstance 属性并且被设置为真。在本文稍后的部分将更详细地说明 <pick> 活动。第一个被这样标记并且获得了一条消息的 receive 活动将创建实例,接着,其余 receive 活动在该实例中就被当作常规 receive 活动来对待。
此时,您可能想知道怎样才能创建第二个实例。相关性用于弄清楚传入的消息要发送给哪个实例。所有可以启动流程的 receive 和 onMessage 都必须拥有相同的相关性设置。所以,当一条消息进来的时候,流程对其进行检查以了解它是否包含与现有的实例相匹配的相关性设置。如果这条消息符合条件,流程就将它发送给那个实例。否则,流程将根据与传入的消息的操作、portType 和伙伴信息相匹配的 receive 活动创建一个新实例。在本系列以后的文章中将详细讨论 BPEL 中的相关性。
<assign> 活动可以用于将数据从一个容器复制到另一个容器,也可以用于通过使用表达式构造和插入新数据。使用表达式主要是由于需要执行简单的计算(如递增序列号)而激发的,这些简单计算是描述业务协议行为所必需的。表达式对消息选择、属性和文字常量进行操作,以便为容器属性或选择产生新的值。
每个 <assign> 活动包含一个或多个 <copy> 元素;每个 <copy> 元素正好包含一个 <from> 元素和一个 <to> 元素。有各种形式的 <from> 元素和 <to> 元素,要记住的最重要的事情就是,从源(<from>)复制到目的地(<to>)的值必须是类型兼容的。
一种较简单的 <from> 形式仅用名称指定容器。当使用仅指定一个容器的源时,将复制整个消息;这意味着目的地也必须仅指定一个容器。
更复杂一点的 <from> 形式指定一个容器以及该容器中的一个部件。当使用这种形式时,目的地也必须指定一个容器及其中的一个部件。
第三种形式的 <from> 指定要用 XPath 进行求值的一般表达式。该表达式可以是 XPath 允许的任何东西,只要该表达式返回 XPath 值类型(字符串、数值或布尔)。当使用这种形式时,目的地必须指定一个容器及其中的一个部件。
简而言之,消息可以覆盖其他消息,消息部件可以覆盖其他消息部件。因为表达式不返回完整的消息,所以它们只被用于覆盖消息部件。
因为有必要使 XPath 表达式能够访问来自流程的信息,所以 BPEL4WS 引入了几个 XPath 扩展函数。在标准的 BPEL4WS 名称空间 http://schemas.xmlsoap.org/ws/2002/07/business-process/ 中定义这些扩展函数,前缀 bpws 与这个名称空间相关联。
这些函数之一的一个示例如下所示。
bpws:getContainerData("containerName", "partName", "locationPath"?)
在这个示例中,containerName 是容器的名称,partName 是该容器中一个部件的名称,locationPath 是这个指定部件中的绝对位置路径,它是可选的。
任何希望检索来自流程中某个容器的数据的 XPath 表达式都可以使用 bpws:getContainerData() 函数,就好像它是内置的 XPath 函数一样。
注:除了复制消息、部件和表达式外,<assign> 活动还可以用于将服务引用复制到伙伴链接以及从伙伴链接复制服务引用。
<throw> 活动发出故障信号。为了使您能够使用故障处理程序来最终捕获故障并对其进行处理,该语言要求故障有一个全局唯一的 QName。可以添加一个可选的容器,该容器指向可以找到与故障相关的数据的位置。例如,您可能有一个发出某种故障的信号的 <throw> 活动,然后可以有一个具有 <reply> 的故障处理程序,该 <reply> 向伙伴发送关于故障的信息。该 reply 将使用故障活动中指定的容器。
<terminate> 活动可以用于立即放弃执行着该终止活动的业务流程实例中的所有执行。
<wait> 活动使流程能够等待一段特定的时间间隔,或者一直等到某个截止期限为止。
<empty> 活动什么都不做。如果您需要捕获一个故障并抑制它,您可以使用这个活动。