引言

 本系列文章介绍如何建模,详细说,是 Web 服务相关的架构,以及如何使用 IBM ? Rational? Software Architect(今后称为 Software Architect)在实际实现中实现这些模型。本系列着眼于以下主题:

  第一部分:建模并生成 XML Schema(参见参考资料 [1])。

  第二部分:建模并生成 WSDL。

  第三部分:将模式应用于 Web 服务工件的生成。

  本文建立在本系列第一部分中介绍的实例的基础之上。特别地,本文中的实例将使用第一篇文章所开发的模式(schema)。本文中所有的实例都已经用 Software Architect version 6.0.1 开发了,尽管下面所介绍的可下载的转换也应该用 Software Architect version 6.0.0.1。

  Web 服务定义建模

  本系列的第一篇文章回答了这样一个问题,为 Web 服务规范的细节建模是否比直接编辑用于获取服务细节的 WSDL 和 XML Schema 有价值。文章特别根据模型驱动开发(Model-Driven Development,MDD)方法的应用来回答的,如图 1 中的图表所示。

  图 1. Web 服务开发的 MDD 配置

Web 服务建模,第 2 部分: 建模并生成 WSDL

 本文的焦点是服务定义的建模,也就是,利用 WSDL 表述的服务规范的各个方面。在这方面,它关注服务提供和所需的操作、消息,和接口,一些您希望 UML 能够表述的内容。事实上,面向服务的某些元素用 UML 表述实际上比用 WS-* 系列规范表述要好。在寻找为面向服务的解决方案建模的方法过程中,我们不得不选定一些关于具体到面向服务的观点的设计方面和如何对它们建模的指导。在 SOA 建模 [2]中,CBDi Forum 清楚地说明了以下建模指导:

  模型 业务层服务

  模型基于协作的服务

  显式模式接口与实现的分离

  显式模式提供者与消费者的分离

 为了确保在模型中获得这些指导,IBM 开发了UML 2.0 Profile for Software Services [3](编制并发布于 IBM? developerWorks? 网站),并提供了向 Software Architect 的安装添加此概要文件 —— 以及模板模型和一些示例模型 —— 的功能的Software Architect 插件 [4]。此概要文件还可以附有一个可以添加到IBM? Rational Unified Process? (RUP?) [5] 中的附加指导集。它结合了明确地为服务规范 —— 作为 UML 接口 —— 建模,与提供者分离,以及与服务消费者分离的 UML 概要文件,和描述服务协作如何用于描述业务层服务的指导。

  一旦使用了此概要文件对服务建模,对于 UML 到 WSDL 的转换示例就可以用于生成 WSDL 源。很重要的是,认识到 Software Architect 转换本身不需要将概要文件应用到模型上,然而,这样做会使模型更加明确,并且所选择的概要文件元素提供转换所要求的建模风格。该概要文件应用于设计和实现模型。这些的真正区别倾向于模型中所获取的细节量,并且设计模型经常被细化成为实现模型,而不是一个完全分离的模型。

  安装 UML 到 WSDL 的转换

 在您开始之前,重要的是要注意,虽然 Software Architect 6.0.1 中包含了 UML 到 XSD 的转换(用在本系列第一篇文章中),但是 UML 到 WSDL 的转换还不是一个产品特性。然而,通过 Software Architect developerWorks RAS(可复用的资产规范)存储库,转换已经可用,作为一个示例。所以在研究管理第一篇文章中的购买订单文档的服务建模之前,您需要将转换安装到 Software Architect 中。

  创建一个连接

  要安装 UML 到 WSDL 的示例 —— 以及相应的 UML 到 XSD 的示例 —— 转换,您需要首先创建一个到 developerWorks RAS 存储库的连接。

  在 Window 菜单中,选择 Show View 然后选择 Other。

  在列表中展开 RAS 文件夹并打开 Asset Explorer 视图。

 如果您还没有到 RSA developerWorks RAS 存储库的连接,单击 Asset Explorer 视图中的 New Repository Connection 按钮。

  在结果向导中,首先选择 developerWorks Repository 项(图 2),然后接受连接的默认值(图 3)。

  图 2. 添加新存储库连接对话框

