このトピックでは、Web サービスでシリアライゼーションおよびデシリアライゼーションを実行する際に生じる可能性のある問題について論じます。
このトピックの各セクションでは、 Web サービスをシリアライズおよびデシリアライズする際に経験する可能性のある問題を取り上げます。 また、それらの問題のトラブルシューティングに役立つ解決策が 提示されています。
クライアントおよびサーバーが Java コードに基づいており、java.util.Calendar インスタンスが受信される場合、 受信した java.util.Calendar インスタンスの時間帯は、送信された java.util.Calendar インスタンスの時間帯と異なる場合があります。
このようは違いが生じるのは、 java.util.Calendar が伝送用に xsd:dateTime としてエンコードされるためです。xsd:dateTime は、 正しい時刻 (基本時刻プラス (またはマイナス) 時間帯オフセット) をエンコードするために必要ですが、 元の時間帯を含むロケール情報の保存には必要ありません。
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"); }
Java 2 Platform, Enterprise Edition (J2EE) 仕様 および Java API for XML-based remote procedure call (JAX-RPC) 仕様向けの Web サービスでは、 Java コードと、すべての Java タイプに対する Web サービス記述言語 (WSDL) 文書の間の 往復 マッピングはサポートされていません。 例えば、 Java Date を XML コードに変換 (つまりシリアライズ) して、その後 Java DATE に戻す (つまりデシリアライズする) ことはできません。 このアクションは、Java Calendar としてデシリアライズされます。
WSDL 文書を作成する Java インプリメンテーションがあり、WSDL 文書からクライアント・バインディングを生成する場合、 クライアント・クラスが同じパッケージ名およびクラス名を持つ場合であっても クライアント・クラスをサーバー・クラスとは別にできます。Web サービス・クライアント・クラスは、Web サービス・サーバー・クラスとは 分離されている必要があります。例えば、Java アーカイブ (JAR) ファイルに Web サービス・サーバー・バインディング・クラスを配置して、 同じユーティリティー JAR ファイルを参照する Web サービス・クライアント JAR ファイルを 組み込まないでください。
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 サービスのクライアントを作成する方法です。 生成された 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.Date getDate() throws java.rmi.RemoteException; }
service.Test_SEI インターフェースのクライアント・バージョンは、 getCalendar メソッドと getDate メソッドの両方が java.util.Calendar を戻すという点で、 サーバー・バージョンとは異なります。 クライアントに必要なシリアライゼーショ ンおよびデシリアライゼーション・コードは、サービス・エンドポイント・インターフェースのクライアント・バージョンです。 コンパイル時または実行時に、 サーバー・バージョンがクライアントの CLASSPATH 変数内に誤って表示された場合、エラーが発生します。
NoSuchMethod エラーに加えて、 IncompatibleClassChangeError および ClassCastException も発生する場合があります。 ただしこのような場合には、どんな実行時例外が発生してもおかしくあり ません。ベスト・プラクティスは、 常に、クライアント Web サービス・バインディング・クラスとサーバー Web サービス・バインディング・クラス を分離するように心がけることです。クライアント・バインディング・クラスとサーバー・バインディング・クラスは、 必ず別々のモジュールに入れるようにしてください。 これらのバインディング・クラスが同じアプリケーション内にある場合は、 モジュール間で共有されていないユーティリティー JAR ファイルにバインディング・クラスを入れてください。