理解 WSRF,第 2 部分:使用 WS-ResourceLifetime、WS-ServiceGroup 和 WS-BaseFaults
谁应该学习本教程?
本教程介绍 Web 服务资源框架(Web Services Resource Framework,WSRF)背后的概念。具体来说,解释了 WS-ServiceGroups 和 WS-BaseFaults 的概念,以及如何创建、使用和操纵它们。还解释了使用 WS-ResourceLifetime 进行的 WS-Resources 的即时销毁和预定销毁。
本教程针对这样一些用户,他们希望创建需要使用“有状态资源”、基于 Web 服务的应用程序。尽管该概念当前最常见的应用是网格服务,但是本教程中的概念也适用于任何需要“状态”概念的 Web 服务应用程序。
因为这是一个概念方面的教程,所以不需要实际的编程,但是熟悉诸如对象和属性这样的编程概念是有帮助的。但是,还是讨论了 Web 服务描述语言(Web Services Description Language,WSDL)文件的创建,所以对 XML 和 Web 服务的一般了解是有帮助的。在本系列的 第 1 部分 “理解 WSRF,第 1 部分:使用 WS-ResourceProperties”中,介绍了基本的 WSDL 概念。(参阅 参考资料,获得到有用的背景信息的其他链接。)
本系列的 第 1 部分“理解 WSRF,第 1 部分:使用 WS-ResourceProperties”,从总体上介绍了 Web 服务资源框架(Web Services Resource Framework,WSRF)。WSRF 提供一种标准方式,在 Web 服务的本质上“无状态的”环境中使用“有状态”资源。除了介绍 WS-Resource 的概念之外,第 1 部分还解释了,根据 WS-ResourceProperties 规范中建立的消息交换模式来操纵 WS-Resources。
本教程接着第 1 部分进行介绍,讨论了 WS-ResourceLifetime、WS-ServiceGroup 和 WS-BaseFaults 规范。在本教程中,我们将:
l 简要概述 WS-Resource 总体概念。
l 直接销毁 WS-Resources。
l 安排 WS-Resources 在稍后的时间终止。
l 创建 WS-ServiceGroup。
l 向 ServiceGroup 添加和删除 ServiceGroupEntries。
l 从 ServiceGroup 检索单个和多个 ServiceGroupEntries。
l 考查标准 BaseFault 的概念。
l 学习如何扩展 BaseFaults 以满足其他目的。
l 展示如何将所有这些任务放在一个与 WSRF 相关的 WSDL 文件中。
注意,WSRF 作为一种规范,定义了描述这些操作的 WSDL 文件的结构。该 WSDL 文件然后可以被任何语言的实现所使用。本教程描述 WSDL 文件的创建并展示产生的 SOAP 消息。
一定要明白,WSRF 规范只定义应该做什么,而不是应该如何做。这里描述的概念的实际实现留给了应用程序。在本系列的第 4 部分“理解 WSRF,第 4 部分:使用 Java Core WSRF 类”中,我们将讨论该实现,其中用到了 The Globus Alliance 提供的 Core Java WSRF 类。
第一节 概述 WS-Resource 总体概念
Web Services Resource Framework
当您有这样一个应用程序时,即它的各个参与者(比如服务器和客户机)在地理位置上是分散的,您通常会发现,某些形式的 Web 服务可以使它从一个地方获得另一个地方的消息更加容易。但是该解决方案的一个问题是,Web 服务在本质上是无状态的。这里没有持久连接,比如数据库客户机到数据库服务器的连接。请求时惟一可用的信息是作为该请求一部分的信息。
如果您只是请求阿尔伯克基的当前温度或者 IBM 的当前股票价格,那么这没有问题。但是当您构建企业应用程序或者计算网格时,这就成其为问题了。
并不是没有方法表示 Web 服务应用程序中的状态。有,实际上是有很多方法,而这就是问题的一部分。为了创建一种“标准”方法,The Globus Alliance 提出了 Web Services Resource Framework (WSRF),这是使用 Web 服务来操纵有状态资源的一种标准方法。
该组织的工作分为几个文档:
l Modeling Stateful Resources With Web Services:该文档解释 WS-Resources 的总体概念,并展示后续文档中的所有概念如何成为一体。
l WS-ResourceProperties:该文档解释如何定义和操纵 WS-Resource。
l WS-ResourceLifetime:该文档解释如何销毁 WS-Resource。
l WS-ServiceGroup:该文档解释如何创建 WS-Resources 的逻辑组,以及如何控制和操纵这些组。
l WS-BaseFault:该文档定义任何 WSRF 应用程序都必须实现的基本故障消息,以及如何扩展它以创建新的故障。
l WS-Notifications:这组文档解释如何使应用程序可以提供针对各种应用程序事件的发布-订阅功能。
本系列的 第 1 部分“理解 WSRF,第 1 部分:使用 WS-ResourceProperties”,介绍了前两项,为本教程打下了基础,本教程将讨论 WS-ResourceLifetime、WS-ServiceGroup 和 WS-BaseFault。本系列的第 3 部分“理解 WSRF,第 3 部分:使用 WS-Notifications”,介绍 WS-Notifications。此外,“理解 WSRF,第 4 部分:使用 Java Core WSRF 类”详细介绍了 Globus Core WSRF 类的使用,以实现第 1-3 部分中的思想。
WS-Resources
至此,最重要的概念是 WS-Resource 的思想。WS-Resource 是 Web 服务与有状态资源 的组合。有状态资源是任何即使您不与之交互也存在的东西,比如文件、数据库,或者我们例子中的人造卫星。
资源属性文档代表有状态资源。考虑我们的人造卫星的资源属性文档:
<satProp:GenericSatelliteProperties
xmlns:satProp="http://example.com/satellite"
xmlns:counterProp="http://example.com/satellite/CounterSatelliteProperties">
<satProp:latitude>30.3</satProp:latitude>
<satProp:longitude>223.2</satProp:latitude>
<satProp:altitude>47700</satProp:altitude>
<satProp:pitch>49</satProp:pitch>
<satProp:yaw>0</satProp:yaw>
<satProp:roll>32</satProp:roll>
<satProp:focalLength>
21999992
</satProp:focalLength>
<satProp:currentView>
http://example.com/satellite/2239992333.zip
</satProp:currentView>
<counterProp:currentCount>
92828
</counterProp:currentCount>
</satProp:GenericSatelliteProperties>
Web 服务描述语言(Web Services Description Language,WSDL)文件描述 Web 服务。为了将它们“钩”在一起形成一个 WS-Resource,我们将从 portType 引用资源属性文档类型,如下所示:
<portType name="SatellitePortType"
wsrp:ResourceProperties="tns:GenericSatelliteProperties">
...
</portType>
一旦我们创建了 WS-Resource 类型,WSRF 就定义了一种使用它的方式。
处理 WS-Resources
我们定义了 WS-Resource 之后,可以对它做些什么呢?哦,WSRF 定义了标准消息,比如 GetResourceProperty 和SetResourceProperty,使我们可以处理对象。例如,我们曾经通过改变代表人造卫星和 Web 服务的 WS-Resource 的 altitude 属性,指示系统去更改人造卫星轨道的高度。
为了做到这一点,我们使用了一个EndpointReference,如 WS-Addressing 规范中所定义的。端点引用包括 Web 服务的 URI,以及其他信息,比如应答应该去往哪里。特别对 WS-Resources 有用的是能够包含附加的信息,以识别特定的 WS-Resource。
这就是 WSRF 的本质。您创建 WS-Resources,并通过属性来操纵它们。例如,在下一节中,我们来看一下通过操纵TerminationTime属性终止WS-Resources。
第二节 WS-ResourceLifetime 介绍
销毁 WS-Resource
刚刚用一整个教程解释了如何创建 WS-Resources,现在又来销毁它们似乎有点傻,但是这两个过程都是自然生命周期的一部分。WS-Resources 在请求时诞生,在不再需要时死亡。
这就是说,如果它们被正确地建立和使用,我们到目前为止创建的所有 WS-Resources 都可以利用 Destroy 消息直接销毁,正如您将在销毁 WS-Resource 一节中看到的。在这种情况下,客户机发送“destroy”消息并等待听到指令已经执行的消息。
但是,有时候这并不是我们所需要的。也许,我们只想要一个资源存在一段指定的时间,而不管我们是否还与系统连接。或许,我们只想要在一会不使用 WS-Resource 时就让它“超时”。
两种情况 — 即时销毁和预定销毁 —— 都可以用 WS-ResourceLifetime 规范中的技术来处理。(注意,“即时销毁和预定销毁”也就是 Globus 术语中的“显式和软件状态”生存期管理。)
在每一种情况都要明白,只有 WS-Resource — 有状态资源和 Web 服务的关联 — 被销毁。资源本身和 Web 服务都没有受到影响。
我们来看一下它是如何工作的。
创建 WS-Resource
在继续之前,我们需要一些可以销毁的东西。现在暂时把刚才的话题搁在一边,先来谈论一下 WS-Resource。
正如我们在 第 1 部分 中学到的,我们可以发送“create”消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<createSatellite xmlns="http://example.com/satellite"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
结果是一个 SOAP 消息,其中包含对操作创建的 WS-Resource 的端点引用:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<wsa:EndpointReference
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address> http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
该端点引用惟一地识别正在谈论的 WS-Resource,所以我们可以使用它来销毁该 WS-Resource。
销毁 WS-Resource
当我们准备销毁 WS-Resource 时,可以使用它的端点引用来创建 SOAP 请求:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/Destroy
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrl:Destroy />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
假设一切正常,我们会收到确认消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/DestroyResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrl:DestroyResponse />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
这似乎不怎么像确认消息,但是只要收到它,就可以知道一切正常。如果不是一切正常,就会得到 WSRF 故障:WS-ResourceLifetime 中所讨论的一条 fault 消息。如果在 WS-Resource 销毁后还试图访问它,也会得到故障消息。
我们也可以安排 WS-Resource 在以后销毁。
WS-Resource 的预定销毁
我们并不总是想要当场销毁 WS-Resource。在有些情况下,我们只是想要保持 WS-Resource 活跃一段特定的时间,然后再让它销毁。为了做到这一点,我们需要给 WS-Resource 附加一个 TerminationTime 属性,这意味着将它添加到资源属性文档。对于我们的人造卫星,意味着类似下面的这些东西:
<satProp:GenericSatelliteProperties
xmlns:satProp="http://example.com/satellite"
xmlns:counterProp="http://example.com/satellite/CounterSatelliteProperties"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<satProp:latitude>30.3</satProp:latitude>
<satProp:longitude>223.2</satProp:latitude>
<satProp:altitude>47700</satProp:altitude>
<satProp:pitch>49</satProp:pitch>
<satProp:yaw>0</satProp:yaw>
<satProp:roll>32</satProp:roll>
<satProp:focalLength>
21999992
</satProp:focalLength>
<satProp:currentView>
http://example.com/satellite/2239992333.zip
</satProp:currentView>
<counterProp:currentCount>
92828
</counterProp:currentCount>
<wsrl:TerminationTime>
2005-12-31T12:00:00
</wsrl:TerminationTime>
<wsrl:CurrentTime>2005-2-15T03:24:57</CurrentTime>
</satProp:GenericSatelliteProperties>
如果像本例中一样,没有指定时区,就会假设是格林威治标准时间。
注意,除了 TerminationTime,我们还添加了 CurrentTime。该属性使我们不必同步时钟,下面您就会看到。
获得 CurrentTime 和 TerminationTime
由于不同系统上的客户机,因而潜在地存在时钟同步的严重问题。例如,假设我们想要指定刚才创建的人造卫星 WS-Resource 应该在 4 小时后终止。选择一个相对于客户机的时间将会成为问题,因为在预定销毁情况下,实际上是由服务器销毁引用的。
幸运的是,WS-Resource 带有自己的“当前时间”。因为它是资源属性文档的一部分,所以我们可以像请求任何其他属性一样请求它:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetMultipleResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetMultipleResourceProperties>
<wsrp:ResourceProperty>wsrl:CurrentTime</wsrp:ResourceProperty>
<wsrp:ResourceProperty>wsrl:TerminationTime</wsrp:ResourceProperty>
</wsrp:GetMultipleResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在本例中,我们请求了 CurrentTime 和 TerminationTime,所以响应中包含了它们俩:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-Resour
ceProperties/GetMutlipleResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetMultipleResourcePropertiesResponse>
<wsrl:CurrentTime>2005-2-15T03:24:57</wsrl:CurrentTime>
<wsrl:TerminationTime>2005-2-15T03:30:00</wsrl:TerminationTime>
</wsrp:GetMultipleResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在应用程序中,然后我们可以使用 CurrentTime 来确定和设置新的 TerminationTime。
注意,尽管我们可以像请求任何其他资源属性一样请求 CurrentTime 和 TerminationTime,但是不能像设置任何其他资源属性一样设置它们。CurrentTime 是只读的,而 TerminationTime 必须使用我们下面将会看到的消息来设置。
设置新的 TerminationTime
一旦为 TerminationTime 确定了适当的值,我们就可以发送 SetTerminationTime 消息了:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTime
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrl:SetTerminationTime>
<wsrl:RequestedTerminationTime>
2005-2-15T07:24:00
</wsrl:RequestedTerminationTime>
</wsrl:SetTerminationTime>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
注意,我们不是通过直接操纵 TerminationTime 属性来设置时间的。这是因为我们需要系统实施它自己的任何一个时间相关规则,比如,不缩短资源的生存期,或者不扩展它超过某个特定的点。
响应消息包含新的 TerminationTime 和 CurrentTime:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTimeResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrl:SetTerminationTimeResponse>
<wsrl:NewTerminationTime>2005-2-15T07:24:00</wsrl:NewTerminationTime>
<wsrl:CurrentTime>2005-2-15T03:25:08</wsrl:CurrentTime>
</wsrl:SetTerminationTimeResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
除非应用程序本身具有设置时间的特定规则,否则没有任何特殊的约束。您甚至可以将 TerminationTime 设置为过去的值,这与发送 Destroy 消息的效果是一样的。
现在,我们需要将该信息添加到 WSDL 文件,以便这些功能可以从 Web 服务可用。
附加信息
当然,所有这些消息都必须编排到 WSDL 文件中,该文件描述了实际的Web服务。从我们在第 1 部分中创建的文件(您可以从 参考资料 下载一个副本)开始,我们可以添加以下信息,用于管理 WS-Resource 生存期。下面从一些必要的信息开始:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
xmlns:wsrlwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
location="WS-ResourceLifetime.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace= "http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
schemaLocation="WS-ResourceLifetime.xsd" />
<xsd:element name="createSatellite">
<xsd:complexType/>
</xsd:element>
...
WS-ResourceLifetime.wsdl 文件包含诸如 Destroy 和 SetTerminationTime 之类消息的定义,而 WS-ResourceLifetime.xsd 文件则包含 CurrentTime 和 TerminationTime 元素的模式定义,所以我们可以简单地引用它们。
资源属性文档
为了安排资源在以后终止,我们需要确保 CurrentTime 和 TerminationTime 属性是资源属性文档的一部分,所以我们需要将它们包含在 WSDL 文件中的定义中:
...
<xsd:element name="roll" type="xsd:float" />
<xsd:element name="focalLength" type="xsd:float" />
<xsd:element name="currentView" type="xsd:string" />
<xsd:element name="GenericSatelliteProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="latitude" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="longitude" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="altitude" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="pitch" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="yaw" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="roll" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="focalLength" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="currentView" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="wsrl:CurrentTime" minOccurs="1" maxOccurs="1" />
<xsd:element ref="wsrl:TerminationTime" minOccurs="1" maxOccurs="1" />
<xsd:any/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
...
现在我们需要做的就是定义 operation 并将它们添加到 binding。
操作和绑定
我们使用的各种消息,比如 DestroyResponse 和 SetTerminationTimeRequest,都定义在 WS-ResourceLifetime.wsdl 文件中,所以我们只需要引用它们就是了:
...
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element="tns:createSatelliteResponse"/>
</message>
<portType name="SatellitePortType" wsrp:ResourceProperties="tns:GenericSatelliteProperties">
...
<operation name="removeTarget">
<input message="wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty"/>
<output message="wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse"/>
</operation>
<operation name="destroySatellite">
<input message="wsrlwsdl:DestroyRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/Destroy"/>
<output message="wsrlwsdl:DestroyResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/DestroyResponse"/>
</operation>
<operation name="renewSatellite">
<input message="wsrlwsdl:SetTerminationTimeRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTime"/>
<output message="wsrlwsdl:SetTerminationTimeResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTimeResponse"/>
</operation>
</portType>
<binding name="SatelliteSoapBinding" type="tns:SatellitePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
...
<operation name="removeTarget">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="destroySatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="renewSatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding="tns:SatelliteSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
</service>
</definitions>
现在我们已经准备好处理资源的即时销毁或预定销毁了。一个可以找到方便功能的地方是在 WS-ServiceGroups 的管理中。
WS-ServiceGroup
我们将要实现的目标
在本节中,我们来看一下 ServiceGroup 的概念,它使得我们可以根据各种规则,将 Web 服务和 WS-Resources 成组在一起。
一开始,我们将创建一个新的 ServiceGroup,并定义它的成员规则。然后创建一个新的 WS-Resource 并将它添加到新的 ServiceGroup。从这里,我们将了解两种用于查找 ServiceGroup 的成员的方法。
在 WS-ServiceGroups 和 WSDL 文件 一节中,我们将了解一些稍微复杂的方法,将这些操作集成到 WSDL 文件中。
我们一开始来看一下 ServiceGroup 到底是什么。
ServiceGroups
一旦应用程序变得足够大而复杂,就应该将资源成组在一起。您可能想要基于用户或服务角色来限制访问,或者您想要提供可用服务的注册表。
不管是什么原因,WSRF 都通过使用 ServiceGroup 来处理问题。ServiceGroup 是一个 WS-Resource,它将指向其他 WS-Resources 和纯 Web 服务的指针成组在一起。
我们再来回顾一下。
ServiceGroup 是一个 WS-Resource。这对于我们来说意味着几件事情。首先,它意味着 ServiceGroup 是 Web 服务与有状态资源的组合。在这种情况下,有状态资源是 ServiceGroup 包含的项的组合,因为它是 WS-Resource,所以这个项组合是由 ServiceGroup 的资源属性文档表示的。
它还意味着 ServiceGroup 是由端点引用识别的,我们可以通过后者来引用前者,并且我们可以在 ServiceGroup 上执行可以在任何其他 WS-Resource 上执行的相同操作,比如创建或销毁它,或者访问它的属性。
创建 ServiceGroup
使用 ServiceGroup 的第一步是创建它。因为 ServiceGroup 就是一个 WS-Resource,所以我们就像创建其他 WS-Resource 一样用一个 Create 消息来创建它:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<createSatGroup xmlns="http://example.com/satellite"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
跟前面一样,响应包含对新 WS-Resource 的端点引用:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<createSatGroupResponse xmlns="http://example.com/satellite">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>
http://example.com/satellite
</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</createSatGroupResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
好的,那么我们真正具有了什么呢?到目前为止,我们总是从定义 WS-Resource 的资源属性文档开始,但是我们在这里不是这样做的,因为它已经为我们定义好了,正如您下面就会看到的。
ServiceGroup ResourceProperties
ServiceGroup 的资源属性文档定义在 WS-ServiceGroup.wsdl 文件中,所以我们无须定义它。实际上,实际的文档类似于下面这样:
<wssg:ServiceGroupRP>
<wssg:MembershipContentRule MemberInterface="sat:AuditedSatellitePortType" />
<wssg:MembershipContentRule MemberInterface="sat:CounterPortType"
ContentElements="sat:audited" />
<wssg:MembershipContentRule ContentElements="sat:approvedBy" />
<wssg:Entry>...</wssg:Entry>
<wssg:Entry>...</wssg:Entry>
</wssg:ServiceGroupRP>
我们马上就会在 ServiceGroup Entry 元素 一节中谈论 Entry 元素。我们将从 MembershipContentRule 元素开始。这些元素定义 ServiceGroupEntry 在可以被添加到 ServiceGroup 之前必须满足的条件。
MemberInterface 属性列出必须由 ServiceGroup 中的任何服务实现的 portType。记住,portType 定义在服务的 WSDL 文件。我们将在 实现多个 portTypes 一节中详细了解它们的实现。
第二个属性,即 ContentElements,指定必须包含在 ServiceGroupEntry 的 Content 元素中的元素。我们在了解 ServiceGroupEntry 时再来详细了解这一点。
ServiceGroupEntries
ServiceGroupEntry 也是一个 WS-Resource,所以它也具有定义其状态的资源属性文档和识别它的 WS-Address。它定义 ServiceGroup 和服务之间的关系,并包含可选内容,所以资源属性文档类似于下面这样:
<wssg:ServiceGroupEntryRP>
<wssg:ServiceGroupEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEPR>
<wssg:MemberEPR>
<wsa:EndpointReference xmlns:wsa=http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:ServiceGroupEntryRP>
ServiceGroupEPR 是对 ServiceGroup 的端点引用,而 MemberEPR 引用实际的 Web 服务或 WS-Resource。ServiceGroupEntry 也引用实际的 Web 服务或 WS-Resource。
Content 元素是可以包含在 ServiceGroupEntry 中的附加信息。在本例中,我们添加了一个批准代码,指出服务即使没有实现 CounterPortType 或 AuditedSatellitePortType portTypes 也可以被添加到组中。
ServiceGroup Entry 元素
现在我们可以回过头来看 ServiceGroup 的资源属性文档中的 Entry 元素。在本例中,每一项识别 ServiceGroupEntry 资源并提供到实际服务的指针,所以 ServiceGroup 的资源属性文档类似于下面这样:
<wssg:ServiceGroupRP>
<wssg:MembershipContentRule MemberInterface="sat:AuditedSatellitePortType" />
<wssg:MembershipContentRule MemberInterface="sat:CounterPortType"
ContentElements="sat:audited" />
<wssg:MembershipContentRule ContentElements="sat:approvedBy" />
<wssg:Entry>
<wssg:ServiceGroupEntryEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY28981</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEntryEPR>
<wssg:MemberServiceEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberServiceEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Entry>
<wssg:Entry>
<wssg:ServiceGroupEntryEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY29003</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEntryEPR>
<wssg:MemberServiceEPR>
<wsa:EndpointReference xmlns:wsa=http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT8557</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberServiceEPR>
<wssg:Content>
<sat:approvedBy> BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Entry>
</wssg:ServiceGroupRP>
ServiceGroupEntryEPR 指向我们在前一节(ServiceGroupEntries)中看到的 ServiceGroupEntry 对象,而 MemberServiceEPR指向添加到ServiceGroup的实际服务或WS-Resource。Content 元素展示 ServiceGroupEntry 中的 Content 元素。
然而,回到我们的例子,我们还只创建了这个 ServiceGroup,所以需要添加所有这些信息,下面我们从 MembershipContentRules 开始。
添加 MembershipContentRules
一旦创建了 ServiceGroup,我们就可以添加一个或多个 MembershipContentRule。因为它们是 ServiceGroup 的资源属性的一部分,所以我们利用 Insert 消息来添加:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wssg=""http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/satellite</wsa:To>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourceProperties xmlns:satProp="http://example.com/satellite">
<wsrp:Insert>
<wssg:MembershipContentRule MemberInterface="sat:AuditedSatellitePortType" />
</wsrp:Insert>
<wsrp:Insert>
<wssg:MembershipContentRule MemberInterface="sat:CounterPortType"
ContentElements="sat:audited" />
</wsrp:Insert>
<wsrp:Insert>
<wssg:MembershipContentRule ContentElements="sat:approvedBy" />
</wsrp:Insert>
</wsrp:SetResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
这里,我们把消息发送到了 ServiceGroup WS-Resource,并添加了匹配我们在 ServiceGroup ResourceProperties 一节中看到过的规则的属性。服务器返回一个确认更改的 SetResourcePropertiesResponse 消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/myClient</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourcePropertiesResponse></wsrp:SetResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
现在 ServiceGroup 本身已经准备就绪,我们可以开始添加项了。
添加新的项
为了向 ServiceGroup 添加项,我们需要对服务或 WS-Resource 的端点引用。还需要任何相关 Content。例如,我们可以将人造卫星 SAT8557 添加到 ServiceGroup:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wssg=""http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>http://docs.oasis-open.org/wsrf/2004/06/WS-ServiceGroup/Add</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/satellite</wsa:To>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wssg:Add>
<wssg:MemberEPR>
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT8557</sat:SatelliteId>
</wsa:ReferenceProperties>
</wssg:MemberEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
这里,我们指定了对服务的端点引用和任何所需的 Content。您也可以添加 InitialTerminationTime 元素,为生成的 ServiceGroupEntry 指定一个 TerminationTime。
在响应中,服务器发送对新 ServiceGroupEntry 的端点引用:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>http://docs.oasis-open.org/wsrf/2004/06/WS-ServiceGroup/AddResponse</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/myClient</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:AddResponse>
</wsa:EndpointReference>
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY29003</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wsrp:AddResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我们可以添加任意多的资源,只要它们不违反任意一个 MembershipContentRule。
检索 ServiceGroupEntry
至此,我们已经向 ServiceGroup 添加了 MembershipContentRule 和一个或多个项,所以资源属性文档跟 ServiceGroup Entry 元素 一节中的类似。现在我们来看检索信息。
例如,假设我们想要计数恒星的个数。ServiceGroup 包含大量我们可以使用的 WS-Resources。如果我们只需要其中之一,最简单的方法是使用 GetResourceProperty 消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wssg="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetResourceProperty
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/satellite</wsa:To>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourceProperty>wssg:Entry</wsrp:GetResourceProperty>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
响应包含一个 Entry 元素:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetResourcePropertyResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/myClient</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourcePropertyResponse>
<wssg:Entry>
<wssg:ServiceGroupEntryEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY28981</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEntryEPR>
<wssg:MemberServiceEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberServiceEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Entry>
</wsrp:GetResourcePropertyResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
该元素包含 MemberServiceEPR,而后者是对服务或 WS-Resource 的端点引用。一旦有了该引用,我们就可以像第1部分中那样使用服务或 WS-Resource 了。不管是从CreateResponse还是 GetResourcePropertyResponse 收到端点引用,之间没有什么区别。我们有了一个端点引用,所以可以使用它所代表的服务或 WS-Resource 了。
检索多个项
在 第 1 部分 中,我们使用了 QueryResourceProperties 消息来查询属性,但是我们也可以使用它来检索多个具有相同名称的属性。例如,我们可以检索 ServiceGroup 的所有 Entry 元素:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wssg="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/QueryResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/satellite</wsa:To>
<sat:SatGroupId>SATGRP3</sat:SatGroupId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:QueryResourceProperties>
<wsrp:QueryExpression Dialect="http://www.w3.org/TR/1999/REC-xpath-19991116">
/*/Entry
</wsrp:QueryExpression>
</wsrp:QueryResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
响应包含所有的 Entry 属性:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wssg="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/QueryResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/myClient</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourcePropertyResponse>
<wssg:Entry>
<wssg:ServiceGroupEntryEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY28981</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEntryEPR>
<wssg:MemberServiceEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberServiceEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Entry>
<wssg:Entry>
<wssg:ServiceGroupEntryEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatGroupEntryId>SATGRPENTRY29003</sat:SatGroupEntryId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:ServiceGroupEntryEPR>
<wssg:MemberServiceEPR>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT8557</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</wssg:MemberServiceEPR>
<wssg:Content>
<sat:approvedBy>BossManBing</sat:approvedBy>
</wssg:Content>
</wssg:Entry>
</wsrp:QueryResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我们也可以使用 XPath 表达式来限制检索的 Entry。例如,我们可以只检索具有 audited 元素的项。一旦有了响应,我们可以使用客户机应用程序来查找每一个 Entry 并使用由每个 MemberServiceEPR 表示的服务。
删除 ServiceGroupEntries 和 ServiceGroups
我们已经向 ServiceGroup 添加了一个服务,但是该如何删除它呢?答案在于 ServiceGroupEntry 以及它是 WS-Resource 这样一个事实。要从 ServiceGroup 删除服务,只要检索对 ServiceGroupEntry 的端点引用,并使用该引用来发送 Destroy 消息即可。在这种情况下,您只是破坏了资源和组之间的链接。如果您销毁资源,就应该也销毁指向该资源的任何 ServiceGroupEntry 对象。
类似地,如果您销毁 ServiceGroup,就应该也销毁它包含的所有 ServiceGroupEntry 资源。
现在我们来看所有这些如何转换成一个 WSDL 文件。
我们可以对 WSDL 文件做什么 第 1 页(共6 页)
您已经知道,WSDL 文件描述 Web 服务。到目前为止,我们已经使用了 WSDL 文件来定义 message,以及使用其他 WSDL 文件中定义的 message。我们然后采用这些 message,创建 operation 和 portType,然后采用 portType 并使用它们作为 binding 的基础,在 service 中创建 port(见图 1)。
图 1. 到目前为止的过程
在本节中,我们将来简化这个过程。首先,我们将添加创建 ServiceGroup 的功能。从这里,我们将添加 WS-ServiceGroup 一节中使用到的其他功能。
创建 ServiceGroup
第一步是添加创建 ServiceGroup WS-Resource 的能力。做这件事的方式与我们前面创建人造卫星 WS-Resources 时的方式非常相似,只是不必定义资源属性文档,因为它已经定义在 WS-ResourceProperties.wsdl 中了:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
xmlns:wsrlwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
xmlns:wssg="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd"
xmlns:wssgwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
location="WS-ResourceLifetime.wsdl" />
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl"
location="WS-ServiceGroup.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
schemaLocation="WS-ResourceLifetime.xsd" />
<xsd:element name="createSatellite">
<xsd:complexType/>
</xsd:element>
<xsd:element name="createSatelliteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="createSatGroup">
<xsd:complexType/>
</xsd:element>
<xsd:element name="createSatGroupResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="latitude" type="xsd:float" />
<xsd:element name="longitude" type="xsd:float" />
...
</xsd:schema>
</types>
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element="tns:createSatelliteResponse"/>
</message>
<message name="CreateSatGroupRequest">
<part name="request" element="tns:createSatGroup"/>
</message>
<message name="CreateSatGroupResponse">
<part name="response" element="tns:createSatGroupResponse"/>
</message>
<portType name="SatGroupPortType" wsrp:ResourceProperties="wssg:ServiceGroupRP">
<operation name="createSatGroup">
<input message="tns:CreateSatGroupRequest" wsa:Action="http://example.com/CreateSatGroup" />
<output message="tns:CreateSatGroupResponse"
wsa:Action="http://example.com/CreateSatGroupResponse" />
</operation>
</portType>
<portType name="SatellitePortType" wsrp:ResourceProperties="tns:GenericSatelliteProperties">
<operation name="createSatellite">
...
现在,所有的事情都已经很熟悉了;我们创建了消息和一个引用 wssg:ServiceGroup 资源属性文档类型的 portType。但是我们如何将它添加到一个已经使用 GenericSatelliteProperties 类型的服务呢?
实现多个 portTypes
如果您还不熟悉 WSDL 文件,可能会有这样的疑问:当服务已经指向 GenericSatelliteProperties 类型时,我们如何指向 ServiceGroup 中的服务?答案在于 portType 的功能。它不只是一个定义,而且是一种类型的接口。毕竟,它只是定义了操作(或功能)和签名(或者操作期望的数据)。实际的实现依赖于 binding。
一直坚持下去,我们可以为新的 portType 添加 binding,然后再通过添加附加的 port 将它添加到服务:
...
<operation name="renewSatellite">
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
</binding>
<binding name="SatGroupSoapBinding" type="tns:SatGroupPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="createSatGroup">
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding="tns:SatelliteSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
<port name="SatGroupPort" binding="tns:SatGroupSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
</service>
</definitions>
用这种方法,我们就实现了 portType。到目前为止,该服务实现了 SatellitePortType 和 SatGroupPortType portType。
我们可以使用该能力来容易地添加规范中的其他功能。但是首先,我们将添加向 ServiceGroup 添加资源属性的能力。
向 ServiceGroup 添加属性
添加向ServiceGroup添加属性的能力很直观,因为SetResourcePropertyRequest和 SetResourcePropertyResponse message都已经定义在 WS-ResourceProperties.wsdl 中,所以可以简单地引用它们:
...
<message name="CreateSatGroupResponse">
<part name="response" element="tns:createSatGroupResponse"/>
</message>
<portType name="SatGroupPortType" wsrp:ResourceProperties="wssg:ServiceGroupRP">
<operation name="createSatGroup">
<input message="tns:CreateSatGroupRequest" wsa:Action="http://example.com/CreateSatGroup" />
<output message="tns:CreateSatGroupResponse"
wsa:Action="http://example.com/CreateSatGroupResponse" />
</operation>
<operation name="addMemberContentRules">
<input message="wsrpwsdl:SetResourcePropertyRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty" />
<output message="wsrpwsdl:SetResourcePropertyResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse"/>
</operation>
</portType>
...
<binding name="SatGroupSoapBinding" type="tns:SatGroupPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="addMemberContentRules">
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
<operation name="createSatGroup">
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
</binding>
...
我们有了一个作用在 ServiceGroup 上的 portType 和定义适当消息的 WS-ResourceProperties.wsdl,所以我们只需要创建 operation 并在 binding 中实现它们。
检索 ServiceGroup 属性
检索 ServiceGroup 的资源属性更加容易,因为 WS-ServiceGroups.wsdl 不仅定义了消息,还定义了 portType 和 operations。这意味着我们需要做的就是为服务创建一个绑定和一个新的端口,就如我们到目前为止所做的:
... </operation>
</binding>
<binding name="ServiceGroupSoapBinding" type="wssg:ServiceGroup">
<operation name="GetResourceProperty">
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding="tns:SatelliteSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
<port name="SatGroupPort" binding="tns:SatGroupSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
<port name="ServiceGroupPort" binding="tns:ServiceGroupSoapBinding">
<soap:address
location="http://example.com/satellite"/>
</port>
</service>
</definitions>
我们可以从头到尾经历这同一过程,以添加 ServiceGroupEntry 和 ServiceGroupRegistration portType,后者包含我们用于创建新 ServiceGroupEntry 的 Add 操作。(下面我们会看到完整的 WSDL 文件。)
但是使用这些预定义 portType 有一个附加的优点。即您将在下一节 WS-BaseFaults 中看到的简化的故障处理。
最终的 WSDL 文件
下面是最终的 WSDL 文件:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
xmlns:wsrl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
xmlns:wsrlwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
xmlns:wssg="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd"
xmlns:wssgwsdl="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import
namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<wsdl:import
namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
location="WS-ResourceLifetime.wsdl" />
<wsdl:import
namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl"
location="WS-ServiceGroup.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:import
namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
schemaLocation="WS-ResourceLifetime.xsd" />
<xsd:element name="createSatellite">
<xsd:complexType />
</xsd:element>
<xsd:element name="createSatelliteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="createSatGroup">
<xsd:complexType />
</xsd:element>
<xsd:element name="createSatGroupResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="latitude" type="xsd:float" />
<xsd:element name="longitude" type="xsd:float" />
<xsd:element name="altitude" type="xsd:float" />
<xsd:element name="pitch" type="xsd:float" />
<xsd:element name="yaw" type="xsd:float" />
<xsd:element name="roll" type="xsd:float" />
<xsd:element name="focalLength" type="xsd:float" />
<xsd:element name="currentView" type="xsd:string" />
<xsd:element name="GenericSatelliteProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="latitude" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="longitude" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="altitude" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="pitch" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="yaw" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="roll" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="focalLength" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="currentView" minOccurs="1"
maxOccurs="1" />
<xsd:element ref="wsrl:CurrentTime"
minOccurs="1" maxOccurs="1" />
<xsd:element ref="wsrl:TerminationTime"
minOccurs="1" maxOccurs="1" />
<xsd:any />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite" />
</message>
<message name="CreateSatelliteResponse">
<part name="response" element="tns:createSatelliteResponse" />
</message>
<message name="CreateSatGroupRequest">
<part name="request" element="tns:createSatGroup" />
</message>
<message name="CreateSatGroupResponse">
<part name="response" element="tns:createSatGroupResponse" />
</message>
<portType name="SatGroupPortType"
wsrp:ResourceProperties="wssg:ServiceGroupRP">
<operation name="createSatGroup">
<input message="tns:CreateSatGroupRequest"
wsa:Action="http://example.com/CreateSatGroup" />
<output message="tns:CreateSatGroupResponse"
wsa:Action="http://example.com/CreateSatGroupResponse" />
</operation>
<operation name="addMemberContentRules">
<input message="wsrpwsdl:SetResourcePropertyRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty" />
<output message="wsrpwsdl:SetResourcePropertyResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse" />
</operation>
</portType>
<portType name="SatellitePortType" wsrp:ResourceProperties="tns:GenericSatelliteProperties">
<operation name="createSatellite">
<input message="tns:CreateSatelliteRequest"
wsa:Action="http://example.com/CreateSatellite" />
<output message="tns:CreateSatelliteResponse"
wsa:Action="http://example.com/CreateSatelliteResponse" />
</operation>
<operation name="getAltitude">
<input message="wsrpwsdl:GetResourcePropertyRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetResourceProperty" />
<output message="wsrpwsdl:GetResourcePropertyResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetResourcePropertyResponse" />
</operation>
<operation name="getOrientation">
<input message="wsrpwsdl:GetMultipleResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetMultipleResourceProperties" />
<output message="wsrpwsdl:GetMultipleResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetMultipleResourcePropertiesResponse" />
</operation>
<operation name="checkOrientation">
<input message="wsrpwsdl:QueryResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/QueryResourceProperties" />
<output message="wsrpwsdl:QueryResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/QueryResourcePropertiesResponse" />
</operation>
<operation name="addTarget">
<input message="wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty" />
<output message="wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse" />
</operation>
<operation name="moveToTarget">
<input message="wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty" />
<output message="wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse" />
</operation>
<operation name="removeTarget">
<input message="wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourceProperty" />
<output message="wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/SetResourcePropertyResponse" />
</operation>
<operation name="destroySatellite">
<input message="wsrlwsdl:DestroyRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/Destroy" />
<output message="wsrlwsdl:DestroyResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/DestroyResponse" />
</operation>
<operation name="renewSatellite">
<input message="wsrlwsdl:SetTerminationTimeRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTime" />
<output message="wsrlwsdl:SetTerminationTimeResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceLifetime/SetTerminationTimeResponse" />
</operation>
</portType>
<binding name="SatelliteSoapBinding" type="tns:SatellitePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="createSatellite">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="getAltitude">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="getOrientation">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="checkOrientation">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="addTarget">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="moveToTarget">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="removeTarget">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="destroySatellite">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="renewSatellite">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="SatGroupSoapBinding" type="tns:SatGroupPortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="addMemberContentRules">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="createSatGroup">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="ServiceGroupSoapBinding" type="wssg:ServiceGroup">
<operation name="GetResourceProperty">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="ServiceGroupEntrySoapBinding"
type="wssg:ServiceGroupEntry">
<operation name="GetResourceProperty">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="ServiceGroupRegistrationSoapBinding"
type="wssg:ServiceGroupRegistration">
<operation name="Add">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="GetResourceProperty">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding="tns:SatelliteSoapBinding">
<soap:address location="http://example.com/satellite" />
</port>
<port name="SatGroupPort" binding="tns:SatGroupSoapBinding">
<soap:address location="http://example.com/satellite" />
</port>
<port name="ServiceGroupPort"
binding="tns:ServiceGroupSoapBinding">
<soap:address location="http://example.com/satellite" />
</port>
<port name="ServiceGroupEntryPort"
binding="tns:ServiceGroupEntrySoapBinding">
<soap:address location="http://example.com/satellite" />
</port>
<port name="ServiceGroupRegistrationPort"
binding="tns:ServiceGroupRegistrationSoapBinding">
<soap:address location="http://example.com/satellite" />
</port>
</service>
</definitions>
第三节 WS-BaseFaults介绍
什么是故障?
如果每件事从第一次开始就一直进行得很好,那该有多好呀!
是呀,要是能中彩票也多好呀。
确实,有人真的中过彩票,但是几率跟您的应用程序一开始就 100% 没有问题一样大。尤其是在这样一种环境中,即有多个系统试图访问其状态被本质上模拟为无状态环境中的状态的对象,通常会有问题。
客户机将请求不存在的 WS-Resources,并试图将它们添加到 ServiceGroup,而其并没有这样的资格。它们将创建并不是真正的 XPath 表达式的 XPath 表达式。
这种情况可能发生,而您必须对此进行处理。
这就是故障产生的缘由。
故障至于 Web 服务就像异常至于 Java 或 C++。它们是这样一些情形,即可能是也可能不是真正的错误 —— 尽管通常都是 —— 但是需要在应用程序的正常流程之外进行处理。
WSDL 中的故障
在 WSDL 文件中,故障定义的方式与其他消息相同,并且指定在与它们相关的 operation 中。考虑:
...
<wsdl:message name="UnableToSetTerminationTimeFault">
<wsdl:part element="wsrl:UnableToSetTerminationTimeFault"
name="UnableToSetTerminationTimeFault"/>
</wsdl:message>
<wsdl:message name="TerminationTimeChangeRejectedFault">
<wsdl:part element="wsrl:TerminationTimeChangeRejectedFault"
name="TerminationTimeChangeRejectedFault"/>
</wsdl:message>
<wsdl:portType name="ScheduledResourceTermination"
wsrp:ResourceProperties ="wsrl:ScheduledResourceTerminationRP">
<wsdl:operation name="SetTerminationTime">
<wsdl:input message="wsrlw:SetTerminationTimeRequest"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime/SetTerminationTime"/>
<wsdl:output message="wsrlw:SetTerminationTimeResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime/SetTerminationTimeResponse"/>
<wsdl:fault message="wsrlw:UnableToSetTerminationTimeFault"
name="UnableToSetTerminationTimeFault"/>
<wsdl:fault message="wsrlw:ResourceUnknownFault"
name="ResourceUnknownFault"/>
<wsdl:fault message="wsrlw:TerminationTimeChangeRejectedFault"
name="TerminationTimeChangeRejectedFault"/>
</wsdl:operation>
</wsdl:portType>
这个来自 WS-ResourceLifetime.wsdl 的简短摘录,展示了两个故障消息 UnableToSetTerminationTimeFault 和 TerminationTimeChangeRejectedFault 的定义。当处理 SetTerminationTimeResponse 出错时,就潜在地返回这两个消息,而不是 返回典型的 SetTerminationTimeResponse。我们可以为某个特定的操作定义任意多的故障。
WS-BaseFaults
当处理其他人编写的应用程序时,您想要做的最后一件事情是试图明白他们在出现错误时的思想。您想要能够马上解释它们并继续。为了在基于 WSRF 的操作中方便这一点,WS-BaseFaults 规范为标准错误定义了基本格式,然后提供一种方法,为更多的特定目的扩展该基本格式,而不改变最初的结构。
中心概念是 BaseFault 的概念。BaseFault 类似于下面这样:
<BaseFault>
<Timestamp>2005-2-15T03:24:57</Timestamp>
<OriginatorReference>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</OriginatorReference>
<ErrorCode dialect="http://www.example.com/NeutronErrorMessages">
PolarityUnchangedError
</ErrorCode>
<Description>Unable to reverse the polarity of the neutron flow! </Description>
</BaseFault>
所有这些值都是可选的,只有 Timestamp 除外,它指出故障是何时实际发生的。OriginatorReference 是对产生故障的 Web 服务的端点引用,而 ErrorCode 和 Description 描述实际的问题。dialect 属性是一个 URL,使我们可以指定如何解释 ErrorCode。提及的规范映射错误代码到(比如) POSIX errno 消息。
我们也可以添加包含其他 BaseFault 的 FaultCause 元素。这使我们可以将错误链接在一起。
创建新的故障
您可以照原来的样子使用 BaseFault,让客户机应用程序解析信息并确定问题,但是更通常的情况是扩展 BaseFault 以创建更多特定的故障。我们做到这一点的方式是,使用 XML 模式来创建新的类型。例如,我们可以像下面这样创建新的 SatelliteNotRespondingFault:
<xsd:complexType name="SatelliteNotRespondingFaultType">
<xsd:complexContent>
<xsd:extension base="wsbf:BaseFaultType">
<xsd:sequence>
<xsd:element name="LastReboot" type="xsd:dateTime" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="SatelliteNotRespondingFault" type="wsrl:SatelliteNotRespondingFaultType"/>
这允许我们返回一个故障,比如:
<SatelliteNotRespondingFault>
<Timestamp>2005-2-15T03:24:57</Timestamp>
<Description>Cannot connect to satellite</Description>
<LastReboot>2005-2-10T09:43:02</LastReboot>
</SatelliteNotRespondingFault>
在本例中,我们以 LastReboot 元素的形式提供了额外的信息,但这是一个 SatelliteNotRespondingFault,几乎给客户机提供了所有信息。实际上,WSRF 规范定义的大多数故障只是扩展 BaseFault 以创建新命名的故障,并不添加任何附加的信息。只要知道返回了哪种类型的故障,就提供了所有必需的信息。
下面我们来看 WSRF 规范定义的不同类型的故障。
WSRF 故障:WS-ResourceProperties
WS-ResourceProperties 规范定义了以下故障,以作为适当事件的响应发送:
l ResourceUnknownFault:该故障适用于所有各种操作,并指出 Web 服务不认识指向端点引用的消息。
l InvalidResourcePropertyQName:当请求一个或多个属性时,该故障指出客户机试图获得或设置所操作的 WS-Resource 上不存在的 ResourceProperty。
l InvalidSetResourcePropertiesRequestContent:在这种情况下,SetResourcePropertyRequest 中发送的数据不符合适当资源属性文档的模式。
l UnableToModifyResourceProperty:在这种情况下,客户机试图设置的资源属性是只读的。
l SetResourcePropertyReqestFailed:这是一个一般错误,指出服务器不能添加或更改资源属性。
l UnknownQueryExpressionDialect:当查询资源属性时,该故障指出客户机试图以服务不认识的方言(dialect)评估查询。因此,定义了 XPath V1.0 和 V2.0。
l InvalidQueryExpression:在这种情况下,查询不符合指定的方言。
l QueryEvaluationError:这是一个一般错误,指出在处理查询时出现了错误。
WSRF 故障:WS-ResourceLifetime
WS-ResourceLifetime 规范定义了四种与 WS-Resource 的即时销毁或预定销毁有关的故障:
l ResourceUnknownFault:与 WS-ResourceProperties 中一样,该故障指出客户机试图访问不存在的或者 Web 服务不知道的 WS-Resource。
l ResourceNotDestroyedFault:该故障指出,WS-Resource 没有被销毁。实际的错误消息可能会给出更多的解释信息。
l UnableToSetTerminationTimeFault:这是一个一般故障,指出服务不能做出请求的更改。
l TerminationTimeChangeRejectedFault:在这种情况下,客户机试图做出不符合 WS-Resource 的内部规则的更改。
WSRF 故障:WS-ServiceGroup
WS-ServiceGroup 规范定义了三种故障:
l UnsupportedMemberInterfaceFault:该故障指出,客户机试图添加的服务不实现任何所需的 portType。
l ContentCreationFailedFault:在这种情况下,添加 Web 服务的请求不具有适当的 Content 元素,如 ServiceGroup 的 MembershipContentRule 中所定义的。
l AddRefusedFault:这是一个一般故障,指出资源不能被添加。
第四节 结束语
本教程讨论了处理 WS-Resources 的一些方面,比如销毁、终止和成组。这些活动都在 WS-ResourceLifetime 和 WS-ServiceGroup 规范中介绍。本教程也讨论了故障的管理,包括 BaseFault 的创建和扩展,如 WS-BaseFaults 规范中所讨论的。
本教程介绍了如下主题:
WS-Resources 和 WS-ResourceProperties 的简要概述。
WS-Resources 的即时销毁。
WS-Resources 的预定终止。
ServiceGroups 的创建和管理。
ServiceGroupEntries 的添加和删除。
通过实现 portType,从外部定义的 WSDL 文件集成信息。
故障消息的创建和定制。
WSRF 中定义的定制故障消息。
Author: orangelizq
email: orangelizq@163.com
posted on 2007-11-27 21:24
桔子汁 阅读(633)
评论(0) 编辑 收藏 所属分类:
Web Service