Web 服务建模,第 2 部分: 建模并生成 WSDL

  图 3. IBM Rational developerWorks 连接属性

Web 服务建模,第 2 部分: 建模并生成 WSDL

  现在,展开新连接,并展开分析文件夹,直到您看到两个示例连接,如图 4 中所示。

  现在,对于 UML to XSD Transform 和 UML to WSDL Transform,右键单击资产并选择Import,依照出现的对话框。 图 4. The IBM Rational 存储库

Web 服务建模,第 2 部分: 建模并生成 WSDL

 向工作区中添加示例

  一旦您完成了这些动作,两个转换就都加入到了示例库中(这些毕竟是示例,不是可以直接安装的特性或插件)。下一个步骤是向您的工作区中添加示例。虽然这可能看起来像额外的工作,但是它的确有一个重要的优点:两个转换都是由 Software Architect 团队自己开发的,并且它们是具有完整源程序形式的示例。事实上,示例 UML to XSD transform 是当前的 Software Architect 产品本身提供的较早的版本。

  在 Help 菜单中打开 Samples Gallery。

  您可以阅读每个示例的安装指导,此处应该显示出指导方针。更重要的是,您可以直接导入示例,如图 5 所示。

  图 5. Sample Gallery

Web 服务建模,第 2 部分: 建模并生成 WSDL

  既然您已经将它们导入,这些示例就作为插件工程包含到您当前的工作区中了,这时您还不可以直接执行这些转换。要使用这些转换,您必须启动运行时工作台,确保其配置中包含新的插件。一旦新的工作台正在运行,您就可以将现有的模型导入到其工作区中,或者创建新的模型。要确保您已经正确地安装了插件,右键单击模型的元素。您应该看到Transform 菜单中的一个列表,如图 6 所示。

  图 6. Transformation 菜单

Web 服务建模,第 2 部分: 建模并生成 WSDL

  如果是这样的情形,您就已经成功地安装了插件,并且您现在可以开始为服务建模了。

  订单处理示例

 您将在本文中开发的服务规范表示一个订单管理服务。这个实例接收、取消,并获得客户订单的状态,由本系列第一部分中所开发的订单方案所表示。此部分着重于服务本身的规范,即外部功能。软件服务的建模方法在 参考资料 [6] 中有所说明,所以这里将不包括理论,或 Software Architect 插件的安装。

  创建服务设计模型

  依照这些步骤开始创建新的模型。

  在 File 菜单中,选择 New -> Other.

  在结果对话框中,打开 Modeling 文件夹和 UML Model。

  一旦您进行了选择,您将看到模型细节对话框。

  在模板列表中选择 Service Design Model,并命名您的模型。在此实例中,模型称为 Order Management Service Design。

  当您创建了模型之后,打开模型根路径下名为 Model Overview Diagram 的图。您会看到模板所提供的默认模型架构。

  花一些时间来探究模型结构,尤其是 Reusable Design Elements 包,它包含了您一会儿将会利用的有用的建模结构。图 7 显示出结果模型根路径下的图。

  图 7. 初始的服务设计模型

Web 服务建模,第 2 部分: 建模并生成 WSDL

  复制方案模型

  不幸的是,您遇到的一个问题是,您在第一篇文章中所创建的方案模型不能直接复用到此练习中。这个问题是,为了在 WSDL 文件中生成方案,UML 到 WSDL 的转换使用了示例 UML to XSD transform(不是第一篇文章中的产品 UML to XSD transform)。这意味着您必须将方案包复制到服务模型中,并重新应用示例 XSD 概要文件。这不是理想的,并且稍微有些费时,而此处是这些步骤。

  打开第一篇文章中创建的方案模型。

  选择包 po-2、单击右键,并将其复制(Copy )到剪切板。

  在新服务设计模型的根路径下,单击右键并从剪切板上粘贴(Paste )。

  您需要去掉原有的概要文件,并选择 po-2 包,添加示例 XSD 概要文件(SampleXSDProfile)。

  您必须在 XSD 库模型中包含一个参考。要做到这点,右键单击新服务设计模型根路径,选择 Import Model Library,并选择 SampleXSDDataTypes 项。

  现在您必须将原型 <<schema>> 重新应用到包中,并设置正确的属性。

  回头查阅第一篇文章,您需要使用原型 $lt:$lt;simpleType$gt:$gt;、$lt:$lt;complexType$gt:$gt;,和 $lt:$lt;attribute$gt:$gt;。

  图 8 显示出所有这些工作的结果(注意,此图中的一些特性没有出现在原始的 PO 方案中:这些将在后面介绍)。

  图 8. 更新的 Purchase Order XSD 模型

