在我们能够设计编排层之前,我们需要很好地理解如何正式地表达流程的操作特征。本书使用
WS-BPEL
语言来演示流程逻辑如何能够被作为具体定义的一部分来描述(
图
16.1
),从而能够通过相适应的编排引擎来实现和执行。
图
16.1.
常见的
WS-BPEL
流程定义结构
虽然你很可能会使用流程建模工具并因此不需要从草稿开始编写你的流程,
WS-BPEL
元素的知识仍旧是有用的和必需的。
WS-BPEL
建模工具经常会涉及到这些元素和结构,而且你可能深入到它们生成的代码中做进一步的精化。
注意
如果你已经轻松了解了
WS-BPEL
语言,请向前跳到
面向服务业务流程设计(
循序渐进的流程
)
章节。
在我们进入
WS-BPEL
语言的细节之前,让我们简要讨论一下这个规范是如何形成的。
Web
服务业务流程执行语言(
BPEL
4WS
)最初在
2002
年
7
月被构思和发布,伴以
BPEL
4WS 1.0
规范,这是
IBM
、
Microsoft
和
BEA
合作的成果。这个文档提议了从先前的各种语言中得到灵感的编排语言,例如
IBM
的
Web
服务流程语言(
WSFL
)
与
Microsoft
的
XLANG
规范。
随着来自于
SAP
和
Siebel Systems
等其他贡献者的加入,版本
1.1
的
BPEL
4WS
规范在一年不到的时间,于
2003
年
5
月发布了。这个版本获得了更多的关注与厂商支持,导致了大量的商业上遵循
BPEL
4WS
的可用编排引擎。正是在这个发布之前,
BPEL
4WS
规范被提交到
OASIS
技术委员会,使得这个规范能够被开发成为一个官方的、开放的标准。
技术委员会正在下一个版本
BPEL
4WS
的最终发布流程中。它已经宣布了语言本身被重新命名为
Web
服务业务流程执行语言,或者是
WS-BPEL
(并被赋予
2.0
版本号)。
WS-BPEL
所规划的变更目前已经对外公布,并可在
OASIS
的
Web
网站
www.oasis-open.org
上获得。
在本节的元素描述中加入了注释,以利于指出
BPEL
4WS
与
WS-BPEL
之间的语法变动。为了简单起见,在本书中我们提到的业务流程执行语言就是指
WS-BPEL
。
现在是学习
WS-BPEL
语言的时候了。如果你还没有准备好,推荐你在继续本节之前阅读第
6
章。第
6
章中涉及了编排、协调、原子事务和业务活动等相关概念,因而在此就不再重复。本章同时也假设你已经通读了第
13
章中提供的
WSDL
教程。
让我们从
WS-BPEL
流程定义的根元素开始。它使用
name
属性来给一个名称赋值,并用于建立流程定义相关的命名空间。
示例
16.1.
process
定义框架
<process name=“TimesheetSubmissionprocess”
targetNamespace=“http://www.xmltc.com/tls/process/”
xmlns=
“http://schemas.xmlsoap.org/ws/2003/03/
business-process/”
xmlns:bpl=“http://www.xmltc.com/tls/process/”
xmlns:emp=“http://www.xmltc.com/tls/employee/”
xmlns:inv=“http://www.xmltc.com/tls/invoice/”
xmlns:tst=“http://www.xmltc.com/tls/timesheet/”
xmlns:not=“http://www.xmltc.com/tls/notification/”>
<partnerLinks>
...
</partnerLinks>
<variables>
...
</variables>
<sequence>
...
</sequence>
...
</process>
process
结构包含一系列常见的子元素,在下列章节中说明。
partnerLink
元素建立了端口类型的服务(伙伴),将参与业务流程的执行过程。伙伴服务能够担当流程的客户端,负责调用流程服务。作为替代,伙伴服务也能够被流程服务自身所调用。
partnerLink
元素的内容代表了两个合作伙伴之间的通信交换
---
流程服务是一个合作伙伴其他服务是另一个合作伙伴。依据通信的种类,流程服务的作用将会变化。例如,被外部服务所调用的流程服务可能担当
“工单提交流程(
TimesheetSubmissionProcess
)”的角色。然而,当这个同样的流程服务调用具有发票校验的不同服务的时候,它担当了不同的角色,或许是“发票客户(
InvoiceClient
)”。
partnerLink
元素因而包含
myRole
与
partnerRole
属性,分别设立了流程服务和伙伴服务服务提供者的角色。
为简单起见,
myRole
属性用于流程服务被伙伴客户端服务所调用时,因为在这个情况下流程服务担当了服务提供者。
partnerRole
属性识别了流程服务所调用的伙伴服务(使伙伴服务成为服务提供者)。
注意当期望的流程服务在相同的伙伴服务中担当服务请求者和服务提供者的时候,
myRole
与
partnerRole
属性都能够被相同的
partnerLink
元素所使用。例如,在流程和伙伴服务的异步通信过程中,在伙伴服务回调期间
myRole
的设置显示出流程服务的角色。
示例
16.2.
partnerLinks
结构包含一个
partnerLink
元素,在该元素内流程服务被一个外部客户端伙伴所调用,并且四个
partnerLink
元素确定了被流程服务所调用的伙伴服务
<partnerLinks>
<partnerLink name=“client”
partnerLinkType=“tns:TimesheetSubmissionType”
myRole=“TimesheetSubmissionServiceProvider”/>
<partnerLink name=“Invoice”
partnerLinkType=“inv:InvoiceType”
partnerRole=“InvoiceServiceProvider”/>
<partnerLink name=“Timesheet”
partnerLinkType=“tst:TimesheetType”
partnerRole=“TimesheetServiceProvider”/>
<partnerLink name=“Employee”
partnerLinkType=“emp:EmployeeType”
partnerRole=“EmployeeServiceProvider”/>
<partnerLink name=“Notification”
partnerLinkType=“not:NotificationType”
partnerRole=“NotificationServiceProvider”/>
</partnerLinks>
你会在
示例
16.2
中注意到,每个
partnerLink
元素同样也包含了
partnerLinkType
属性。这涉及到
partnerLinkType
结构,在下面说明。
对于包含在流程中的每个伙伴服务,
partnerLinkType
元素在流程定义中确定了被
partnerLink
元素引用的
WSDL
portType
元素。因此,这些结构典型地都直接嵌入到每个伙伴服务的
WSDL
文档中(包括流程服务)。
正如
partnerLink myRole
与
partnerRole
属性所定义的那样,
partnerLinkType
结构为每个服务可以担当的角色包含一个
role
元素。其结果是,
partnerLinkType
将具有一个或两个
role
子元素。
示例
16.3. WSDL
定义
结构包含
partnerLinkType
结构
<definitions name=“Employee”
targetNamespace=“http://www.xmltc.com/tls/employee/wsdl/”
xmlns=“http://schemas.xmlsoap.org/wsdl/”
xmlns:plnk=
“http://schemas.xmlsoap.org/ws/2003/05/partner-link/”
...
>
...
<plnk:partnerLinkType name=“EmployeeServiceType” xmlns=
“http://schemas.xmlsoap.org/ws/2003/05/partner-link/”>
<plnk:role name=“EmployeeServiceProvider”>
<portType name=“emp:EmployeeInterface”/>
</plnk:role>
</plnk:partnerLinkType>
...
</definitions
>
注意多个
partnerLink
元素可以引用相同的
partnerLinkType
。这当流程服务与多个伙伴服务具有相同关系的时候十分有用。所有的伙伴服务因而能够使用相同的流程服务的
portType
元素。
注意
在
2.0
版本的
WS-BPEL
规范中,提议了
portType
元素的变更以便作为
role
元素的一个属性存在。
WS-BPEL
流程服务通常使用
variables
结构来保存与即时工作流逻辑关联的状态信息。整个消息和数据集合被格式化为
XSD schema
类型,能够在处理过程中被置入变量并在以后获取。数据的类型能够被赋予
variable
元素,它需要用下面三个属性之一来预定义:
messageType
,
element
,或
type
.
messageType
属性允许变量包含整个
WSDL
定义的消息,而
element
属性完全引用了
XSD
元素结构。
type
属性能够用于仅代表
XSD
simpleType
,如
string
或
integer
。
示例
16.4.
variables
结构仅包含一些后续被工单提交流程所使用的
variable
子元素
<variables>
<variable name=“ClientSubmission”
messageType=“bpl:receiveSubmitMessage”/>
<variable name=“EmployeeHoursRequest”
messageType=“emp:getWeeklyHoursRequestMessage”/>
<variable name=“EmployeeHoursResponse”
messageType=“emp:getWeeklyHoursResponseMessage”/>
<variable name=“EmployeeHistoryRequest”
messageType=“emp:updateHistoryRequestMessage”/>
<variable name=“EmployeeHistoryResponse”
messageType=“emp:updateHistoryResponseMessage”/>
...
</variables>
典型地来讲,具有
messageType
属性的变量是为流程定义所处理的每个输入和输出消息定义的。这个属性的值是来自于伙伴流程定义的消息名称。
WS-BPEL
提供内置函数,允许存储在变量中或者是与变量关联的信息能在业务流程执行期间被处理。
getVariableProperty
(
variable name
,
property name
)
这个函数允许从变量中接收全局的属性值。它完全接受了作为输入的值和属性名称,并返回所要求的值。
getVariableData
(
variable name
,
part name
,
location path
)
由于变量通常用于管理状态信息,这个函数要求提供访问数据的其他部分处理逻辑。
getVariableData
函数具有一个强制的变量名称参数和两个能够用于指定变量数据的可选变量。
在我们的示例中我们多次使用
getVariableData
函数来从变量中获取消息数据。
示例
16.5.
两个
getVariableData
函数被用于接收来自于不同变量的特定数据
getVariableData
(
'InvoiceHoursResponse'
,
'ResponseParameter'
)
/SPAN>
getVariableData
(
'input'
,
'payload'
,
'/tns:TimesheetType/Hours/...'
)
sequence
结构允许你组织一系列的活动以便它们以预定义的、有顺序的次序执行。
WS-BPEL
提供了大量能够用于在流程定义中表示工作流逻辑的活动。在本节中剩余的元素描述解释了一组基本的用于我们将要进行案例研究示例的一部分活动。
示例
16.6.
sequence
结构框架仅包含了
WS-BPEL
所提供的许多活动元素中的一些
<sequence>
<receive>
...
</receive>
<assign>
...
</assign>
<invoke>
...
</invoke>
<reply>
...
</reply>
</sequence>
注意
sequence
元素可以嵌套,允许你在序列中定义序列。
该元素识别了伙伴服务的操作,这是流程定义计划在其执行过程中要调用的。
invoke
元素配备了五个常见属性,进一步详细说明了条文的细节(
表
16.1
)。
表
16.1.
invoke
元素属性
属性
|
描述
|
partnerLink
|
该元素通过相应的
partnerLink
来命名伙伴服务。
|
portType
|
该元素用于识别伙伴服务的
portType
元素。
|
operation
|
流程服务需要发送请求到的伙伴服务操作。
|
inputVariable
|
输入消息将用于和伙伴服务操作进行通信。注意这里所提及的是作为变量,因为它引用了具有
messageType
属性的
WS-BPEL
变量。
|
outputVariable
|
当基于请求
-
响应的
MEP
进行通信的时候采用该元素。返回值存储在单独的
variable
元素中。
|
/SPAN>
示例
16.7.
invoke
元素确定了目标伙伴服务的细节
<invoke name=“ValidateWeeklyHours”
partnerLink=“Employee”
portType=“emp:EmployeeInterface”
operation=“GetWeeklyHoursLimit”
inputVariable=“EmployeeHoursRequest”
outputVariable=“EmployeeHoursResponse”/>
receive
元素允许我们建立流程服务期望从外部客户端伙伴服务中接收请求的信息。在这个案例中,流程服务被视作是等待调用的服务提供者。
receive
元素包含一组属性,它们中的每一个都被赋值,涉及到预期进来的通信(
表
16.2
)。
表
16.2.
receive
元素属性
属性
|
描述
|
partnerLink
|
客户端伙伴服务在相应的
partnerLink
结构中被识别。
|
portType
|
流程服务
portType
会等待从伙伴服务中接收请求消息。
|
operation
|
会接收请求的流程服务操作。
|
variable
|
进来的请求消息将会被存储在流程定义的
variable
结构中。
|
createInstance
|
当这个属性被设置成“
yes
”的时候,这个特殊请求的可能负责创建新的进程实例。
|
注意这个元素同样能够被用于在异步消息交换的过程中接收回调消息。
示例
16.8.
用于工单提交流程定义的
receive
元素预示着客户端的伙伴服务负责启动工单文挡提交流程
<receive name=“receiveInput”
partnerLink=“client”
portType=“tns:TimesheetSubmissionInterface”
operation=“Submit”
variable=“ClientSubmission”
createInstance=“yes”/>