级别: 初级 Reiner Kraft (rekraft@almaden.ibm.com), 高级软件工程师, IBM Almaden Research Center
2002 年 10 月 01 日 本文是一个系列的第 3 部分,讨论 WebSphere Studio Application Developer 和 Visual Studio .NET 中与 SOAP 和 WSDL 协议层有关的互操作性问题。文章仔细研究了 Application Developer 和 .NET,从而确定它们如何演示不同 Web 服务实现之间的互操作性,着重具体论述了这两种环境如何消费一些用 Apache SOAP、.NET、SOAP::Lite 和 GLUE 实现的现有 Web 服务,并突出讲述可能存在的互操作性问题。
© Copyright International Business Machines Corporation 2002.All rights reserved.
引言
IBM® WebSphere®Studio Application Developer 版本 4.03(以下称为 Application Developer)是一个开发环境,它允许您创建可用于跨异类系统部署的开放、与平台无关的 Web 服务。本质上,Application Developer 合并了 VisualAge™for Java™ 和较早的 WebSphere Studio 产品中的功能,例如,J2EE、Enterprise JavaBean™(EJB)组件以及 Web 工具。包括 XML 工具和对 Web 服务的支持在内的许多新功能也被添加了进来。
Microsoft® Visual Studio® .NET(以下称为 .NET)允许开发者编写、构建和测试 .NET 应用程序。
ASP .NET、
通用语言运行库(Common Language Runtime,CLR)、文档、样本、工具以及命令行编译器都是其中的一部分。
虽然这两个解决方案都基于开放标准(例如:
XML、
SOAP、
WSDL和
UDDI),但是它们之间存在着许多差异(例如:框架、编程语言、运行库、服务发现以及术语等等)。
在本系列的第一篇文章
IBM WebSphere Studio Application Developer 与 Microsoft Visual Studio .NET 的比较 ? 第 1 部分:概念区别中,我对这两个开发环境和工具作了一个高级别的概述,着重具体论述它们如何支持 Web 服务的开发。在第二篇文章
IBM WebSphere Studio Application Developer 与 Microsoft Visual Studio .NET 的比较 ? 第 2 部分:实现方面的差异中,我描述了这两个环境的实现细节和其它差异,主要着力于 Web 服务开发方面可用的工具的可用性。
本文是第 3 部分,讨论这两个环境中与 SOAP 和 WSDL 协议层有关的互操作性问题,并展示互操作性是如何给开发过程带来额外复杂性的。互操作性要求对 Web 服务栈中几个协议有深入的理解。因此,一个快速应用开发(rapid application development,RAD)环境应尽可能隐藏这些问题并产生能够很好地与不同实现一起工作的代码,从而让开发者不必担心这些方面的问题。但是,如果需要微调低级别协议的设置,开发者应该仍然有能力做到。
目前,在 Web 服务社区中使用的主要 Web 服务实现如下:
-
Apache SOAP是对提交给 W3C 的
SOAP 提案的一个基于 Java 的实现。它源于
IBM SOAP4J 实现并取代这个实现。Application Developer 基于 Apache SOAP 技术。
-
Microsoft Visual Studio .NET是 Microsoft 建立在
.NET 框架基础上的 Web 服务实现,用来开发 XML Web 服务。.NET Framework SDK 可以免费下载,它包含有一组命令行工具和编译器,您可以用它们来入门。这些工具不要求 Visual Studio .NET(但使用 Visual Studio .NET 能促进整个开发过程)。
-
SOAP Lite是 Paul Kulchenko 的
SOAP::Litefor Perl。它是一组 Perl 模块,这些模块提供了到 SOAP 的简单而轻量的接口。
可用的其它 SOAP 实现还有许许多多。在
www.xmethods.netWeb 站点的
SOAP Implementations可以查看到更完整的清单。这张清单上另一个有趣的实现是
GLUE,它提供了对诸如 SOAP、WSDL 和 UDDI 之类标准的高性能、基于 Java 的实现,并提供了与 EJB、Java 消息服务(Java Message Service,JMS)和 Java 认证和授权服务(Java Authentication and Authorization Services,JAAS)的无缝集成。
我将对 Application Developer 和 .NET 两者进行考察,以找出它们如何支持不同 Web 服务实现之间的互操作性,以及成功地“隐藏”了多少实现细节。
本文具体演示如何消费用 Apache SOAP、.NET、SOAP::Lite 和 GLUE 实现的现有 Web 服务,并突出讨论可能存在的互操作性问题。
在系列的
第 2 部分中,我展示了用 Application Developer 实现的 Web 服务可以容易地用建立在 Apache SOAP 技术上的开发工具来消费,并且也演示了用 .NET 客户机来消费 .NET Web 服务是相当容易的。接着,在第 3 部分,我将只描述那些用不同客户机技术来消费 Web 服务的方案(例如,用基于 Apache SOAP 的 Application Developer 客户机来消费 .NET Web 服务)。
Web 服务的流行的服务注册中心可以从 Web 上访问到,例如,
xMethods和
SALCentral;请访问这些服务注册中心熟悉现有的功能。请定期访问这些注册中心以了解这种技术是如何走向成熟的,并获知提供了哪些类型和类别的 Web 服务。了解这些信息可以刺激创造性思维,从而产生目前尚未提供但却可能有这种需要的相似或不同类别的其它有趣而有用的 Web 服务。
这些基于 Web 的服务注册中心正日益流行,其原因也可以解释为 UDDI 作为 Web 服务通用目录的受欢迎程度不高甚至是严重不足。用户可能更喜欢能提供额外信息(例如,一些展示如何使用服务的样本、分析报告、实现信息以及所用的协议版本等等)和对 Web 服务的更强大的搜索和浏览功能的基于 Web 的办法。
因为本文无意充当讲述如何使用 WebSphere Studio Application Developer 或 Visual Studio .NET 的教程,所以,这里会省略一些在详细教程中将另有描述的次要步骤。
本文随带的样本文件包含在
下面的下载文件中。
必备知识
本文假设您已经阅读过本系列的
第 1 部分和
第 2 部分。
您应该对 Web 服务和 Web 服务协议栈有一些基本了解:
要获得对 Web 服务的全面介绍,请访问
IBM developerWorks。要求具备
Java开发、
HTTP和
XML的知识。此外,熟悉 Web 开发(ASP、JavaScript 等等)以及 Visual Studio 以前的版本(比如版本 6.0)是有帮助的,但这不是必须的。
对于代码样本,您需要
.NET 框架软件开发包,它包含在 Visual Studio .NET 中,或者可以从
MSDN下载。针对 .NET 的代码样本是用 C# 编写的。MSDN 提供有
C# 教程;不过,这些样本并未使用高级的 C# 功能,所以有经验的 Java 或 C++ 开发者理解起来不会有什么问题。
如果尚未安装 WebSphere Studio Application Developer 的一个副本,那您可以
下载一个试用版。如果您已经在使用 Application Developer 或 .NET 来设计 Web 服务,那本文向您展示的就是使用不同工具和技术的作用及可能有的优点。
此外,我推荐您阅读 Sheldon Wosnick 的
用 IBM WebSphere Studio Application Developer 和 Microsoft .NET Framework SDK 开发 EJB Web 服务的 Microsoft .NET Web 服务客户机一文,该文发表于《IBM WebSphere 开发者技术期刊》的 2002 年 4 月那一期。
协议互操作问题
HTTP、SOAP 和 WSDL 代表了 Web 服务协议栈的核心协议和基础。由于存在不同的协议版本和实现,所以 Web 服务之间常常缺乏互操作性。尽管协议和规范正日益成熟,但这些互操作性问题仍然挥之不去,所以我们要进一步调研它们对在 Application Developer 和 .NET 中进行的 Web 服务开发有什么影响。
用户如果要理解一个 Web 服务客户机为什么运转不起来,那就要在 SOAP/HTTP 协议级别上进行仔细的考察。要了解什么地方出了问题,SOAP 故障代码总是很好的第一条线索。
Application Developer 和 .NET 这两个开发环境都让用户能够在 SOAP 级别上对消息进行微调。然而,要正确地解决互操作性问题,需要具备专门知识和丰富的经验以及对 Web 服务协议栈的精深理解。
SOAP
目前有几个可用的 SOAP 规范。万维网联盟(World Wide Web Consortium,W3C)目前正在进行 SOAP 版本 1.2 的工作。但是,SOAP 1.1 仍然被广泛使用。尽管版本 1.1 和 1.2 非常相似,但还是存在一些微妙的差异,这些差异会引起不兼容方面的问题。因此,开发者应清楚了解这些微妙的差异。而且,如有必要修正这些低级别协议上的问题,开发者需要知道怎么做,因为这些问题隐藏在 Application Developer 和 .NET 中。
在 Snell、Tidwell 和 Kulchenko 所著的《
Programming Web services with SOAP》一书的第 1 和第 2 章中很好地介绍和概述了这个主题(请参阅
相关参考资料部分)。在专门讨论互操作性的一节中,三位作者提供了以下的 HelloWorld 示例,并更深入地研究了一些 SOAP 协议问题。
举例来说,请考虑这个简单的 HelloWorld .NET Web 服务(请参阅
下面的下载文件中的
HelloWorld.asmx )。代码用 C# 编写并建立在 ASP .NET 的基础上,ASP .NET 从运行着 Internet Information Server(IIS)并支持 .NET 的机器上获得执行。
<%@ WebService Language="C#" Class="HelloWorld" %>
using System.Web.Services;
[WebService(Namespace="urn:Example1")]
public class HelloWorld {
[WebMethod]
public string sayHello(string name) {
return "Hello " + name;
}
}
|
要做到使用 .NET 来消费这个服务相当容易(请参阅
下面的下载文件中的
HelloWorld.cs )。WSDL 描述(请参阅
下面的下载文件中的
HelloWorld.wsdl )进一步简化了 .NET Web 服务客户机的开发过程,因为它除去了不得不处理低级别的 SOAP 调用所带来的负担(要了解如何做到这一点,请参阅本系列的
第 2 部分)。
然而,试图消费这个 Web 服务的 SOAP::Lite 或 Apache SOAP 客户机却不能正常运转,原因有两个:
- .NET 要求将 HTTP
SOAPAction 头用来标识所请求的操作;其格式是服务的名称空间后跟操作名,中间用
/ 隔开(例如,
urn:Example1/sayHello )。SOAP::Lite 使用
# 作为分隔符,而基于 Java 的 Apache SOAP 在缺省情况下则干脆将
SOAPAction 头忽略了。
- .NET 要求用于方法调用的所有参数都被显式类型化。
对于研究和修正这样的问题,有一个能够拦截 SOAP 消息的调试工具(如 Apache SOAP 分发包随带的 TunnelGui)是至关重要的。Application Developer 包含了 Apache SOAP(
soap.jar ),从而包含了上述颇有价值的基于 Java 的工具,用来研究 SOAP 消息。此外,Application Developer 还提供了 TCP/IP Monitoring Server,它类似于 TunnelGui。您可以创建服务器配置/实例,这个服务器配置/实例允许您将 TCP/IP Monitoring Server 添加为一个服务器,并且启动和停止它也很容易。
.NET 用户如果需要调试 SOAP 消息,那他们可能就需要下载 Apache SOAP,或者也可以使用 ASP .NET 跟踪功能(请参阅 MSDN 上
Matt Powell 的文章,学习如何使用这个功能)之类的替代办法。我更喜欢能拦截 SOAP 消息的基于代理的工具(如 TunnelGui),因为使用这些工具很容易,凭直觉就行了。
定制 SOAP 消息
通过 Java SOAP API,Application Developer 允许对 SOAP 消息进行细粒度的操作。可以从
Apache SOAPWeb 站点找到关于如何实现这一点的详细描述。
.NET 采用了一种不同的办法,它通过一种基于属性的机制来实现对 SOAP 消息的操作。这些属性与 C# 方法或类关联,让用户去控制 SOAP 消息中 XML 的格式。
例如,
[WebService(Namespace="urn:Example1")]
|
将把 Web 服务的名称空间(namespace)属性设置成
urn:Example1 。
在设计 XML Web 服务时,首先要做出的决定之一是如何在 SOAP 请求中对 XML 进行编码。您可以选择使用 XSD 模式或者使用 SOAP 规范的第 5 节和第 7 节所概述的格式化规则。WSDL 将前一种选择称为
文本式(literal)(使用预定义的 XML 模式),称后一种选择为
编码式(encoded)(遵循 SOAP 规范的第 5 节和第 7 节)。
要指定基于文本的格式化,我们需要把
SoapDocumentMethod属性关联到代理(proxy)类的某个方法,并将 Use 属性设置为 SoapBindingUse.Literal。例如:
[
SoapDocumentMethod(
"http://www.almaden.ibm.com/HelloWorld",
RequestNamespace="http://www.almaden.ibm.com",
ResponseNamespace="http://www.almaden.ibm.com",
Use=SoapBindingUse.Literal]
public string HelloWorld (string name) {
|
要指定编码式的参数格式化,我们将
SoapDocumentMethod属性关联到代理类的某个方法,并将 Use 属性设置为 SoapBindingUse.Encoded。
服务样式(service style)(参见 WSDL 1.1)的概念可能会引起更多的兼容性问题;使用能进行基本的
远程方法调用(Remote Procedure Call,RPC)但不支持文档样式
DOC的工具箱与此有所不同。这种样式问题指的是将 SOAP 信封的结构安排成适合于发送 XML 文档的,还是让 SOAP 信封成为 RPC 方法调用的序列化表示。
文档样式(Document style)的意思就是 SOAP 体携带常规 XML 文档,并且没有明确的方法调用概念。DOC 样式是指 XML 文档在客户机和服务器之间来回传递。SOAP RPC 则更严格,必须遵循预定义的规范(请参阅 SOAP 规范的第 7 节)。不同之处在于,对于 DOC 样式的情况,SOAP 消息体中所使用的 XML 由应用程序来指定,而对于 RPC 样式的情况,XML 则在协议本身中指定。
如果一个接受和发送文档样式信封的服务接收到 RPC 样式的请求信封,或者是反过来的情况,那这就成了互操作性问题。在这种情况下,SOAP 信封将很可能不被接受。起初,在 SOAP 工具箱中,RPC 样式是优先的选择。现在,由于两种样式针对的是不同的情形(例如,在表达能力和易于集成之间可能要有一个折中),所以选择一种样式而不选择另一种样式并没有对错之分。
Application Developer 在发布 SOAP 服务时缺省采用 RPC 样式。.NET 缺省采用文档样式。不过,由于这两个开发环境都支持 WSDL 1.1,而且将请求规范化时需要的所有信息(包括所使用的是哪一种样式)都包含在 Web 服务的 WSDL 规范中,所以这个问题减轻了一些。但是,开发者应该知道这一点,尤其是在消费较老的采用 RPC 样式的服务时,从相应的 WSDL 中是看不出这一点的。
要在 .NET 中指定文档格式化样式,我们需要将
SoapDocumentMethod属性应用到代理类中的方法。下面的示例将文档方法格式化样式和文本式参数格式化样式结合了起来:
[
SoapDocumentMethod("http://www.almaden.ibm.com/DocumentWrappedLiteral",
RequestNamespace="http://www.almaden.ibm.com",
ResponseNamespace="http://www.almaden.ibm.com",
Use=SoapBindingUse.Literal)]
public string HelloWorld (string name) {
|
要指定 RPC 样式,我们需要将
SoapRpcMethod属性应用到代理类中的方法:
[
SoapRpcMethodAttribute("http://www.almaden.ibm.com/Rpc",
RequestNamespace="http://www.almaden.ibm.com",
ResponseNamespace="http://www.almaden.ibm.com")]
public string HelloWorld (string name) {
|
还可以对更多的属性进行操作,举例来说,在各个参数是被封装到一个 XML 元素中还是直接跟在 Body 元素之后方面。.NET 文档包含有对这些情形的描述,并更详细地描述了这些定制。
WSDL
使用 WSDL 的主要动机是为了能够更容易使用 Web 服务。目前,WSDL 的版本是 1.1,它取代了 NASSL(IBM 所使用的)和 SDL(.NET 中所使用的)。到目前与止,Application Developer 和 .NET 中与最初的不同实现有关的许多互操作性问题都已经得到解决或有所缓解。
然而,.NET 和 Application Developer 之间的互操作性问题仍在出现,其原因在于如何生成和使用 WSDL:.NET 针对每个 Web 服务生成一个 WSDL 文件,而 Application Developer 则将 Web 服务的 WSDL 文件分为两个文件 ? Web 服务接口和 Web 服务实现。对这两种文档类型的详细描述可以在 IBM developerWorks 的
Understanding WSDL in a UDDI registry - Part 1中找到。特别是 Application Developer 的 UDDI 浏览器(UDDI Explorer)也受到了影响,因为它无法处理这些单一的 WSDL 文件。根据规范,这两种办法都可以采用,只是在某些情况下需要手工的变通办法。
WSDL 服务接口(WSDL Service Interface)文档实质上包含以下元素:
- import
- types
- message
- portType
- binding
相比而言,WSDL 服务实现(WSDL Service Implementation)文档则只有以下元素:
要看看如何手工修正这个问题的示例,请参阅
下面的下载文件中的
HelloWorld.wsdl 。我们需要手工将这个文件分成
HelloWorld-interface.wsdl 和
HelloWorld-service.wsdl ,在
下面的下载文件中也提供了这两个文件。请注意,
HelloWorld-service.wsdl 在表单的开头使用了一条 import 语句:
<import namespace="urn:Example1" location="http://blackbox/Reiner
/HelloWorld-interface.wsdl">
|
来导入服务接口定义。
互操作性问题:消费用不同技术实现的 Web 服务
在这一部分中,我描述我使用 Application Developer 和 .NET 来开发 Web 服务客户机的经验,这些客户机试图消费向
xMethods.net注册中心注册了的 Web 服务。在我的前一篇文章中,我展示了如何在两种环境中开发和部署 Web 服务。我还描述了如何实现消费 Web 服务的 Web 服务客户机。如何消费用不同技术实现的 Web 服务,其工作原理应与前一篇文章所描述的相同。
在下面的每个示例中,Web 服务客户机将用 Application Developer 和 .NET 来实现。将展示代码片段和样本输出。将突出讲述的是在开发客户机的过程中发生的问题。
总的来说,看到在这些信手拈来的示例中几乎不存在互操作性问题,这是一种正面的经验。一些次要的问题得归因于前面所描述的 SOAP 或 WSDL 问题。这些示例主要使用简单的数据类型(如字符串型和整型)。如果互操作性问题使得开发者无法消费这些类型的服务,则我们就可以料想到那些使用更复杂类型的服务将根本不能运转起来。
在创建 Web 服务客户机时,通常会发生两类问题:
-
开发期间的错误
当导入 WSDL 以创建代理类时,存在问题的或不兼容的 WSDL 会引起自动生成代理类方面的一些问题。构建过程将停止并指出这些问题。此时,一种可能的解决方案是,如果可能的话,去下载 WSDL,对它进行分析,然后作一些手工修改。有时,某些公开出来的 Web 服务之所以不能运转,仅仅是因为 WSDL 是手工生成的;期望的参数与所描述的不同,XML 解析错误导致只能去猜测正确的 XML 格式应该是怎么样的。在有些情况下,Web 服务可能根本就不能用。
-
运行时错误
WSDL 导入过程顺利进行,但在运行时(调用),在 SOAP 级别(SOAP 错误)或在网络级(如 HTTP)上抛出了一个异常。这些类型的错误通常需要对 SOAP 消息进行微调(请参阅前面的部分)。
在下面所描述的示例中,Application Developer 和 .NET 客户机正确地消费了所有 Web 服务而没有任何互操作性问题。
示例 1:用 Apache SOAP 实现的天气/温度(Weather/Temperature)服务
这个天气/温度检索 Web 服务(请参阅 xMethods
描述)是用 Apache SOAP 实现的,以邮政编码(例如
95120 )的形式给它一个输入参数,它就会返回温度值。请同时参阅
这个 Web 服务的 WSDL。
在 Application Developer 中消费天气/温度服务
Application Developer 的一些向导会指导用户方便地完成开发过程,使用户很容易就能生成 Web 服务客户机。欲了解更多详情,请参阅本系列的
第 2 部分。
在创建了一个 Web 工程之后,我们调用 Web service client 向导。接着,我们要指定 WSDL 文件的 URL。还有更多设置;对这些设置,都接受其缺省值。生成一个样本应用程序。现在,请启动 IBM EJB Test Client(选择
Launch Test Client)。
Application Developer 的 navigator 窗口应类似于图 1:
图 1. 运行了 Web service client 向导之后 Application Developer 的 navigator 窗口
在 navigator 窗口中,您将看到所生成的样本代码(例如,用于测试服务的一些 JSP 页),以及使访问该服务成为可能的 SOAP 代理类(
TemperatureServiceProxy.class )。
测试客户机(test client)启动后将显示关于 Web 服务的功能(例如,所支持的方法和所期望的参数)的信息:
图 2. Application Developer 的 EJB Test client 窗口显示所支持的方法
请选择方法
float getTemp(String)。这将打开一个页面,您可以方便地输入一个参数(对于这种情况,是输入一个邮政编码):
图 3. Application Developer 的EJB Test client 窗口让用户输入输入参数
到这里,我们就可以调用 Web 服务了,并获得所要的结果。(不出所料)不存在任何互操作性问题,因为客户机和服务器两者是用相同的技术实现的。
在 .NET 中消费天气/温度服务
在 .NET 中,我们创建一个新的解决方案(例如,C# 单机控制台应用程序),添加一个 Web 引用(它指向
WSDL的 URL)到该工程中,然后添加一些实例化代理类
Weather.cs (请参阅
下面的下载文件获得
Weather.cs 文件)的 C# 代码,代理类
Weather.cs 在本地代表远程的 Web 服务。请参阅本系列的
第 2 部分了解更多详情。
我们需要添加的 C# 代码是:
net.xmethods.www.TemperatureService oProxy =
new
net.xmethods.www.TemperatureService();
float
fResult = oProxy.getTemp(args[0]);
|
如果我们以邮政编码作为参数调用该 Web 服务客户机,那么我们就会获得所要的结果:
图 4. Web 服务调用 .NET 客户机调用天气/温度服务所得的结果
请注意,两次调用的结果是不同的,因为我们是在不同时间调用 Web 服务客户机的。
对于这个服务不存在任何互操作性问题。另一种方向(Apache SOAP 调用 .NET)可能会带来一些前面所指出的问题,原因在于 SOAP 消息的缺省生成方式。您可以参阅 MSDN 上的一篇
文章,它描述了这种情形(.NET 客户机消费 Apache SOAP)下的互操作性问题,并描述了一些与分解由 Application Developer 产生的两个 WSDL 文件有关的问题。
在开发用来在添加 Web 引用之后对所生成的代理类进行实例化的 Web 服务客户机时,我有时会碰到一些困难。在缺省情况下,.NET 不会在 Solution Explorer 中显示所生成的代理类。您需要手工单击 Solution Explorer 窗口顶端的
Show all,然后才可以看到该代理类,显示为
Reference.cs (当使用 C# 时)。打开这个类,您将会发现 Web 服务的名称空间(例如
net.xmethods.www )被嵌套进解决方案所使用的名称空间(例如
example1 )中。要引用使用全限定名的代理类,请将工程名称空间和 Web 服务的名称空间一起包含进去。
在这个示例中,要引用这个代理类,我们需要使用
example1.net.xmethods.www.
TemperatureService
。在消费名称空间以
com. 打头的其它 Web 服务时,我亲身经历了这个问题。
示例 2:用 SOAP::Lite 实现的 FedEx 跟踪(tracking)服务
这个用 SOAP::Lite 实现的 Web 服务提供了对 FedEx 跟踪信息的访问(请参阅 xMethods
描述)。它返回给定跟踪号的最新 FedEx 状态。您可以
下载这个 WSDL。
在 Application Developer 中消费 FedEx 跟踪服务
此处,我们照搬上面的示例 1 中所概述的步骤,然后用一个包含一个跟踪号的字符串调用测试客户机。根据 FedEx 条款,客户应只能用这个服务来跟踪它自己的包裹。事情就是这么巧,我正在等待一个 FedEx 快递过来的物品,于是便去跟踪它。
我发现在 Application Developer 中开发一个客户机来访问 FedEx 跟踪程序非常简单。
在使用 Application Developer 来访问 SOAP::Lite Web 服务时,我没发现任何互操作性问题。一切都顺利进行。
在 .NET 中消费 FedEx 跟踪服务
在这里,请重复上面的示例 1 中所概述的相同的步骤。
在创建了一个新的解决方案之后,Solution Explorer 看起来应类似于图 5:
图 5. 在创建了一个访问 FedEx 跟踪 Web 服务的新 Web 服务客户机之后,.NET 的 Solution Explorer
请注意,我们只需要添加两行 C# 代码(请参阅
下面的下载文件获得
FedEx.cs 文件):
// instantiate proxy
net.xmethods.www.FedExTrac
kerService oProxy = new
net.xmethods.www.FedExTrackerService();
String strStatus = oProxy.getStatus(args[0]);
|
第一行代码实例化代理(proxy)对象,第二行代码则执行 getStatus() 方法。IntelliSense® Editor 是一个很有帮助的工具,因为它能显示 oProxy 对象所有可用的方法。这样,您甚至没有必要查看 WSDL。
最后,我们构建应用程序。这将产生可执行文件
FedEx.exe ,保存在
bin\debug 文件夹中。当从命令行调用客户机时,您应该能够看到我们包裹的当前状态。
不存在任何互操作性问题。请注意,在这种情形中,我们用 .NET 客户机调用 SOAP::Lite Web 服务。正如前面所提到的,进行另一种方向(即 SOAP::Lite 调用 .NET)要更复杂一些,因为我们需要操作 SOAP 头并提供参数的分类。
示例 3:用 .NET 实现的 Whois 服务
Whois 服务(请参阅 xMethods
描述)是用 .NET 实现的,它返回 .com、.net、.org 和 .edu 域方面的
whois信息。首先,
请下载 WSDL。
我们将调用方法 String getWhois(String, String)。第一个参数代表域(如
ibm.com )。对于第二个参数,我们使用许可证密钥
0 来测试一下。
在 Application Developer 中消费 Whois 服务
同样地,我们重复前面几个示例所概述的相同的步骤:调用 Web service client 向导,输入 Web 服务的 WSDL,然后让向导自动启动一个测试客户机。
图 6. Web 服务调用 Application Developer 客户机调用 Whois 所得的结果
这个结果表明,Application Developer 和 .NET 可以顺利进行交互。当使用 Application Developer 和 .NET 的 beta 测试版时,可能得不到这个结果,原因在于不兼容性。自那时起,两个版本都做了许多改变,Web 服务技术也已经成熟起来。
在 .NET 中消费 Whois 服务
用 .NET 消费这个 Web 服务,其步骤与上面的示例 1 和 2 中的完全一样,也与本系列的
第 2 部分所描述的一样。因为客户机和服务两者都是用 .NET 实现的,所以毫无疑问不会有任何互操作性问题。
示例 4:用 GLUE 实现的货币兑换(currency conversion)服务
这个货币兑换 Web 服务(请参阅 xMethods
描述)是用 GLUE 实现的,以国家名称的形式给定两个输入参数,它就会返回货币兑换率(例如,
germany 和
usa )。请同时参阅
这个 Web 服务的 WSDL。
在 Application Developer 中消费这个货币兑换服务
请执行前一个示例中所描述的相同的过程,然后用以下两个变量来调用货币兑换服务:
germany 和
usa 。结果如图 7 所示:
图 7. Web 服务调用 Application Developer 客户机调用货币兑换的结果
在 Application Developer 中,访问用 GLUE 实现的 Web 服务完全不会引起任何互操作性问题。
在 .NET 中消费货币兑换服务
我们在 .NET 中完成前面几个示例所描述的相同步骤。我们将需要添加以下 C# 代码(请参阅
下面的下载文件中的
Currency.cs ):
net.xmethods.www.CurrencyExchangeService oProxy = new
net.xmethods.www.CurrencyExchangeService();
float fResult = oProxy.getRate(args[0], args[1]);
|
调用 .NET Web 服务客户机的预期结果如下所示:
图 8. Web 服务调用 .NET 客户机调用货币兑换服务所得的结果
不存在任何互操作性问题。
结束语
我在本文中指出了 Application Developer、.NET 和其它 Web 服务实现在协议级别(例如,SOAP 和 WSDL)上可能出现的互操作性问题,并提供了如何定制 SOAP 消息方面的详细信息。我还提供了一些示例,它们演示了如何使用 Application Developer 和 .NET 来消费用不同技术实现的 Web 服务。这些示例帮助说明了可能存在的互操作性问题。
这两种环境通过不同的途径来处理互操作性问题。例如,WebSphere Studio Application Developer 提供了一个基于 Java 的 API,从而允许微调 SOAP 消息。Visual Studio .NET 则主要使用与 C# 代码关联的属性,用这些属性来帮助微调 SOAP 消息。
总之,看见这两种开发环境之间的互操作性水平这么好是非常鼓舞人心的:在 .NET 中编写一个 Web 服务,然后用 Application Developer 来消费它,这可以进行得很好,反之亦然。不过,尽管有这些令人鼓舞的结果,但由于存在各式各样的 Web 服务实现,所以互操作性问题不会很快消失。目前,开发者在试图消费某个特定 Web 服务时,仍然需要知道它是用哪种技术实现的。这似乎在一般意义上与平台和实现透明性的设想以及 Web 服务的普遍性背道而弛。开发者需要了解互操作性问题,并且明白这些问题对整个开发过程可能会有什么影响;这就要求对各个底层协议(HTTP、SOAP 和 WSDL 等)有深入的理解。Application Developer 和 .NET 都努力隐藏这些复杂性。但是,在发生了问题的时候,您还是不得不启动调试会话(例如,TunnelGui)来分析 SOAP 消息,找出如何在 C# 中设置 SOAP 属性或者如何检查处理这些问题的 Java API 调用。
这些互操作性问题妨碍了 UDDI 所提倡的 Web 服务的动态发现和使用,这是一个合乎逻辑的结果。在理想的世界中,Web 服务应只由它们的接口来描述;实现本身应该无关大碍。然而,在现实的世界中,仍然要求开发者知道一个服务是如何实现的(例如,采用的是哪种技术),这样才能借助于手工微调,使 Web 服务应用程序最终能按预期的运行。希望有一天,我们能够改善基于开放标准和协议的互操作性,从而使 Web 服务动态调用的设想,最终是语义化的 Web 成为现实。
参考资料
关于作者  | 
|  |
Reiner Kraft是 IBM Almaden Research Center 的高级软件工程师。他是 IBM jCentral Java 资源搜索引擎的一名关键开发人员,该引擎现已集成到 IBM developerWorks 中。他还设计并实现了 xCentral,一个特定于 XML 的搜索引擎。Reiner 发表了多篇讲述 Web 服务的技术文章和关于面向服务的体系结构(service oriented architecture,SOA)的研究论文。面向服务的体系结构是 Web 服务体系结构的抽象模型,也是 Web 服务与安全(包括访问控制在内)有关的论题。他的研究兴趣是智能搜索引擎(因特网搜索技术)、超文本、安全和因特网信息系统。您可以通过
rekraft@almaden.ibm.com与 Reiner 联系,或者访问他的
Web 站点。
|
对本文的评价
|