Web 服务建模,第 2 部分: 建模并生成 WSDL

  就眼前来说,虽然这是一个难题,但是一旦 Software Architect 产品中包含了 UML 到 WSDL 的转换,您将不再需要这样做了。

  既然您已经重排了方案模型,您就应该确保您的服务可以复用方案元素。要做到这点,打开模型根路径下的原有图,并将您的方案包拖拽到图上。一旦完成了,从 Message 和 Services 视图中将两个包的导入关系添加到方案包中,如下面图 9 中所示。

  图 9. 包含方案包

Web 服务建模,第 2 部分: 建模并生成 WSDL

  服务规范建模

  Web 服务建模着重于服务的规范:也就是说,响应的操作、输入和输出的消息,以及客户端能够期望及信赖的服务行为。对于此实例,您选择使用一个 UML 概要文件及 [3] 和 [6]中介绍的特别技术集,第一个是服务规范。要帮助您创建一个新的服务规范,模型包含(如前面所提到的)可复用的设计元素集。依照这些步骤:

  打开此包。

  将 $I{service} 元素复制并粘贴到 Package Service 视图。

  右键单击新生成的元素并选择Find/Replace

  用 "OrderManagement" 代替文本 "${service}"

  这是一个开始点。以转换的观点,此服务规范映射到 WSDL 端口类型,此时这是一个无趣的端口,因为到目前为止还没有操作或消息。因此,要证明这一点,现在运行转换,并看到发生了什么。图 10 演示出:基本上,转换有一组验证规则,并且不会按没有操作的规范来执行。技术上,WSDL 确实允许没有操作的端口类型,但是很难想象为什么。此外,注意到第二个错误说转换的目标是无效的。这是由于这样一个事实,在 Software Architect 团队中,WSDL 文件属于 Web 工程,且在这种情况下,您已经创建了 OrderManagementEARWeb 工程。

  图 10. 转换对话框中的错误

Web 服务建模,第 2 部分: 建模并生成 WSDL

  回来完成您的服务规范,添加一些基本操作(列在下面的包 1 中)。您将注意到,它包含来自购买订单方案的元素,包括不是本系列第一篇文章中原有方案中一部分的 POID 元素。问题是,鉴别它的购买订单中没有元素。因此,虽然将购买订单作为 CancelOrder(或者甚至是 GetOrder 和 GetOrderStatus)的输入来发送,但是您如何将其关联到先前接受了的订单?因此,您需要向订单中加入标识符 —— 但是在哪个点上订单号被分配呢?

  表 1. 添加到服务规范中的基本操作

 

操作名称(Operation Name) 参数名称(Parameter Name) 参数类型(Parameter Type) 返回类型(Return Type)
AcceptOrder Order po-2::PurchaseOrder  
CancelOrder Order po-2::PurchaseOrder  
GetOrder OrderID po-2::POID po-2::PurchaseOrder
GetOrderStatus OrderID po-2::POID  

  您需要对方案本身做一些变更,将一个带有模式集合的名为 POID 的简单类型(出自于 NMTOKEN)添加到 POd{2}-d{8} 中。现在向原始的 apurchaseOrderType 添加一个属性,名为 purchaseOrderID、类型为 POID,原型为 ?attribute?,最后将多重性设置为 0..1(必须选择这项,以便客户端在提交之前不用必须输入一个值)。接下来,在 message 视图中,添加一个带有文字 Created、Accepting、Accepted、Canceling、Canceled、Picking、Shipping、Shipped、 Fulfilled 的枚举.还添加一个复杂类型 OrderStatus 和一个类型 OrderState 的属性状态。结果应该类似图 11 中所显示的那些内容。

  图 11. Schema 和 Message View 的附加内容

