Web 服务内幕,第 4 部分
Web 服务内幕,第 4 部分: 介绍 Web 服务流语言
内容:
工作流概述
学会术语
进入流程
展望未来
参考资料
关于作者
对本文的评价
介绍 Web 服务流语言

James Snell (jasnell@us.ibm.com)

软件工程师,Emerging Technologies,IBM
2001 年 6 月

所谓工作流就是指为满足商业需要而把各个过程组织成定义完备的操作流程。为了在 Web 服务架构的框架内定义软件的工作流过程,IBM 最近发布了一种新的 XML 语法。这里的四篇文章专门讨论 Web 服务中的工作流问题,我在第一篇中将介绍 Web 服务流语言的一些基本概念,使您迅速了解它究竟是什么以及它试图完成些什么。

(请点击文章顶部和底部的讨论,加入关于本文的讨论论坛。)

Web 服务的目的是使应用程序能够在网络上进行无缝集成,而不必考虑它的编程语言和运行环境。而 Web 服务工作流的目的就是使商业流程和利用了大量 Web 服务的交易生命周期能够进行同样的无缝集成。

Web 服务流语言(WSFL)是由 IBM 针对两个层面上的工作流提出的一项新标准:

  • 它试图用一个有向图模型来定义和执行商业流程;
  • 它定义了一个公共接口,该接口允许商业流程把自己宣传成为 Web 服务。

我们这四篇文章中专门帮助您学会如何充分利用 WSFL。我在第一篇中将首先介绍这种规范的一些最基本的概念。这一系列的另外三篇文章将主要讲述如何实际使用 WSFL。这里的介绍只打算让您对 WSFL 是什么以及必须提供什么有个最初的了解,因此对一些概念的细节部分忽略不谈。在这一系列文章的后续部分,我将会更深入钻研和探讨这种规范的更重要的部分。

工作流概述
工作流定义机制,在历史上已有先例。它能够对各种复杂的情况控制自如,使 XML 规范看起来就象孩子的童话一样奇妙。这其中的窍门就是创造一种能够迅速和精确地定义一个过程的方法,而且这种方法不能使控制逻辑变得过分复杂,以至于增加大量开销而无法实现。

为了从上述困境中解脱出来,WSFL 不打算适用于所有人,也不打算无所不能,只把重点放在工作流核心模型的产生上。该模型包括一些基本的过程以及简单的有向图, 这些边框控制着从一个活动到下一活动的处理逻辑流程。

如果您对商业流程建模和工作流不太熟悉,图 1 提供了一个简单的工作流的基本示例。这是一个有向图。每一个方框代表一个活动(即一些需要被完成的工作),每一条带箭头的实线(即)代表从一个活动到另一活动的控制流程,箭头指明流程进展的方向(因而被称作有向边)。在各个控制点要判定是否继续进行处理、当前活动是否完成、边框图是否继续画下去以及是否发生了错误,如此等等。那些连接各项活动的虚线表示两个活动之间的信息流程。

图 1:一个商业流程的示例
商业流程

根据图 1,我们可以把工作流的整个过程设想成从一个活动执行到另一个活动,并且在每个控制点作出相应的判定。

WSFL 实际上是一个对精确图表进行建模的工具,它使用人和机器都能理解的 XML 语法。通过使用 WSFL,一个按照活动和控制点层层递进的工作流引擎可以在商业流程中贯穿始终。无论如何这并非一个新的概念,然而 Web 服务之所以具有革命性的力量,主要在于它能够成为跨越各种平台边界的桥梁,因此 WSFL 的强大之处在于它能够跨越技术和商业的边界来对商业流程进行建模,而这恰恰是绝大多数的工作流引擎的局限之处。

清单 1 显示了图 1 的工作流图的 WSFL 语法。好好研究该文档的语法和结构。其中涉及到有关语法和个别元素时,可以参阅 WSFL 规范(请参阅参考资料)。

清单 1:示例商业流程的 WSFL 语法

<flowModel name="totalSupplyFlow" serviceProviderType="totalSupply">

  <serviceProvider name="buyer" type="buyer" />
  <serviceProvider name="seller" type="seller" />
  <serviceProvider name="shipper" type="shipper" />

  <activity name="submitPO">
    <performedBy serviceProvider="buyer"/>
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="submitPO"/>
      </export>
    </implement>
  </activity>

  <activity name="processPO">
    <performedBy serviceProvider="seller"/>
    <implement>
      <export>
        <target portType="receivePO"
