Web 服务内幕,第 5 部分:进入流
Web 服务内幕,第 5 部分:进入流
内容:
商业流程 101
整体规划中的 Web 服务
构建流模型
构建全局模型
下一部分内容?
参考资料
关于作者
对本文的评价
用 WSFL 建模的商业流程

James Snell (jasnell@us.ibm.com)
软件工程师,Emerging Technologies,IBM
2001 年 7 月

在 Web 服务内幕的上一部分中,我已经向您介绍了 Web 服务流语言(Web Services Flow Language,WSFL)的基本原理。在这一部分,我将兑现我的许诺,循序渐进地阐述如何设计和创建用 WSFL 实现的商业流程模型的具体步骤。

商业流程建模对于许多开发人员并不是很容易掌握,因为它并不是简单地下载一个代码片段然后进行适当的修改就可完成的。我们要承认这样一个事实,有时我们开发人员是相当懒惰的。适当的商业建模需要花费一定的时间,它要求接受整体规划的能力,不仅能够组合应用程序的特殊 kibbles'n' 字节,而且能够使应用程序适合整个架构,该架构用于实现一些截然不同的商业目标。

在上一期中(请参阅参考资料),我花费了一些时间向您介绍一个新规范,这个规范适用于在 Web 服务架构的框架内实现商业流程。WSFL 使开发人员能够很容易地创建、执行 Web 服务,以及将 Web 服务合并到复杂的过程和工作流中。

在 Web 服务内幕的这一部分中,我将探究如何创建一个 WSFL 商业流程的实现,首先是介绍一般商业流程建模的基本原理。然而,这将是一个相当高深的讨论,涵盖许多更复杂的问题,不过有时会完全忽略其它问题。要牢记的重要一点是,它只不过是一个介绍,被设计用来帮助您从正确的方向开始。强烈推荐您利用本文结束处所包含的参考资料。

商业流程 101
太多情况下,开发人员习惯于根据他们要实现的技术或功能来看他们正在编写的应用程序;这儿是一个地址薄,那儿是一个购物车,或许甚至是即时消息或对等架构等等。他们经常不考虑需要使用那些应用程序的整体规划,而这些整体规划,在许多情况下,可解决某些类型的关键商业需要。

冒着听起来好象是在鼓吹公司的危险,人们常常把电子商务看成是“电子”而非“商务”。商业流程建模通过将框架植入个别应用程序(为满足流程中每一步的要求,可能要插入这些应用程序),努力把“商务”做成了一个图 — 就象为一个汽车装配线购买原材料,或雇用一个新员工或支持一个重要的客户帐号。商业流程建模从一个能表达流程整体样子的图开始,并按照以下因素分解开来:必须完成的特定活动、必须完成这些活动的顺序、这些活动间的依赖性以及确保完成这些活动的角色的定义。

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

图 1 描绘了一个从 WSFL 规范完全复制而来的简单商业流程。您会注意到上面的图中,流程中的每个重要步骤都被标识出来,且与定义了特定顺序(每个步骤都必须按这个顺序完成)的工作流一致。无论使用一些 Java 应用程序、或 Web 服务、或任何不相关的内容能或不能严格地实现这些步骤中的任何一个。换句话说,一个商业流程模型是关于必须发生的事件链而不是关于这些事件将如何发生的特定细节。

图 1 中的一个椭圆表示一个活动。每个活动表示必须由某人或某物完成的某事。所有的活动都用箭头链接在一起,称为有向边,它指出从一个活动到下一活动的流向。这个流向可能是有条件的也可能是无条件的;也即,可能有一些指定条件的规则,要执行流程中的下一个活动必须满足这些规则。可能还有一些规则指定完成某个活动的确切时间或发生错误时如何处理。图中虚线行指出活动间的信息流,这一点我将在创建 WSFL 全局模型这一部分进行更深入的说明。

整体规划中的 Web 服务
WSFL 使 Web 服务在整个商业流程或“流”模型中扮演实现活动的角色。在整体规划中,这意味着个别类型的 Web 服务(地址薄、即时消息,信用卡验证服务等)不如正在实现的整个工作流重要,至少从希望使用那些服务的公司来看是如此。用另一种方法解释,Web 服务的真正价值在于它们能够使开发人员真正地引导商务或共享信息,而不在于 Web 服务自身的个别优点。

构建流模型
这一次,我需要指出这样一个事实,即 WSFL 自身,不是一个关于如何创建商业流程模型的规范,而是一个关于如何实现使用新兴 Web 服务架构的商业流程模型的规范。换句话说,您并不实际使用 WSFL 定义商业流程模型;这些工作由一些 UML 行执行。您将更愿意使用 WSFL 来创建商业模型的一个 XML 表示法,然后将 XML 表示法供给中间件应用程序,这些中间件应用程序被设计用来调用和管理过程(例如,通过使用 IBM 的 MQSeries Workflow,或 Rational Rose)。然后,您需要理解如何将商业流程模型图转换为 WSFL 流模型。