Web 服务建模,第 2 部分: 建模并生成 WSDL

  所有这些应该令您看到如图 12 中所示的服务规范。

  图 12. 目前为止的服务规范

Web 服务建模,第 2 部分: 建模并生成 WSDL

  现在您可以重新运行转换,用上面的服务规范作为源,用动态 Web 工程作为目标。转换的结果是清单 1 中所列出的 WSDL。注意到,方案定义已经被省略了,因为它与第一部分中所生成的方案一样。

  清单 1. 重新执行方案的结果

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="IOrderManagement"
 targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://tempuri.org/">
   ...
  </xsd:schema>
 </wsdl:types>
 <wsdl:message name="IOrderManagement_GetOrderStatusResponse">
  <wsdl:part name="ReturnResult" type="tns:OrderStatus" />
 </wsdl:message>
 <wsdl:message name="IOrderManagement_GetOrderResponse">
  <wsdl:part name="ReturnResult" type="tns:purchaseOrderType" />
 </wsdl:message>
 <wsdl:message name="IOrderManagement_GetOrderStatusRequest">
  <wsdl:part name="OrderID" type="tns:POID" />
 </wsdl:message>
 <wsdl:message name="IOrderManagement_CancelOrderRequest">
  <wsdl:part name="Order" type="tns:purchaseOrderType" />
 </wsdl:message>
 <wsdl:message name="IOrderManagement_AcceptOrderRequest">
  <wsdl:part name="Order" type="tns:purchaseOrderType" />
 </wsdl:message>
 <wsdl:message name="IOrderManagement_GetOrderRequest">
  <wsdl:part name="OrderID" type="tns:POID" />
 </wsdl:message>
 <wsdl:portType name="IOrderManagement">
  <wsdl:operation name="AcceptOrder">
   <wsdl:input message="tns:IOrderManagement_AcceptOrderRequest" />
  </wsdl:operation>
  <wsdl:operation name="CancelOrder">
   <wsdl:input message="tns:IOrderManagement_CancelOrderRequest" />
  </wsdl:operation>
  <wsdl:operation name="GetOrder">
   <wsdl:input message="tns:IOrderManagement_GetOrderRequest" />
   <wsdl:output message="tns:IOrderManagement_GetOrderResponse" />
  </wsdl:operation>
  <wsdl:operation name="GetOrderStatus">
   <wsdl:input message="tns:IOrderManagement_GetOrderStatusRequest" />
   <wsdl:output message="tns:IOrderManagement_GetOrderStatusResponse" />
  </wsdl:operation>
 </wsdl:portType>
</wsdl:definitions>

  值得在此提出的 Software Architect 的另一个方面是 Process Advisor —— Rational Unified Process 的一个视图 —— 您可以从Help 菜单访问到。Process Advisor 是上下文相关的:它使用您操作的模型元素作为环境提供模型使用的指导。在这种情况下,因为您正在处理服务规范,所以您可以看到,这已经出现在 Advisor 中了 —— 并且位于列表顶部。您还可以在图 13 中看到,Advisor 列出了来自过程指导的活动 —— Service Design —— 此次值得回顾。

  图 13. RSA Process Advisor

Web 服务建模,第 2 部分: 建模并生成 WSDL

  回调规范建模

  在订单管理服务的情况下,您想要订单的接受和取消为异步操作。要达到这个目的,您需要描述客户所实现的用于回调服务的规范。要生成回调规范,您要使用上面的相同过程,但将 ${service} 重名名为 OrderManagementCallback。并且,将表 2 中所示的操作添加到新规范中。

  表 2. 添加到回调规范的操作

 

