Web Service 序列化和反序列化故障诊断技巧

使用这些技巧对执行 Web Service 序列化和反序列化时遇到的问题进行故障诊断。

本主题中的每个部分描述一个问题,这些问题在序列化和反序列化 Web Service 时可能遇到。还提供了有助于对问题进行故障诊断的解决方案。

在反序列化的 java.util.Calendar 中的时区信息与预期的不同

如果客户机和服务器都是基于 Java™ 代码,那么在接收 java.util.Calendar 实例时,接收到的 java.util.Calendar 实例中的时区可能与发送的 java.util.Calendar 实例中的时区不同。

存在这种差别的原因是 java.util.Calendar 被编码为 xsd:dateTime 以进行传输。编码正确时间(基本时间加或减时区偏移量)需要 xsd:dateTime,但不需要它也能保存语言环境信息(包括原始时区)。

当比较日历实例时要考虑到未保存当前语言环境的时区这个事实。java.util.Calendar 类 equals 方法在确定相等性时检查时区是否相同。因为反序列化的日历实例中的时区可能不匹配当前语言环境,所以使用 before 和 after 比较方法来测试两个日历是否引用相同的日期和时间,如以下示例所示:
java.util.Calendar c1 = ...// Date and time in time zone 1
java.util.Calendar c2 = ...// Same date and equivalent time, but in time zone 2

// c1 and c2 are not equal because their time zones are different
if (c1.equals (c2)) System.out.println("c1 and c2 are equal");

// but c1 and c2 do compare as "not before and not after" since they represent 
the same date and time
if (!c1.after(c2) & !c1.before(c2) {
			System.out.println("c1 and c2 are equivalent");
}

混合 Web Service 客户机和服务器绑定导致错误

对于所有 Java 类型,Java 平台企业修订版 (Java EE) 的 Web Service 和“针对基于 XML 的远程过程调用的 Java API”(JAX-RPC) 规范都不支持 Java 代码和 Web 服务描述语言 (WSDL) 文档之间的来回映射。例如,不能将 Java 日期转移或序列化为 XML 代码,然后又转回或反序列化为 Java 日期。此操作将 XML 代码反序列化为 Java 日历。

如果从 Java 实现创建了 WSDL 文档,然后又从 WSDL 文档生成客户机绑定,那么即使客户机类与服务器类的包名和类名相同,客户机类与服务器类也可能不同。Web Service 客户机类必须与 Web Service 服务器类分开。例如,不要在实用程序 Java 归档 (JAR) 文件中放置 Web Service 服务器绑定类之后,还在该实用程序中包含引用同一实用程序 JAR 文件的 Web Service 客户机 JAR 文件。

如果没有将 Web Service 客户机类和服务器类分开,那么根据所用的 Java 类,可能会发生多种异常。以下是可能发生的样本堆栈跟踪错误:
com.ibm.ws.webservices.engine.PivotHandlerWrapper TRAS0014I: The following exception was 
loggedjava.lang.NoSuchMethodError: com.ibm.wssvt.acme.websvcs.ExtWSPolicyData:
   method getStartDate()Ljava/util/Date;
not found 
at com.ibm.wssvt.acme.websvcs.ExtWSPolicyData_Ser.addElements(ExtWSPolicyData_Ser.java: 210)
at com.ibm.wssvt.acme.websvcs.ExtWSPolicyData_Ser.serialize (ExtWSPolicyData_Swer.java:29)
at com.ibm.ws.webservices.engine.encoding.SerializationContextImpl.serializeActual (SerializationContextImpl.java 719)
at com.ibm.ws.webservices.engine.encoding.SerializationContextImpl.serialize (SerializationContextImpl.java: 463)
该问题是由在服务实现中对服务端点接口使用如下的接口所致:
package server:
public interface Test_SEI extends java.rmi.Remote {
	public java.util.Calendar getCalendar () throws java.rmi.RemoteException;
	public java.util.Date getDate() throws java.rmi.RemoteException;
}
当通过 Java2WSDL 命令行工具编译和运行此接口时,WSDL 文档按以下示例映射方法:
<wsdl:message name="getDateResponse">
	<wsdl:part name="getDateReturn" type="xsd:dateTime"/>
</wsdl:message>

<wsdl:message name="getCalendarResponse">
	<wsdl:part name="getCalendarReturn" type="xsd:dateTime"/>
</wsdl:message>
Java2WSDL 工具实现的 JAX-RPC 映射已将 java.util.Date 和 java.util.Calendar 实例都映射到 XML 类型 xsd:dateTime。下一步是使用生成的 WSDL 文件为 Web Service 创建客户机。当在生成的 WSDL 上运行 WSDL2Java 工具时,生成的类包括另一版本的 server.Test_SEI 接口,例如:
package server;
public interface Test_SEI extends java.rmi.Remote {
	public java.util.Calendar getCalendar() throws java.rmi.RemoteException;
	public java.util.Calendar getDate() throws java.rmi.RemoteException;
}

service.Test_SEI 接口的客户机版本与服务器版本不同,在服务器版本中,getCalendargetDate 方法都返回 java.util.Calendar。客户机预期的序列化和反序列化代码是服务端点接口的客户机版本。如果由于疏忽,在编译或运行时间服务器版本包含在客户机的 CLASSPATH 变量中,那么会发生错误。

除了 NoSuchMethod 错误,还可能发生 IncompatibleClassChangeErrorClassCastException。但是,几乎任何运行时异常都可能发生。最佳实践是认真地将客户机 Web Service 绑定类与服务器 Web Service 绑定类分开。客户机绑定类和服务器绑定类永远应该放置在不同的模块中。如果这些绑定类在同一应用程序中,那么将绑定类放置在模块之间不共享的实用程序 JAR 文件中。


指示主题类型的图标 参考主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rwbs_trbserialize
文件名:rwbs_trbserialize.html