级别: 初级 Frank Cohen (fcohen@pushtotest.com), CEO, PushToTest
2003 年 5 月 01 日 IBM 新兴技术工具箱(Emerging Technologies Toolkit,ETTK)以 Axis 工具包为特色,软件开发人员能够通过 Axis 工具包使 Java 应用程序充当基于 SOAP 的 Web 服务。在本文,Frank Cohen 会向 Java 开发人员展示如何通过 Axis 使用复杂数据类型,包括 JavaBean 组件。
ETTK 是一套工具和库,用于设计、开发以及执行新兴的自主和有关网格的技术与 Web 服务。ETTK 带有由 IBM 新兴技术开发部门和研究小组最新公布的规范和原型的示例,同时还提供了介绍性的材料来帮助开发人员着手开发 Web 服务。ETTK 由 Web 服务工具包(Web Services Toolkit,WSTK)演变而来,并包括 Axis 库,该库是为 Java 开发人员制定的 SOAP 1.1 规范的一个完整实现。
Axis 使 Java 开发人员能够简单地用现存的 Java 代码构建基于 SOAP 的 Web 服务。其最简单的形式:将 Java 归档资源(Java Archive Resource,JAR)文件放入 Axis webapps 目录,同时 Axis 自动将 public 方法作为基于 SOAP 的 Web 服务公开。请看看下面
清单 1中的 Java 类。
清单 1. 简单的 Responder Java 类
public class Responder
{
public String Repeat( String theword )
{
return "You told me to say: " + theword;
}
}
|
Responder 类有一个名为 repeat 的 public 方法。它接受一个 String 值同时返回一个 String 值。编译 Responder 类并将它包装到一个 JAR 文件后,您就可以通过将 JAR 文件放入 Axis webapps 目录来将该 Responder 作为 Web 服务提供。那是不是很容易?较为困难的是将带有期望发送或接收复杂数据类型的方法的 Java 类公开。
清单 2中是一个有两次调用的 Responder 类,它返回一个 Java Bean。
清单 2. 较复杂的 Responder Java 类
public class Responder
{
public String repeat( String theword )
{
return "You told me to say: " + theword;
}
public MyID getMyID()
{
MyID theid = new MyID();
return theid;
}
class MyID
{
private String name = "Frank Cohen";
private int number = 10;
public MyID();
public String getName() { return name; }
public void setName( String aname ) { name = aname; }
public String getNumber() { return number; }
public void setNumber( int num ) { number = num; }
}
}
|
这个 Responder 类有一个内部类,它定义 JavaBean 组件。遗憾的是,不是仅仅把这个已编译的 JAR 放入 Axis webapps 目录就能获得对 getMyID() 方法的访问权。Axis 并不理解 MyID bean 的复杂数据类型的格式,它会返回一个序列化异常。
SOAP 规范定义了一套简单数据类型 — 字符串型(String)、整型(Int)、长型(Long)等等 — 和一个支持复杂数据类型的方法。大多数的 SOAP 实现带有适用于复杂数据类型(包括 Java Bean 组件)的编码器和译码器。本文将展示如何在 Apache Axis 和 Apache SOAP 中使用复杂数据类型。
作为普及的开放源代码测试框架与实用程序 — TestMaker — 的维护人员,我就运作中的软件开发实践,尤其通过 Web 服务,来发表一下自己独到的见解。最近,我花了大半天在一家大公司帮助一位开发人员用 TestMaker 测试一个发出复杂数据类型的基于 SOAP 的 Web 服务。这个开发人员需要帮助,使 TestMaker 理解定制的响应类型,以及在她的主机上使用 Apache Axis 创建 Web 服务。
这里是她要完成的任务:
- 在服务器上通过 Apache Axis 创建一个 Web 服务,该 Web 服务使用内建的 BeanSerializer 来处理复杂数据类型。
- 创建上述 Web 服务的客户机,该客户机使用 Apache Soap 的 BeanSerializer 类来处理复杂数据类型。
- 运行性能测试以了解序列化器的吞吐量。
本文将描述完成这些任务所需要的各个步骤。文中提到的所有软件都能够免费下载获得(请链接参阅
参考资料)。
定义 Web 服务
首先,您将创建一个复杂数据类型的 JavaBean 表示。在
清单 3中展示了这个 JavaBean。
清单 3. 复杂数据类型的 JavaBean 表示
package com.pushtotest;
/**
* Forecast Java Bean for the weather Web Service
*/
public class Forecast {
String zip = null;
String city = null;
String state = null;
String date = null;
String forecast = null;
byte hi = 0;
byte low = 0;
byte precip = 0;
/** Creates a new instance of WeatherBean */
public Forecast() {
}
public void setZip( String thezip )
{
zip = thezip;
}
public String getZip()
{
return zip;
}
public void setCity( String thecity )
{
city = thecity;
}
public String getCity()
{
return city;
}
public void setState( String thestate )
{
state = thestate;
}
public String getState()
{
return state;
}
public void setDate( String thedate )
{
date = thedate;
}
public String getDate()
{
return date;
}
public void setForecast( String theforecast )
{
forecast = theforecast;
}
public String getForecast()
{
return forecast;
}
public void setLow( byte thelow )
{
low = thelow;
}
public byte getLow()
{
return low;
}
public void setHi( byte thehi )
{
hi = thehi;
}
public byte getHi()
{
return hi;
}
public void setPrecip( byte theprecip )
{
precip = theprecip;
}
public byte getPrecip()
{
return precip;
}
}
|
Forecast 是一个简单的 Java 类,它封装天气预报的变量,包括 U.S. 邮编和温度。Forecast 遵循 JavaBean 模式,具有一个公用的无参数初始化程序且为每一个封装的变量提供了 getter/setter 方法。您将看到,在服务器端和客户机端都将使用这个 Forecast JavaBean 组件。
下面定义一个天气 Web 服务。它接收一个邮编值并返回一个 Forecast 对象。在
清单 4所示的 WSDL 文档中描述了天气 Web 服务的接口。
清单 4. 天气服务的 WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="urn:weather"
xmlns:impl="urn:weather"
xmlns:intf="urn:weather"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns2="http://weather"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://weather">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="Forecast">
<sequence>
<element name="zip" nillable="true" type="xsd:string"/>
<element name="city" nillable="true" type="xsd:string"/>
<element name="state" nillable="true" type="xsd:string"/>
<element name="date" nillable="true" type="xsd:string"/>
<element name="forecast" nillable="true" type="xsd:string"/>
<element name="hi" type="xsd:byte"/>
<element name="low" type="xsd:byte"/>
<element name="precip" type="xsd:byte"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getWeatherResponse">
<wsdl:part name="getWeatherReturn" type="tns2:Forecast"/>
</wsdl:message>
<wsdl:message name="getWeatherRequest">
<wsdl:part name="in0" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="Weather">
<wsdl:operation name="getWeather" parameterOrder="in0">
<wsdl:input name="getWeatherRequest" message="impl:getWeatherRequest"/>
<wsdl:output name="getWeatherResponse" message="impl:getWeatherResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="weatherSoapBinding" type="impl:Weather">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getWeather">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getWeatherRequest">
<wsdlsoap:body
use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:weather"/>
</wsdl:input>
<wsdl:output name="getWeatherResponse">
<wsdlsoap:body
use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:weather"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="WeatherService">
<wsdl:port name="weather" binding="impl:weatherSoapBinding">
<wsdlsoap:address
location="http://examples.pushtotest.com:92/ axis/servlet/AxisServlet"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
要想构建服务器端的 Web 服务,您需要通过
清单 5中所示的代码定义 weather Java 类。
清单 5. Weather 类
/*
* weather.java
*/
package com.pushtotest;
public class weather {
/** Creates a new instance of weather */
public weather() {
}
public Forecast getWeather( String ziprq )
{
Forecast fb = new Forecast();
fb.setZip( ziprq );
fb.setCity( "Campbell" );
fb.setState( "CA" );
fb.setDate( "April 11, 2003" );
fb.setForecast( "20 percent chance of rain." );
return fb;
}
}
|
weather 类定义一个 getWeather 方法,该方法在 String 对象中接收一个邮编值并且返回一个 Forecast 对象。由于您将使用 SOAP RPC 编码,因此由 SOAP 栈对请求进行数据编出,然后把 Forecast 对象数据编组到一个响应中。
简单的 Ant 构建脚本先将 weather 对象和 Forecast 对象编译到类文件,然后再编译到 weather.jar 归档文件。在 Web 服务的源文件中能够找到 Ant 构建脚本 — build.xml(请链接参阅
参考资料)。
一旦构建了这个脚本,就随时可以将 weather.jar 作为 Web 服务安装在 Apache Axis 服务器上。Apache Axis 通过格式化成 Web 服务部署描述符(Web Service Deployment Descriptor,WSDD)的文件提供一种简易的安装机制。WSDD 是 Axis 定义的一种 XML 格式,它定义了 Web 服务的安装参数。
清单 6中展示了天气 Web 服务的 WSDD。
清单 6. 天气服务的 WSDD
<!-- This file deploys the weather Web Service onto an Apache Axis server ->
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- Services from Weather service -->
<service name="weather" provider="java:RPC" style="rpc" use="encoded">
<parameter name="wsdlTargetNamespace" value="urn:weather"/>
<parameter name="wsdlServiceElement" value="WeatherService"/>
<parameter name="wsdlServicePort" value="weather"/>
<parameter name="className" value="weather.ws.WeatherSoapBindingImpl"/>
<parameter name="wsdlPortType" value="Weather"/>
<operation name="getWeather"
qname="operNS:getWeather"
xmlns:operNS="urn:weather"
returnQName="getWeatherReturn"
returnType="rtns:Forecast"
xmlns:rtns="http://weather" >
<parameter name="in0"
type="tns:string"
xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
</operation>
<parameter name="allowedMethods" value="getWeather"/>
<parameter name="scope" value="Session"/>
<typeMapping
xmlns:ns="http://weather"
qname="ns:Forecast"
type="java:com.pushtotest.Forecast"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
<service name="forecast" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.pushtotest.forecast.Forecast"/>
<beanMapping
qname="myNS:Forecast"
xmlns:myNS="urn:ForecastService"
languageSpecificType="java:com.pushtotest.forecast.ForecastBean"/>
</service>
|
有两种通过这个 WSDD 文件安装 Web 服务的方法。Axis 运行时,请在 shell 的命令行使用:
java org.apache.axis.client.AdminClient deploy.wsdd
|
如果 Axis 没有运行的话,请在 shell 命令行使用:
java org.apache.axis.utils.Admin server deploy.wsdd
|
试着在 Apache Axis 1.1 release candidate 2(rc2)上安装 Web 服务时,我发现 Axis 会在部署天气 Web 服务时抛出异常。Axis 在安装时报告“class not found”问题。检查 Axis 用户邮件发送清单时,我发现在 Axis 1.1 rc2 与 Apache Tomcat 4.0.3 之间存在不兼容性。编写本文时,我还没有收到过其他 Axis 用户就该问题的变通方法的来信。因此我在这提供一下我自己的变通方法。将下面的配置代码片断(
清单 7 中所示)添加到
servlet_container/webapps/axis/WEB-INF/server-config.wsdd 上的 Axis 配置文件。
清单 7. 代码片断
<service name="weather" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.pushtotest.weather"/>
<beanMapping
qname="myNS:Forecast"
xmlns:myNS="urn:ForecastService"
languageSpecificType="java:com.pushtotest.Forecast"/>
</service>
|
这就手工地将天气 Web 服务添加到了 Axis,同时将响应中的 Forecast 对象映射到了 Apache Axis BeanSerializer 对象。BeanSerializer 提供所有遵循 JavaBean 模式的对象的 SOAP RPC 编码(先前描述过)。
根据您用来安装该天气 Web 服务的方法,应该重新启动 Axis 服务以使 Web 服务可用。
PushToTest 在它免费的
http://examples.pushtotest.com 服务上提供了天气 Web 服务来帮助开发人员、QA 技术员以及 IT 经理理解隐藏在测试 Web 服务可伸缩性、性能以及功能后面的概念。要想查看那里所托管的服务,请浏览这个 URL
http://examples.pushtotest.com:92/axis/servlet/AxisServlet 。您应该看到天气服务提供了一个单独 getWeather 方法。
目前为止,我已经描述了天气 Web 服务的实现细节。您也能够构建天气 Web 服务并将它部署到 Apache Axis 服务器上了。接下来就是构建客户机端的工作。
客户机端
许多 SOAP 库都可用来构建天气 Web 服务的客户机端。本文将展示 TestMaker,一个本机支持基于 SOAP 的 Web 服务的测试框架和工具。另外还将展示为简化测试 Web 服务可伸缩性、性能和功能而设计的 TestMaker 环境。如果想了解详细情况,请参阅下面的
参考资料。
TestMaker 是构建智能测试代理的框架和实用程序。TestMaker 带有一个名为面向测试对象库(Test Object Oriented Library,TOOL)的协议处理程序库。TestMaker 测试代理脚本是用 Jython(用 Java 完整实现的 Python 语言)编写的。Jython 脚本实例化 TOOL 协议处理程序对象。当 SOAP 协议处理程序需要构造一个发送到主机的请求时,TestMaker 使用自己所包括的 Apache SOAP 栈对请求和响应进行数据编组与数据编出。
这个服务的 WSDL 表明客户机可以通过
http://examples.pushtotest.com:92/axis/servlet/AxisServlet 这个 URL 访问该服务。请求必须包含一个单独 String 对象,保存一个 U.S. 邮编。考虑到本文的目的,天气 Web 服务并不真的去查看天气情况,而是把返回的 Forecast 对象的邮编返回。
清单 8中列出了带有逐步说明的完整的 TestMaker 测试代理脚本。该脚本名为 SOAP_BeanSerializer.a,可以在
参考资料部分下方的下载文档参考信息中找到。
清单 8. TestMaker 脚本
# Import tells TestMaker where to find Tool objects
from com.pushtotest.tool.protocolhandler import ProtocolHandler,
SOAPProtocol, SOAPBody, SOAPHeader
from com.pushtotest.tool.response import Response
from java.lang import Long, Integer, String
from com.pushtotest import Forecast
# These classes are provided by the Apache SOAP library
from org.apache.soap.encoding.soapenc import BeanSerializer
from org.apache.soap.util.xml import QName
from org.apache.soap import Constants
print "Agent started."
protocol = ProtocolHandler.getProtocol("soap")
body = SOAPBody()
protocol.setBody(body)
protocol.setHost("examples.pushtotest.com")
protocol.setPath("axis/servlet/AxisServlet")
protocol.setPort( 92 )
# Send a request to the Forecast.getForecast() method on the host
body.setTarget("weather")
body.setMethod("getWeather")
# The service accepts a zip code parameter. The service will response with
# a Java Bean containing the forecast (which is made-up for this example.)
body.addParameter( "ziprq", String, "95008", None )
# Tells the Apache SOAP library to use the BeanSerializer when it receives
# a response from the ForecastService.
beanSer = BeanSerializer()
qName = QName("urn:ForecastService", "Forecast")
protocol.setMapTypes( Constants.NS_URI_SOAP_ENC, qName, Forecast, beanSer, beanSer )
response = protocol.connect()
print "Response from host:"
print response
print "Ended."
|
TestMaker 脚本以使用指定 TOOL 库中对象的导入命令以及稍后在脚本中使用到的 Apache SOAP 库为起始:
# Import tells TestMaker where to find Tool objects
from com.pushtotest.tool.protocolhandler import ProtocolHandler,
SOAPProtocol, SOAPBody, SOAPHeader
from com.pushtotest.tool.response import Response
from java.lang import Long, Integer, String
from com.pushtotest import Forecast
# These classes are provided by the Apache SOAP library
from org.apache.soap.encoding.soapenc import BeanSerializer
from org.apache.soap.util.xml import QName
from org.apache.soap import Constants
|
对象导入后,该脚本实例化协议处理程序对象:
protocol = ProtocolHandler.getProtocol("soap")
|
该脚本实例化一个新的 SOAP 协议处理程序。这个处理程序由
protocol变量引用:
body = SOAPBody()
protocol.setBody(body)
|
该脚本实例化一个新的 SOAPBody 对象来保存邮编参数,这个参数在对天气 Web 服务的请求中发送。
该脚本通过使用 URL、路径以及端口号对主机进行识别,确定在哪里找到这个天气 Web 服务:
protocol.setHost("examples.pushtotest.com")
protocol.setPath("axis/servlet/AxisServlet")
protocol.setPort( 92 )
|
该脚本将主机上 weather 对象的 getWeather 方法指定为该 Web 服务的请求的目标:
body.setTarget("weather")
body.setMethod("getWeather")
|
Web 服务接收一个在简单 String 对象中已编码的邮编参数:
body.addParameter( "ziprq", String, "95008", None )
|
addparameter 方法会提供许多灵活性。例如,如果天气 Web 服务接收了一个 Forecast 对象而不是通过 Forecast 对象响应,您可以使用这个命令:
body.addParameter( "theForecast", Forecast, myForecast, None )
|
这会告知 TOOL 对 myForecast 对象(一个 Forecast 对象类型)进行编码并将它发送到主机。换言之,任何对象(Jython 或 Java)都可以通过 TOOL 的 addParameter 方法进行数据编组。
如果没有通过任何附加配置就指示脚本构造该天气 Web 服务的请求,客户机端上的 TestMaker SOAP 栈将抛出一个如
清单 9所示的异常。
清单 9. 异常
com.pushtotest.tool.ToolException: Error making SOAP RPC call: No Deserializer found to
deserialize a 'urn:ForecastService:Forecast'
using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'.
at com.pushtotest.tool.protocolhandler.SOAPProtocol.soapRpcCall(SOAPProtocol.java:297)
at com.pushtotest.tool.protocolhandler.SOAPProtocol.connect(SOAPProtocol.java:254)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java)
at org.python.core.PyMethod.__call__(PyMethod.java)
at org.python.core.PyObject.__call__(PyObject.java)
at org.python.core.PyInstance.invoke(PyInstance.java)
at org.python.pycode._pyx5.f$0(D:\\agents\\Serializers\\SOAP_BeanSerializer.a:52)
at org.python.pycode._pyx5.call_function(D:\\agents\\Serializers\\SOAP_BeanSerializer.a)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyCode.call(PyCode.java)
at org.python.core.Py.runCode(Py.java)
at org.python.core.__builtin__.execfile_flags(__builtin__.java)
at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java)
at com.pushtotest.testmaker_module.agentRunner$1$Job.run(Unknown Source)
at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:119)
com.pushtotest.tool.ToolException: com.pushtotest.tool.ToolException: Error making
SOAP RPC call: No Deserializer found to
deserialize a 'urn:ForecastService:Forecast'
using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'.
|
客户机端上的 TestMaker SOAP 栈不知道如何处理来自天气 Web 服务的响应中的 Forecast 对象。序列化对象会将 XML 响应映射入 Java 对象。
幸运的是,如同前面服务器端上的 Apache Axia 一样,Apache Soap 库也包括一个 BeanSeializer 类。通过添加几行 TestMaker 脚本,TestMaker 中的 Apache SOAP 库将使用 BeanSerializer 类对响应中的 Forecast 对象进行数据编出。
先前,这个代理脚本使用了下列代码导入 Forecast 对象:
from com.pushtotest import Forecast
|
这告知类装入器浏览 TestMaker 类路径查找 com.pushtotest.Forecast 对象。TestMaker 通过维持它自己的类路径来简化远程运行 PushToTest 同类产品中相同的测试代理(称为 TestNetWork)。在下面的
参考资料部分可以找到 TestNetwork 的相关信息。
Forecast 对象被编译到先前已加载到 Apache Axis 主机的 weather.jar 脚本。TestMaker 目前在客户机端上引用同样的 weather.jar 对象。为此,编辑
testmaker_home/testmaker/bin/runide.cfg 文件并添加:
-cp:a D:/agents/Serializers/dist/weather.jar
|
您需要修改一下路径以匹配运行 TestMaker 的机器上的配置。
SOAP_BeanSerializer.a 脚本中的下一步骤是告知 TestMaker 如何处理来自天气 Web 服务的响应中的 Forecast Java Bean。
beanSer = BeanSerializer()
qName = QName("urn:ForecastService", "Forecast")
protocol.setMapTypes( Constants.NS_URI_SOAP_ENC, qName, Forecast, beanSer, beanSer )
|
这告知 Apache SOAP 库在接收来自天气 Web 服务的 Forecast 复杂对象类型的响应时使用 BeanSerializer。
connect 方法指示 TOOL 协议处理程序对请求进行数据编组,并通知天气 Web 服务主机:
response = protocol.connect()
|
connect 方法完成后会返回一个新的响应对象:
print "Response from host:"
print response
|
请参阅有关 TOOL 的文档获得响应对象中所提供的方法的完整清单。为简洁起见,这个脚本只打印 response 对象以显示 Forecast JavaBean 组件的内容。
TestMaker 的输出窗口中,天气 Web 服务主机的成功调用将如
清单 10所示。
清单 10. 天气 Web 服务主机的成功调用
Agent running: SOAP_BeanSerializer.a
Description:
SOAP-based Web Services may send and receive complex datatypes. This agent
accesses a Web Service that returns a Java Bean containing several values.
The script uses the Apache SOAP BeanSerializer to unmarshal the Java Bean
encoded response from the examples.pushtotest.com host.
Agent started.
Response from host:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:getWeatherResponse
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="weather">
<getWeatherReturn href="#id0"/>
</ns1:getWeatherResponse>
<multiRef id="id0" SOAP-ENC:root="0"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns3:Forecast" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/:encodingStyle"
xmlns:ns3="urn:ForecastService">
<date xsi:type="xsd:string">April 11, 2003</date>
<zip xsi:type="xsd:string">95008</zip>
<city xsi:type="xsd:string">Campbell</city>
<state xsi:type="xsd:string">CA</state>
<forecast xsi:type="xsd:string">20 percent chance of rain.</forecast>
<low xsi:type="xsd:byte">0</low>
<hi xsi:type="xsd:byte">0</hi>
<precip xsi:type="xsd:byte">0</precip>
</multiRef>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Ended.
|

 |

