3. Correlation Sets
Correlation Sets(关联集合)定义了BPEL业务流中各业务交互的相关集,以指定服务实例中相关联的操作组。在业务流程实例的生命期中,它通常与涉及它工作的伙伴进行一次或多次对话。对话可基于成熟的传输基础结构,这种基础结构通过使用某种形式的对话标识使对话中的消息相关,并把它们自动地路由到正确的服务实例而无需在业务流程中注释。但是,在许多情况下,相关对话涉及的参与者不止两个,或使用轻量级传输基础结构(即把相关标记直接嵌套在被交换的应用程序数据中),在这种情况下,常常有必要提供另外的应用程序级机制,以使消息和对话被匹配到预定的业务流程实例。为了处理相关性情况,BPEL提供了声明性机制,以指定服务实例中操作的被相关组。一组相关标记可被定义为被相关的组中被所有消息共享的一组属性。这样的一组属性被称为关联集合。
每个关联集都在一个作用域中进行声明并属于该作用域。属于全局流程作用域的关联集称为全局关联集;属于局部作用域的关联集称为局部关联集。在流程开始时,全局关联集处于未初始化的状态。在其所属的作用域的执行开始时,局部关联集处于未初始化的状态。相关集在其语义上类似于延迟绑定的常数。相关集的绑定由特别标记的消息发送或接收操作来触发。相关集在其所属作用域的生存期中只能初始化一次。在初始化之后,它的值可被认为是业务流程实例的标识别名。在多方业务协议中,相关集合非常有用。初始者流程发送启动会话的第一个消息,从而定义了标记该对话的相关集中的特性值。所有其他参与者通过接收提供相关集中特性值的传入消息来绑定会话中的相关集。比如一个旅行社订票流程,当该流程启动之后,用户需要能够查询该流程状态,并能取消该流程,这就需要相关集的支持来确保后续的请求消息绑定到相同的流程实例中。
在实际应用中,我们必须保证在两个服务间一个长运行交互中交换的每个消息都找到与之相关的相同服务实例。Correlation Sets可以提供这种机制保障,一个Correlation Sets有助于唯一识别一个流程实例,并且将消息关联到特点的流程实例(如图8所示)。
图8
当定义一个CorrelationSet时,必须声明Correlation Sets、属性和属性别名。与此同时,也需要明确知晓与之相关实例或交互服务的消息的WSDL消息类型。实例如下,消息类型为:
newInvoiceMsg是匹配Invoice业务流程的第一个消息,这意味着当消息到达流程时流程仍然不保留数据。事实上,这个消息初始化Invoice业务流程,由此,我们可以将newInvoiceMsg消息关联到Invoice流程。
首先,需要识别消息中唯一标识流程的identifier。在上面的例子中,InvoiceNumber就是Invoice流程的唯一标识,因此我们定义一个单一属性:
定义属性:InvoiceNumber=xsd:String。这个属性被定义在WSDL文件中。
属性定义好后,定义Correlation Set。Correlation Set作为BPEL流程的一个元素。
定义Correlation Set:InvoiceKey=InvoiceNumber。
最后,需要建立一个newInvoiceMsg和Correlation Set的连接。这个连接定义就是属性别名。
属性别名可以看作消息部分和关联属性的一个简单映射。服务间的交互可以进一步细化为图9所示.
图9
4. FaultHandlers
活动执行过程中发生异常,业务流程必须对错误进行处理。与Java等语言类似,BPEL提供了异常处理机制。用户可以在业务流程中添加FaultHandlers来捕获并处理相应的异常。FaultHandlers与特定的Scope关联,用于捕获Scope内产生的异常。当异常发生时,BPEL正常执行流结束,控制流转入FaultHandlers内执行。
FaultHandlers类似于try-catch结构,它包含多个catch元素,每个都提供活动为特定类型的错误条件进行异常处理。故障会通过接收WSDL定义的故障消息来生成,或者它们可以通过使用throw元素被明确触发。FaultHandlers结构可以由catchAll元素构成(或终止)以提供默认的错误处理活动:
<faultHandlers>
<catch faultName="QName"?
faultVariable="BPELVariableName"?
( faultMessageType="QName" | faultElement="QName" )? >*
activity
</catch>
<catchAll>?
activity
</catchAll>
</faultHandlers>
当异常在特定的Scope内产生时,如果被Scope内定义的FaultHandler捕获,则该Scope状态被置位为Failed。当异常被处理后,外部Scope继续执行。如果异常无法被此Scope内FaultHandler捕获或无FaultHandler定义,则该Scope状态被置为Failed,并且将异常抛出到外部Scope继续处理,直到异常被处理为止。