操作名称(Operation)Name 输入名称(Input Name) 输入类型(Input Type) 结果类型(Result Type)
OrderAccepted Status OrderStatus N/A
OrderAcceptedFault Fault OrderManagementFault N/A
OrderCanceled Status OrderStatus N/A
OrderCanceledFault Fault OrderManagementFault N/A

  要完成这些操作,您需要一个新的消息类型,order management fault。它可以很简单地添加到模型中(在 Message View 中),如图 14 所示。

  图 14. OrderManagementFault 消息

Web 服务建模,第 2 部分: 建模并生成 WSDL

  服务提供者建模

  要对服务本身建模(也就是说,实现刚刚描述的服务规范的软件组件),您将使用 UML Components 和 Ports。如同以前的服务规范一样,您将使用其中一个可重用的设计元素,在这种情况下称为 ${complexservice}Provider。将此元素重命名为 OrderManagement,并且打开嵌套的元素。结果应该类似于图 15 中所示的内容。然而,在这种情况下,您已经对 IOrderManagement 和回调服务规范建模了,因此您可以删除模式所创建的这两个内容。

  图 15. 可重用的 Complex Service 提供者

Web 服务建模,第 2 部分: 建模并生成 WSDL

  要完成此模型,对您已经创建的规范重复创建实现和使用规范。这将产生一个完整的服务提供者,如图 16 所示(此图是开放的 OrderManagement Overview 模式的一部分)。

  图 16. 完整的服务提供者

Web 服务建模,第 2 部分: 建模并生成 WSDL

  从此图中,您可以看到所提供的和需要的接口,但是您没有看到的是模型还使用了 UML Ports 来表示服务(服务提供者所提供的特别的端点)。要将这些可视化,右键单击服务提供者并选择 Filters -> Show External View,而后您将看到类似图 17 中的视图。

  图 17. 服务提供者外部视图

Web 服务建模,第 2 部分: 建模并生成 WSDL

  如果您现在选择服务提供者并且执行 WSDL 转换,您将会在结果 XML 中发现更多细节。清单 2 说明了这一点,显示出,您现在有一个实现了端口类型的服务和一个 HTTP/SOAP 的默认绑定。这完成了 Web 服务规范的生成,且虽然您确实具有通过模型添加新绑定的灵活性,但是使用具有字面文档编码的 HTTP/SOAP 是最常见的。

  清单 2. 执行最新的 WSDL 转换的结果

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="OrderManagementProvider"
 targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
 ...
 <wsdl:binding name="IOrderManagementBinding"
  type="tns:IOrderManagement">
  <soap:binding style="document"
           transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="AcceptOrder">
   <soap:operation soapAction="http://tempuri.org/AcceptOrder/" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
  </wsdl:operation>
  <wsdl:operation name="CancelOrder">
   <soap:operation soapAction="http://tempuri.org/CancelOrder/" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
  </wsdl:operation>
  <wsdl:operation name="GetOrder">
   <soap:operation soapAction="http://tempuri.org/GetOrder/" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
  <wsdl:operation name="GetOrderStatus">
   <soap:operation soapAction="http://tempuri.org/GetOrderStatus/" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="OrderManagement">
  <wsdl:port name="IOrderManagementPort"
   binding="tns:IOrderManagementBinding">
   <soap:address location="http://tempuri.org/" />
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>

  生成 Java 实现

  在实现透视图中,下一个步骤是相当的简单:运行 new Web Service Wizard(File -> New -> Other -> Web Service)并选择 Skeleton Java bean Web Service 作为类型。向导将询问您 WSDL 的位置,您将需要一个配置了的服务器来运行工程(此实例使用 WebSphere v6.0 Server 本地运行)。这将创建一个服务实现框架,您可以用业务逻辑来完成。向导的开始页如图 18 所示。一旦您选择了类型、WSDL,和工程,您就可以按下 Finish (可以安全地忽略大多数高级设置)。

  图 18. Web Service 向导的首页

Web 服务建模,第 2 部分: 建模并生成 WSDL

  在本系列的下一个部分中,您将对服务应用模式。