|
结束语
本文阐述了在 Web 服务中使用复杂数据类型的技术。在服务器端,您使用 Apache Axis 创建接收简单数据类型的 Web 服务,并通过被编码成复杂数据类型的 JavaBean 组件响应。在客户机端,您使用 TestMaker — 然后它会使用 Apache SOAP — 来发送请求并接收 JavaBean 组件。
参考资料
关于作者  | |  | 当企业需要测试与解决复杂交互操作信息系统中的问题,特别是 Web 服务方面的问题时,Frank Cohen 就是那位“擅长解决问题”的人。Frank 是 PushToTest(一种测试自动解决方案业务)的奠基人,编著过几本有关测试信息系统的书。在过去的 20 年中,他主导开发过软件业最为成功的一些产品,有 Norton Utilities Macintosh 版、Stacker 以及 SoftWindows。他开始时为微型机写操作系统,帮助建立视频游戏产业,帮助建立 Norton Utilities 特许,领导 Apple 进入中间件和因特网技术领域的工作并且在最近担任 Sun Community Server、Inclusion.net(OTC: IINC)和 TuneUp.com 的主要设计师。他是软件开发人员论坛(加州硅谷中主要的计算机软件业协会)的积极分子和前董事会成员。您可以通过
fcohen@pushtotest.com与 Frank 联系。
|
对本文的评价
|