这个过程其实很简单,一旦有这样一个工具,它可暗箱处理这个步骤,根据图形化商业流程模型自动生成 WSFL 流模型,这就将成为一个您不必理会的问题了。但现在,理解在 WSFL 中各种事物是如何结合在一起的,有助于理解它在 Web 服务架构中的用处和功能。

根据商业流程模型创建 WSFL 流模型实际仅取决于对 WSFL 语法中使用的每个 XML 元素的功能的理解,以及对在流程模型中互相通信的每个重要信息片段之间的差别的理解。

在模型中,您会注意到有三个截然不同的角色,活动的实现要贯穿这三个角色。这些角色代表了谁负责实现特定活动。例如,旅游者计划行程,代理商选择行程路线而航空公司签发电子机票。WSFL 要求明确指定这些角色,以作为流程实现的一部分。您将使用 WSFL serviceProviderType 元素来完成这项工作。

清单 1:描述旅游过程中的角色的 WSFL 语句

<definitions name="totalTravel">
   <serviceProviderType name="travelerType">
      <portType name="abc:ticketBuyer" />
   </serviceProviderType>
   <serviceProviderType name="agentType">
      <portType name="abc:tripHandler" />
      <portType name="abc:ticketBuyer" />
   </serviceProviderType>
   <serviceProviderType name="airlineType">
      <portType name="abc:ticketHandler" />
      <portType name="abc:ticketDelivery" />
   </serviceProviderType>
</definitions>

serviceProviderType 元素在给定商业流程模型的上下文中标识每个角色类型和特定 Web 服务接口(以 WSDL 定义的 portTypes 形式),它们必须由 Web 服务提供者来实现,以履行那些角色。