operation="receivePO"/>
      </export>
    </implement>
  </activity>

  <activity name="processPayment">
    <performedBy serviceProvider="seller"/>
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="processPayment"/>
      </export>
    </implement>
  </activity>

  <activity name="submitShippingOrder">
    <performedBy serviceProvider="seller" />
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="submitShippingOrder"/>
      </export>
    </implement>
  </activity>

  <activity name="receiveShippingOrder">
    <performedBy serviceProvider="shipper" />
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="receiveShippingOrder"/>
      </export>
    </implement>
  </activity>

  <activity name="shipProduct">
    <performedBy serviceProvider="shipper" />
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="shipProduct" />
      </export>
    </implement>
  </activity>

  <controlLink source="submitPO" target="processPO"/>
  <controlLink source="processPO" target="processPayment" />
  <controlLink source="processPayment" target="submitShippingOrder"
/>
  <controlLink source="submitShippingOrder"
target="receiveShippingOrder" />
  <controlLink source="receiveShippingOrder" target="shipProduct" />

  <dataLink source="submitPO" target="processPO">
    <map sourceMessage="purchaseOrder"
targetMessage="purchaseOrder"/>
 </dataLink>
  <dataLink source="processPO" target="processPayment">
    <map sourceMessage="purchaseOrder"
targetMessage="purchaseOrder"/>
  </dataLink>
  <dataLink source="processPayment" target="submitShippingOrder">
    <map sourceMessage="purchaseOrder"
targetMessage="shippingOrder" />
  </dataLink>
  <dataLink source="submitShippingOrder"
target="receiveShippingOrder">
    <map sourceMessage="shippingOrder"
targetMessage="shippingOrder" />
  </dataLink>
  <dataLink source="receiveShippingOrder" target="shipProduct">
    <map sourceMessage="shippingOrder"
targetMessage="shippingOrder" />
  <dataLink>
</flowModel>

学会术语
就象普通的工作流一样,WSFL 有它自己专用的词汇表;控制 WSFL 的关键是控制该词汇表。下面我仅仅粗略地讲一下一些更重要的 WSFL 的概念。随着这一系列的讨论继续进行,我们将会精选出更多的概念来进行重点讲解。

商业流程:商业流程就是通过组合能实现一个特定商业目标的各项活动的任一集合。例如,处理一个信用卡号,雇佣一个新职员,提交一个专利等都是商业流程的示例。

流程模型:流程模型实际就是用 XML 表示的一个对商业流程建模的指示性图表。其结构过去常常被用于把 Web 服务组成工作流,而 Web 服务由它们各自的 Web 服务描述语言(WSDL)文档来定义(请参阅参考资料)。流程模型有时被认为是流程的排版,其作用相当于管弦乐的编曲和舞蹈的编排。

全局模型:仅仅对一个工作流中两个活动之间的处理流程进行建模是不够的(在 WSFL 的术语中是指对两个 Web 服务之间的处理流程进行建模)。除流程模型之外,还需要有种方法来明确指定在整个过程中 Web 服务相互之间如何实现预期的交互作用。所以我们就引入了全局模型这个概念,全局模型就是当流程被执行时,用来指定 Web 服务之间的消息在流程模型中如何传递的一系列必需链接。

递归嵌套:WSFL 有一个很酷的特征:一旦您为一个指定的商业流程定义了全局模型和流程模型,就可能把整个商业流程定义为一个个别的 Web 服务,该 Web 服务可能被其它的商业流程使用。换句话说,在 WSFL 商业流程中可以递归嵌套 WSFL 商业流程。这样能大大提高您定义的模型的灵活性,并丰富其可能性。它也为一些非常激动人心的商机的到来打开了门户,有关这些商业上的种种可能性,我将在第四篇文章中阐明。

服务提供者:服务提供者就是一个商业流程中负责执行一个特定活动的团体。在 WSFL 中,每一个活动都是一个 Web 服务,因而每一个服务提供者就是一个由 Web 服务架构文档定义的 Web 服务提供者(请参阅参考资料)。

服务提供者类型:为了明确区分商业流程及其实现,WSFL 的流程模型和全局模型把每个活动定义为由特殊类型的服务提供者来实现,而不是由特殊的服务提供者本身来实现。服务提供者类型由一个使用 WSFL 的 Web 服务接口文档来定义。为了在商业流程中做到不同类型的服务提供者能够控制与之相应的特殊活动,服务提供者必须正确实现与之相适应的 Web 服务接口。

控制链:控制链就是 WSFL 中相当于我们前面谈到的指示性边框的部分,也就是说,它是在商业流程中通过工作流处理器把每个活动贯通起来的机制。

数据链:数据链是工作流处理器用来控制通过商业流程的数据流的机制。尽管多数情况下,数据流和控制流紧密相连,但很可能整个商业流程中的信息流传递方式与所激活的各项活动的序列有所不同。

转移条件:作为一个正在运作的商业流程,工作流处理器必须能够识别一个特定的活动何时结束以及下一个活动何时被判定和被激活。转移条件就是一条是或者否的语句,处理器借以判定任何一个特定活动的当前状态。

