139 lines
6.7 KiB
HTML
139 lines
6.7 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||
|
<html>
|
||
|
<head>
|
||
|
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||
|
<LINK rel="stylesheet" type="text/css" href="../../../rzahg/ic.css">
|
||
|
|
||
|
<title>Troubleshoot: Serialization and deserialization in Web services</title>
|
||
|
</head>
|
||
|
|
||
|
<BODY>
|
||
|
<!-- Java sync-link -->
|
||
|
<SCRIPT LANGUAGE="Javascript" SRC="../../../rzahg/synch.js" TYPE="text/javascript"></SCRIPT>
|
||
|
|
||
|
<h2><A NAME="wstrbserialize">Troubleshoot: Serialization and deserialization in Web services</A></h2>
|
||
|
|
||
|
<p>The following are problems you might encounter performing serialization
|
||
|
and deserialization in Web services that are developed and implemented based
|
||
|
on the Web Services for Java 2 platform Enterprise Edition (J2EE) specification.</p>
|
||
|
|
||
|
<p><strong>Time zone information in deserialized java.util.Calendar is
|
||
|
not as expected</strong></p>
|
||
|
|
||
|
<p>When the client and server are based on Java code
|
||
|
and a <tt>java.util.Calendar</tt> object is received, the time zone in the received <tt>java.util.Calendar</tt> instance
|
||
|
might be different from that of the <tt>java.util.Calendar</tt> instance that
|
||
|
was sent.</p>
|
||
|
|
||
|
<p>This occurs because <tt>java.util.Calendar</tt> is encoded
|
||
|
as an xsd:dateTime for transmission. An xsd:dateTime is required to encode
|
||
|
the correct time (base time plus or minus a time zone offset), but is not
|
||
|
required to preserve locale information, including the original time zone.</p>
|
||
|
|
||
|
<p>The fact that the time zone for the current locale is not preserved needs to be
|
||
|
accounted for when comparing Calendar instances. The <tt>java.util.Calendar </tt> class
|
||
|
equals method checks that the time zones are the same when determining equality.
|
||
|
Since the time zone in a deserialized Calendar instance might not match the
|
||
|
current locale, the before and after comparison methods should be used to
|
||
|
test that two Calendars refer to the same date and time as shown below:</p>
|
||
|
<pre>
|
||
|
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");
|
||
|
}</pre>
|
||
|
|
||
|
<p><strong>Mixing Web services client and server bindings
|
||
|
causes exceptions</strong></p>
|
||
|
|
||
|
<p>Web Services for J2EE and Java API for XML-based
|
||
|
remote procedure call (JAX-RPC) do not support "round-trip" mapping between
|
||
|
Java code and a Web Services Description Language (WSDL) document for all
|
||
|
Java types. For example, you cannot turn (serialize) a Java Date into XML
|
||
|
code and then turn it back (deserialize) into a Java Date. It deserializes
|
||
|
as Java Calendar.</p>
|
||
|
|
||
|
<p>If you have a Java implementation that you create
|
||
|
a WSDL document from, and you generate client bindings from the WSDL document,
|
||
|
the client classes can be different from the server classes even though the
|
||
|
client classes have the same package and class names. The Web service client
|
||
|
classes must be kept separate from the Web service server classes. For example,
|
||
|
do not place the Web service server bindings classes in a utility Java archive
|
||
|
(JAR) file and then include a Web service client JAR file that references
|
||
|
the same utility JAR file.</p>
|
||
|
|
||
|
<p>If you do not keep the Web service client
|
||
|
and server classes separate, a variety of exceptions can occur, depending
|
||
|
on the Java classes used. The following is a sample stack trace error that
|
||
|
can occur:</p>
|
||
|
<pre>
|
||
|
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)
|
||
|
</pre>
|
||
|
|
||
|
<p>The problem is caused by using an interface like the following for the Service
|
||
|
Endpoint Interface in the service implementation:</p>
|
||
|
<pre>
|
||
|
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;
|
||
|
}
|
||
|
</pre>
|
||
|
<p>When this interface is compiled and run through the <strong>Java2WSDL</strong> command-line
|
||
|
tool, the WSDL document maps the methods as follows:</p>
|
||
|
<pre>
|
||
|
<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>
|
||
|
</pre>
|
||
|
|
||
|
<p>The JAX-RPC mapping implemented by the <strong>Java2WSDL</strong> tool
|
||
|
has mapped both <tt>java.util.Date</tt> and <tt>java.util.Calendar</tt> to
|
||
|
the XML type xsd:dateTime. The next step is to use the generated WSDL file
|
||
|
to create a client for the Web service. When you run the <strong>WSDL2Java</strong> command-line
|
||
|
tool on the generated WSDL, the generated classes include a different version
|
||
|
of server.Test_SEI, for example:</p>
|
||
|
<pre>
|
||
|
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;
|
||
|
}
|
||
|
</pre>
|
||
|
<p><strong>Note:</strong> The client version of the <tt>service.Test_SEI</tt> interface
|
||
|
is different from the server version in that both <tt>getCalendar</tt> and <tt>getDate</tt> methods
|
||
|
return <tt>java.util.Calendar</tt>. The serialization and deserialization
|
||
|
code that the client expects is the client version of the SEI. If the server
|
||
|
version inadvertently appears in the client's CLASSPATH, at either compilation
|
||
|
or execution time, an exception occurs.</p>
|
||
|
|
||
|
<p>In addition to the<tt>NoSuchMethod</tt> error,
|
||
|
the <tt>IncompatibleClassChangeError </tt>and <tt>ClassCastException </tt> can
|
||
|
occur, however, almost any run-time exception can occur. The best practice
|
||
|
is to be diligent about separating client Web services bindings classes from
|
||
|
server Web services bindings classes. The client bindings classes and server
|
||
|
bindings classes should never be placed in the same module and, if they are
|
||
|
in the same application, should not have bindings classes in utility JAR files
|
||
|
that are shared between modules.</p>
|
||
|
|
||
|
</body>
|
||
|
</html>
|