当我开始这个分四部分的介绍 WSFL 的系列时,我的目的很简单:使您对 WSFL 有一个基本了解,知道它能做什么,如何使用它,以及它有什么优势。但是,如果不接触它其中的一个核心功能:商业流程的递归组合,任何关于 WSFL 的讨论都不能算完整。
递归组合的思想很简单:可以通过组合现有的商业流程来定义新的商业流程(请参见 图 1)。由于我在这里讨论的是 Web 服务,所以从本质上来说它意味着,使用 WSFL 您可以用一个 Web 服务接口(WSDL 文档)将商业流程包装起来,并将其当作您希望与之交互的任何其它 Web 服务一样对待。
图 1:Web 服务的递归组合
您可能马上会问,“它是什么?为什么它很重要?”我将用一个现实生活中的案例回答这些问题。例如,您在 ReaderCo 公司工作,您希望买一本书。您的公司已经有了一个使用 WSFL 建模的采购商业流程。现在,我的公司 SnellCo 是销售书籍的。我有一个为处理书籍订单而建立的商业流程。您的 WSFL 流模型包含一个向能够处理此订单的公司提交此订单的活动。我的 WSFL 流模型只可在已经接收到购买订单时才能够开始。因此,通过用 WSDL 接口将我的商业流程包装起来并将其作为“书籍订购 Web 服务”在 Web 上发布,您的 WSFL 流模型就可以发现我的服务并提交其购买订单。
在这个案例中,您不用在意我的 WSFL 流模型是什么样子,只是希望能够将购买订单推进这个模型来使整个流程运转。而我也真的不在意您的 WSFL 流模型是什么样子,我只希望接收到您的购买订单,这样就可以让这个流程继续进行。WSFL 支持递归组合,允许您和我用某种方法将我们的两个商业流程链接起来,这种方法要求我们只要在提交的购买订单的格式上达成一致即可。在保持分布式工作流体系结构时,这可以简化进行商业活动的方法。
在 WSFL 中,每个商业流程都有私有生命周期和共有生命周期。有一些内容内部成员能够看到而外部成员则看不到。商业流程的私有生命周期称为 商业流程的 私有接口,同样,公共生命周期是其 公共接口。在私有接口中,您会发现流模型和全局模型,它们定义商业流程实际要做的工作。WSFL 允许您操作流程的单个部分,比如接收购买订单的地方,或打出收据的地方,并将它们作为商业流程公共接口的一部分 导出。 图 2显示了在 WSFL 中的单个活动的导出如何允许您为商业流程建立一个 WSDL 接口,其它应用程序可通过这个接口进行交互。
图 2:导出 WSFL 中的单个活动
导出一个 WSFL 活动与将 Java 类上的操作标记为
public 大致相同。也就是说,当一个方法被标记为
public 时,对于其它使用该 Java 类的应用程序它就是可见的和可访问的。它与下面这种情况完全相同,即当您导出一个活动时,它变为可见的,同时也是使用 WSDL 进行描述的 Web 服务接口描述的一部分。为搞清楚这一点,我将向您展示一个简单的示例。
首先,设想一个非常简单的工作流流程,如 图 3所示。
图 3:一个非常简单的工作流流程
在这个流程中,只有三个活动: 查看股票、 确定最好的卖出价格以及 卖出股票( 不卖出泡泡框实质上会结束工作流而无需任何附加活动)。这个流程的流模型如 清单 1所示。
<flowModel name="sample" serviceProviderType="sampleType"> <flowSource name="samplesource"> 牋_<output name="processInstanceData" message="tio:doStocks"/> _</flowSource> _<serviceProvider name="buyer" type="buyerType"/> _<serviceProvider name="seller" type="sellerType"/> _<export lifecycleAction="spawn"> 牋_<target portType="tio:sample" operation="doStocksRequest"> 牋牋_<map sourceMessage="doStocks" targetMessage="processInstanceData" targetPart="request"/> 牋_</target> _</export> _<activity name="checkStocks"> 牋_<input name="checkStocks" message="tio:checkStocks"/> 牋_<output name="checkStocksOutput" message="tio:stockQuote"/> 牋_<performedBy serviceProvider="buyer"/> 牋_<implement> <!--implementation details --> 牋_</implement> _</activity> _<activity name="determineSellPrice"> 牋_<input name="dataIn" message="tio:stockQuote" /> 牋_<output name="dataOut" message="tio:sellOrder"/> 牋_<performedBy serviceProvider="buyer"/> 牋_<implement> <!--implementation details --> 牋_</implement> _</activity> _<activity name="sellStocks" > 牋_<input name="sellOrder" message="tio:sellOrder"/> 牋_<output name="sellOrderOut" message="tio:sellConfirmation"/> 牋_<performedBy serviceProvider="buyer"/> 牋_<implement> <!--implementation details --> 牋_</implement> _</activity> _<controlLink name="c1" source="checkStocks" target="determineSellPrice"/> _<controlLink name="c2" source="determineSellPrice" target="sellStocks"/> _<dataLink_name="c1" source="checkStocks"_ target="determineSellPrice"/>_ _<dataLink_name="gT-rS-data" source= "determineSellPrice" target="sellStocks"/> </flowModel> |
其中的两个操作, 查看股票和 卖出股票,要求商业流程与商业流程自身外部的 Web 服务进行交互,所以我们需要将那些活动作为流程公共接口的一部分导出。我们使用流模型中的导出机制进行此导出操作,如 清单 2所示。
_<activity name="checkStocks"> 牋_<input name="checkStocks" message="tio:checkStocks"/> 牋_<output name="checkStocksOutput" message="tio:stockQuote"/> 牋_<performedBy serviceProvider="buyer"/> 牋_<implement> 牋牋_<export portType="tio:stockBuyer" operation="checkStocks"> 牋牋_<map sourceMessage="checkStocks" sourcePart="check" targetMessage="checkStocksOutput" targetPart="stockQuote"/> 牋牋_</export> 牋_</implement> _</activity> |
WSFL 实现引擎现在可获取全局模型,在整个 WSDL 生成过程中运行此全局模型并创建公共 Web 服务接口(WSDL portType)定义,如 清单 3所示。
<definitions> 牋牋 <message name="checkStocks"> 牋牋牋_<part name="check" element="tio:checkStocks" />_ 牋__lt;/message> 牋牋牋牋 牋牋 <message name="sellStocks"> 牋牋牋_<part name="order" element="tio:sellStocks" />_ 牋牋 </message> 牋牋牋牋 牋_<portType name="stockBuyer">_ 牋牋牋_ 牋牋牋牋 <operation name="checkStocks"> 牋牋牋牋牋 <input message="tns:checkStocks" /> 牋牋牋牋牋 <output message="tns:checkStocksOut" /> 牋牋牋牋 </operation> 牋牋牋_ 牋牋牋牋 <operation name="sellStocks"> 牋牋牋牋牋 <input message="tns:sellStocks" /> 牋牋牋牋牋 <output message="tns:sellConfirmation" /> 牋牋牋牋 </operation>_ 牋_</portType> </definitions> |
现在,为了解释一下刚才发生的事情,我将要后退一步。考虑一下 查看股票操作。实质上,为了执行这个活动,WSFL 引擎必须向一些位于网络外部的股票行情服务发出一个 Web 服务请求。但是,该引擎需要确切知道要进行这次调用,应怎样做以及做些什么。在 WSDL 术语中, 查看股票操作是一个请求—响应操作。使用 WSFL 全局模型中的 plug-link机制,您向引擎提供执行该操作的必要信息并将其绑回到正在执行的商业流程中。
那么如何将其绑回到递归组合中呢?WSFL 工作流中的每个活动都是由 Web 服务公开的操作执行。那些操作通过使用 WSDL 端口类型定义而被公开。WSFL 全局模型和 pluglink 允许您为商业流程的各部分建立 WSDL 端口类型定义。您可以将这两者链接在一起,这样一个流程中的活动就可以通过另一个流程的公共接口实现。 图 4显示一个递归组合流程,其中一个流程中的活动被绑定到另一个流程的公共接口。
图 4: 一个递归组合流程
递归组合提供一种将来自不同提供者的服务聚集到单个解决方案的方法。例如,一个服务提供者可能提供一个购买订单 Web 服务,它实际上是一个由许多不同的服务提供者(为完成诸如信用卡认证,物流等任务)提供的 Web 服务的集合体。从最终用户的角度来看,他/她看到的是购买订单服务,而不是这个服务背后所进行的其它事情。
将 WSFL 的动态选择使用哪个 Web 服务实现和服务提供者来执行工作流中给定的任何活动的能力与递归组合概念结合在一起将会为您提供更高级别的灵活性。这个过程与我在本专栏的上一部分中所描述的完全相同(请参阅 参考资料)。
从本质上来说,多个服务提供者可以用完全相同的公共接口实现两个完全不同的工作流。因为他们导出相同的 Web 服务操作集合,他们彼此之间可进行互操作。由于 WSFL 流模型链接到 Web 服务的公共接口(而不是该接口的特定实现),所以两个提供者都有涉足履行活动的能力。WSFL 引擎,以 WSFL 流模型的设计师提供的规则为基础,可在任何给定的情况下动态地确定使用哪个提供者。
通过被合理地利用,WSFL 会成为企业的整体 Web 服务战略的重要组件。毫无疑问,许多概念是相当复杂,在最好的情况下,设计一个成功的商业流程也会是一项复杂的任务。但是,有了适当数量的实践,适当的工具以及一些耐心,它所带来的好处将会超过其复杂性。
我写这一系列文章的目的只是为了向您介绍 WSFL。因此,我省去了许多细节问题,而其它还有一些细节被我完全忽略了。目的是为了帮助您对 WSFL 的基本概念有一个初步了解,而不是要您成为这方面的专家。我建议,如果您已经对 WSFL 的基本概念有了初步的了解,您可以阅读 WSFL 规范。学习这个规范,从头至尾彻底看一下这些概念,并花费一些时间练习将工作流放在一起。而且,和以前一样,如果您有什么看法和问题,请发消息给我。
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 参与本文的
讨论论坛。
- 请务必查阅本专栏的前 3 部分:
第 4 部分、
第 5 部分和
第 6 部分。
- 从 alphaWorks 下载
Web 服务流程管理功具包。
- 阅读 WSFL
规范
- 学习
SOAP、
WSDL和
UDDI
- 学习
WebSphere MQ及其工作流组件
James Snell 是 IBM 的 Software Group 中 Emerging Internet Technologies 小组的一员,在那里,他对发展中的 Web 服务技术的体系 结构和实现起着积极的作用。他是 O'Reilly & Associates 出版的 Programming Web Services with SOAP 一书的合著者之一。 您可以通过 jasnell@us.ibm.com 联系 James。