在这个示例中,实际上有两个不同的子过程需要您关心:登记行程与订票和签发机票过程。一般情况下,应使用不同的 WSDL flowModel 为每个过程建模。每个 flowModel 由几个至关重要的信息片段组成,它们是管理过程实现的工作流引擎在工作时所必需的。这些信息包括:

  • 服务提供者的身份,该提供者履行必需的角色,负责每个活动
  • 启动过程的条件(称为 flowSource
  • 过程的外部接口,通过这个接口可使信息进出该过程
  • 每个活动的定义(根据实现方法以及预期实现者进行定义)
  • 在过程被执行时,控件和信息如何从一个活动流向下一个活动的定义,包括每个活动和过程自身的各种退出和启动条件

遗憾的是,我没有时间详细描述每个元素,所以我能做的是提供一个类似用于购买机票的 flowModel 的示例。这是来自 WSFL 规范自身的又一个示例,所以为更多地了解这个示例,我推荐您花费些时间阅读它。

清单 2:旅游过程的流模型
<flowModel name="bookTickets" serviceProviderType="airlineFlow">

  <!-- Defines the start condition for this process, 
      which in this case is the reception of
      a TicketOrder -->

  <flowSource name="ticketFlowSource">
    <output name="processInstanceData" message="tio:receivedTicketOrder"/>
  </flowSource>

  <!-- Defines the service providers who will be 
      implementing this process. The serviceProvider 
      element offers several ways of uniquely or 
      dynamically identifying the specific provider 
      who will be implementing that role. -->

  <serviceProvider name="agent" type="agentType"/>
  <serviceProvider name="traveler" type="travelerType"/>

  <!-- Defines an external interface that allows this 
      process to be launched. WSFL defines that this 
      interface is itself a Web Service making it
      possible to "spawn" a business process using SOAP 
      messages, etc. Each export represents an operation 
      in a WSDL document that describes WSFL Web Services -->

  <export lifecycleAction="spawn">
    <target portType="tio:ticketHandler" operation="receiveTicketOrder">
      <map sourceMessage="receiveTicketOrderInput" 
      targetMessage="processInstanceData" targetPart="request"/>
      <map sourceMessage="processInstanceData" 
      sourcePart="airlineWorkId" 
      targetMessage="receiveTicketOrderOutput"
      targetPart="airlineWorkId" />
    </target>
  </export>

   <!-- Activities are defined in terms of the WSDL 
      defined messages that are either received, sent 
      or both, as well as in terms of who is responsible 
      for performing that activity. -->
  <activity name="reserveSeats">
    <input name="reserveSeatsInput" message="tio:receivedTicketOrder"/>
    <output name="reserveSeatsOutput" message="tio:reservation"/>
    <performedBy serviceProvider="local"/>
    <implement>
      <internal>
        <!-- .. call to reservation system .. -->
      <internal/>
    </implement>
  </activity>

  <activity name="chargeCreditCard" >
    <input name="dataIn" message="tio:reservation" />
    <output name="dataOut" message="tio:chargedReservation"/>
    <performedBy serviceProvider="local"/>
    <implement>
      <internal>
        <!-- .. call to credit card service .. -->
      </internal>
    </implement>
  </activity>

  <activity name="confirmFlights" >
    <input name="confirmFlightsInput" message="tio:chargedReservation"/>
    <output name="confirmFlightsOutput" message="tio:eTicketMsg"/>
    <performedBy serviceProvider="agent"/>
    <implement>
      <export portType="tio:ticketHandler" operation="sendConfirmation">
        <map sourceMessage="confirmFlightsInput" sourcePart="confirmationInfo" 
          targetMessage="sendConfirmationOutput" targetPart="confirmationInfo"/>
      </export>
    </implement>
  </activity>

  <activity name="issueETicket">
    <input name="issueETicketInput" message="tio:eTicketMsg"/>
    <performedBy serviceProvider="traveler"/>
    <implement>
      <export portType="tio:deliverTickets" operation="sendETicket">
        <map sourceMessage="issueETicketInput" sourcePart="authorization" 
          targetMessage="sendETicketOutput" targetPart="authorization"/>
      </export>
    </implement>
  </activity>

  <!-- controlLinks represent the directed edges in the process diagram.  They are
        the arrows that determine the next step in the business process. -->
  <controlLink name="rS-cC" source="reserveSeats" target="chargeCreditCard"/>
  <controlLink name="cC-cF" source="chargeCreditCard" target="confirmFlights"/>
  <controlLink name="cF-sT"  source="confirmFlights" target="issueETicket"/>

  <!-- dataLinks define the flow of data from activity to another.  They represent the 
        dotted lines that we see in the model diagram -->
  <dataLink  name="rS-cCdata" source="reserveSeats"  target="chargeCreditCard"/> 
  <dataLink  name="gT-rS-data" source= "ticketFlowSource" target="reserveSeats"/>
  <dataLink name="cC-cFdata" source="chargeCreditCard" target="confirmFlights"/>
  <dataLink name="cF-sTdata" source="confirmFlights" target="issueETicket"/>
</flowModel>

构建全局模型
WSFL flowModel 中定义的每个活动都是以 WSDL 定义的 Web 服务的形式实现的。每个活动代表给定的 portType 中的一个操作或操作组合。在给定过程中履行角色的每一方都必须正确执行由 flowModel 中的 serviceProviderType 元素定义的 portTypes。然后必需的是一个映射 portTypes 的方法和一个由服务提供者使用 portTypes 实现的操作以及由另一个服务提供者实现的操作,这样 flowModel 中定义的控件和数据链接知道执行活动或交换信息时要调用活动的哪个操作。现在,如果您不确定这是否有意义,请这样考虑:如果您要寄一盒巧克力给我 — 我很乐意接受 — 您需要知道我的地址。在 WSFL 中,这个地址是以给定的 Web 服务接口上的操作的形式表示的,并通过 globalModel 进行通信。

清单 3:旅游过程的全局模型

<globalModel name="bookTripNTickets" serviceproviderType="agentType">

  <!-- Defines the identity, location and implementation of the service provider
        fulfilling the role of the travel agent -->
  <serviceProvider name="travelAgent" serviceProviderType="tio:agentType">
    <export>
      <source portType="tio:tripHandler" operation="sendItinerary"/>
      <target portType="tio:tripNTicketHandler" 
operation="sendItinerary"/>
    </export>
    <export>
      <source portType="tio:tripHandler" operation="receiveTripOrder"/>
      <target portType="tio:tripNTicketHandler" 
operation="receiveTripOrder"/>
    </export>
    <locator type="static" service="Traveluck.com"/>
  </serviceProvider>

  <!-- Defines the identity, location and implementation of the service provider
        fulfilling the role of the airline -->
  <serviceProvider name="airline" serviceProviderType="tio:airlineType">
    <export>
      <source portType="tio:ticketDelivery" operation="sendETicket"/>
      <target portType="tio:tripNTicketHandler" 
operation="sendETickets"/>
    </export>
  </serviceProvider>

  <!-- A plugLink links the output of an operation of one service provider to the 
input of 
        an operation for another service provider -->
  <plugLink>
    <source serviceProvider="airline" portType="tio:ticketHandler"
operation="sendConfirmation"/>     <target serviceProvider="travelAgent" portType="tio:tripHandler"
operation="waitForConfirmation"/>   </plugLink>   <plugLink>     <source serviceProvider="travelAgent" portType="tio:tripHandler"
operation="requestTicketOrder"/>     <target serviceProvider="airline" portType="tio:ticketHandler"
operation="receiveTicketOrder"/>   </plugLink> </globalModel>

flowModelglobalModel 分开使您能够把工作流过程的抽象定义(flowModel)与关于给定过程是如何实现的特定细节(globalModel)分开。

下一部分内容?
在本栏目的下一部分中,我将讨论服务提供者必须要做哪些工作,来履行 WSFL flowModel 所定义的角色。该过程具有从现有的商业流程中重新组合新的商业流程的能力,表现出 WSFL 强大的、引人注目的功能中的一种。同时,您可能希望通过使用下面列出的参考资料来继续学习商业流程建模和 WSFL。

参考资料

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



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