生命周期接口:如上所述,WSFL 商业流程本身能够被定义成 Web 服务。生命周期接口就是由 WSDL 定义的 Web 服务接口,该接口描述了在一个特殊的 Web 服务应用程序中所有 WSFL Web 服务支持的一组基本操作。这些操作包括:商业流程的激活、挂起、恢复、阻塞、终止,以及查询其当前状态。

进入流程
读完上面给出的商业流程的示例,我们可以容易地根据图表把一般处理流程看作每个被具体执行的活动。整个过程的关键就是 activitycontrolLink 的定义,它们控制着实际的流程。举例来说,清单 2 就描述了从 submitP0 活动到 processP0 活动的一段控制流程。

清单 2:一段控制流程的描述

    <activity name="submitPO">
    <performedBy serviceProvider="buyer"/>
    <implement>
      <export>
        <target
portType="totalSupplyPT" operation="submitPO"/>
      </export>
    </implement>
  </activity>

  <activity name="processPO">
    <performedBy serviceProvider="seller"/>
    <implement>
      <export>
        <target portType="receivePO"
operation="receivePO"/>
      </export>
    </implement>
  </activity>

  <controlLink source="submitPO" target="processPO"/>

这里,掌握下面一个简单的概念非常重要:每个活动被 WSDL 文档描述成一个单独的 Web 服务。不同的 controlLink 边框把这些 Web 服务按照一定的顺序连接起来。下面显示的是 dataLink 定义,它定义了数据是怎样从一个活动传递到下一个活动中。

清单 3:数据链定义

  <dataLink source="submitPO" target="processPO">
    <map sourceMessage="purchaseOrder"
targetMessage="purchaseOrder"/>
  </dataLink>

sourceMessagetargetMessage 属性指的是 WSFL 为源 Web 服务和目标 Web 服务定义的消息。dataLink 把这两种消息映射在一起,实际上就是表明 sourceMessage 就和 targetMessage 一模一样。

没有出现在这个 WSFL 示例中的是控制转移条件,实际上正是它们决定了每个单独活动当前是否完成,以及工作流是否准备转移到下一个活动中去。我将在接下来的部分中讨论这些转移。

您还应该注意 flowModel 示例中提到了三种类型的服务提供者:买方、卖方和发货方。

清单 4:流程模型示例中的服务提供者

  <serviceProvider name="buyer" type="buyer" />
  <serviceProvider name="seller" type="seller" />
  <serviceProvider name="shipper" type="shipper" />

它们中的每个都代表了完成整个商业流程所必须胜任的角色。任何一个能够实现买方、卖方和发货方服务提供者类型定义的 Web 服务提供者都可以胜任这样的角色。一旦确定了一个适当的服务提供者,有关该提供者的引用可能立即就通过定位器元素和 WSFL 文档一起被直接引用,或者工作流引擎可能会判定有关链接是如何被分辨的。如此设置的机制可以大大提高 WSFL 的灵活性,允许商业流程被自由定义,而不必关心究竟是谁来负责实现每一个单独活动。

展望未来
在这一部分,我已经描绘了 WSFL 的概貌,简单介绍了它是做什么的以及它怎样来做。您已经了解到 Web 服务工作流的基本概念。下一部分我们将论及以下必要步骤:如何实际建模一个商业流程、创建全局模型和流程模型以及定义具体实现流程步骤的服务提供者类型。在第 3 部分中,我们会看到一个服务提供者怎样来实现一个定义好的服务提供者类型,并且在商业模型内部假定适当的角色。在第 4 部分和最后,我们将探讨递归嵌套的概念,并且示例说明商业流程怎样被组合利用来解决更加复杂的商业问题。

参考资料

  • 请点击文章顶部和底部的讨论,加入关于本文的讨论论坛
  • -->
  • 请确信仔细阅读过本专栏在此之前的三篇文章:第 1 部分第 2 部分第 3 部分
  • 如果您初次接触 Web 服务方面的内容,强烈推荐您阅读 Web 服务概念架构文档,从而对一些重要概念有个基本的了解。
  • WSFL 主要建立在 Web 服务描述语言(WSDL)和用于描述单独 Web 服务的 XML 语法的基础之上。
  • WSFL 规范表明 IBM 不断充实完备基于 XML 的工作流定义语法的集合,该集合包括 ebXML 商业流程规范商业流程建模语言以及 Microsoft 专利的作为 Biztalk Server 核心的 XLANG
  • 当然,还有 Web 服务流语言规范本身。

关于作者
James Snell 是一位撰稿人和开发人员,他也是 IBM Web 服务开发小组的最新成员之一。他在进入 IBM 之前,已经具有关于定制企业应用开发和商家对商家集成这些方面的背景,而且他对 Web 技术前沿方面有着极大的热情。可以通过
jasnell@us.ibm.com 和他联系。


(c) Copyright IBM Corp. 2001, (c) Copyright IBM China 2001, All Right Reserved
  关于 IBM  |  隐私条约  |  法律条款  |  联系 IBM