Troubleshoot serialization and deserializaton in Web services based on Web Services for J2EE

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 J2EE.

 

Time zone information in deserialized java.util.Calendar is not as expected

When the client and server are based on Java code and a java.util.Calendar is received, the time zone in the received java.util.Calendar instance might be different from that of the java.util.Calendar instance that was sent.

This occurs because java.util.Calendar 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.

The fact that the time zone for the current locale is not preserved needs to be accounted for when comparing Calendar instances. The java.util.Calendar 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

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");
}

 

Mixing Web services client and server bindings causes exceptions

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 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.

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.

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

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)

The problem is caused by using an interface like the following for the Service Endpoint Interface in the service implementation

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;
}
When this interface is compiled and run through the Java2WSDL command-line tool, the WSDL document maps the methods as follows

<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>
The JAX-RPC mapping implemented by the Java2WSDL tool has mapped both java.util.Date and java.util.Calendar 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 WSDL2Java command-line tool on the generated WSDL, the generated classes include a different version of server.Test_SEI, for example

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;
}

Note: The client version of the service.Test_SEI interface is different from the server version in that both getCalendar and getDate methods return java.util.Calendar. The serialization and deserilazation 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.

In addition to theNoSuchMethod error, the IncompatibleClassChangeError and ClassCastException 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.

 

See Also

Troubleshooting Web services based on Web Services for J2EE