このシリーズの第1回の記事では、SOAPがどのようにしてデータ型をXMLにマップするのかを示し、Apache SOAPツールキットに組み込まれているシリアライザーおよびデシリアライザー (以後、両者をまとめて「(デ)シリアライザー」と呼びます) の使用方法を示しました。今回は、ユーザー独自の(デ)シリアライザーを作成するための調理法を紹介することにします。参照のために、いくつかの基本(デ)シリアライザーの元になる素材を用意しておくとよいでしょう。また、型マッピングがシステム内でどのように解決されるのかを再確認するために、第1回の『型マッピングのパターン』のセクションを読み返してください。
調理法の説明の後で、スキーマで制約されたSOAPをインプリメントする簡単なアプリケーションを紹介します。このアプリケーションが行なう通信においては、セクション4エンコード方式に準拠しない購入注文文書を、意図的にSOAPを使用して送信しています。
Apache SOAPツールキットにバンドルされた(デ)シリアライザーが、いずれもユーザーのJavaクラスに使えない場合には、ユーザー自身でカスタム・(デ)シリアライザーを作成する必要があります。まず、私がルート・(デ)シリアライザー と呼んでいるものと、通常の(デ)シリアライザー と呼んでいるものを区別していただく必要があります。RPCのパラメーターおよび応答のシリアライゼーションとデシリアライゼーションの初期ブートストラッピングは、ルート・(デ)シリアライザーによって処理されます。表1 に、Apache SOAPにおける3つのルート・(デ)シリアライザーをリストしておきます。
表1. ルート・(デ)シリアライザー
| エンコーディング・スタイル | (デ)シリアライザー |
|---|---|
| セクション5 |
ParameterSerializer
|
| リテラルXML |
XMLParameterSerializer
|
| XMI |
XMIParameterSerializer
|
該当のルート・(デ)シリアライザーは、encodingStyle と、クラスParameter (シリアライゼーションの場合)、またはQNameSOAP-ENV:Parameter (デシリアライゼーションの場合) との2つに基づいてディスパッチされます。実際のディスパッチングがどのように行なわれるのかを知るためには、クライアント・サイドにおけるJavaタイプのシリアライゼーションに至る、一連のイベントを理解しておく必要があります。
Call call = new Call(); ... resp = call.invoke(url, ""); //1 |
上記の行1 (//1) でCall クラスのinvoke メソッドが呼び出されると、Call クラスは、関連付けられたパラメーターを繰り返して処理します。
org.apache.soap.rpc.RPCMessage:
...
Serializer ser = xjmr.querySerializer(Parameter.class, actualParamEncStyle); //2
ser.marshall(...);
...
|
それぞれのパラメーターごとに、タイプをマップするレジストリーが照会され、その後で、戻されたシリアライザーのmarshall() メソッドが呼び出されます。行2で戻されるシリアライザーはルート・シリアライザーです。
ここで、Webサービスにおけるデシリアライゼーション・プロセスに注目してみましょう。サーバー・サイドでは、SOAP RPCメッセージのリスナーはサーブレットとしてインプリメントされています。doPost メソッドはSOAP要求を検索し、それをもとにCall オブジェクトの再構成を試みます。
org.apache.soap.rpc.RPCMessage:
...
Bean paramBean = smr.unmarshall(actualParamEncStyle, RPCConstants.Q_ELEM_PARAMETER
...); //3
Parameter param = (Parameter)paramBean.value;
...
|
行3では、RPCConstants.Q_ELEM_PARAMETER の値はSOAP-ENV:Parameter となります。ルート・デシリアライザーへのディスパッチングが行なわれるのは、unmarchal() メソッドが呼び出されたとき、すなわちこの行3においてです。
次に、ルート・(デ)シリアライザーは、タイプをマップするレジストリーを照会し、次に呼び出す通常の(デ)シリアライザーを探し出します。この呼び出しは、(シリアライゼーションの実行中に) レジストリーがプリミティブJavaタイプに対する(デ)シリアライザーを戻すとき、または (デシリアライゼーションの実行中に) XMLエレメントが単純タイプに対するコンテナーであるときにだけ開始されます。
提供された通常の(デ)シリアライザー (これらは、パッケージorg.apache.soap.encoding.soapenc に収められています) の大部分は、Apache SOAPにおけるほとんどのヘルパー・クラスと同様に、セクション5のエンコード方式を処理します。私がセクション5のエンコード方式による(デ)シリアライザーに焦点をしぼって説明するのは、このためです。
図1. (デ)シリアライザーを作成するためのAPI
シリアライザーはorg.apache.soap.util.xml.Serializer をインプリメントし、単一のメソッドを認識します。
void marshall(
java.lang.String inScopeEncStyle,
java.lang.Class javaType,
java.lang.Object src,
java.lang.Object context,
java.io.Writer sink,
NSStack nsStack,
XMLJavaMappingRegistry xjmr,
SOAPContext ctx)
throws java.lang.IllegalArgumentException,
java.io.IOException
|
次に、marshall() の各パラメーターについて調べてみましょう。
-
inScopeEncStyle: これは、外側のCallまたはResponseオブジェクトで指定されたとおりにencodingStyleURIを表します。 -
javaType: これは、直列化されるオブジェクトの実行時タイプです。 -
src: これは、直列化されるJavaオブジェクトへの参照です。 -
context: アクセサー名を記述するStringです。このシリアライザーがParameterSerializerによって呼び出される場合、コンテキスト値は、(SOAPクライアントで宣言された)Parameterクラス内の名前付きプロパティーと等価になるか、あるいはこれがSOAPサーバーの場合にはreturnにハードコーディングされます。これは、非ヌルでなければなりません。 -
sink: SOAP XMLインスタンスが書き込まれる宛先シンク。 -
nsStack: 現在の有効範囲に含まれているネームスペース宣言のスタックをインプリメントするデータ構造。 -
xjmr: これは、Javaタイプに基づいて次に使用するシリアライザーを照会するために使用する、smrです。javaTypeおよびencodingStyleに基づいて他のシリアライザーに代行させるために、xjmrマーシャル・メソッドも呼び出します。例えば、HashtableやVectorなどの複合構造体の場合には、これを行う必要があります。 -
ctx: これは、サーブレット・コンテキストからjavax.servlet.http.HttpServletRequestやjavax.servlet.http.HttpSessionなどを渡すために使用されます。
marshall() メソッドの使用法は、次のとおりです。
nsStack.pushScope(); |
XMLのネームスペース宣言の有効範囲を管理するには、このNSStack クラスを使用してください。後にこのメソッド内でNSStack を使用することにより、新規ネームスペースを追加したり、スタックからURIが指定された接頭部を探し出したりすることができます。
シリアライゼーションが行なわれるためには、2つの条件が満たされる必要があります。つまり、シリアライザーが、サポートされるタイプになっていなければならず、また、直列化されるオブジェクトが非ヌルでなければなりません。次のコードは、これらの制約がVectorSerializer に課せられるようすを表しています。
if ( (src != null) &&
!(src instanceof Vector) &&
!(src instanceof Enumeration))
throw new IllegalArgumentException("Tried to pass a '" +
src.getClass().toString() + "' to VectorSerializer");
|
組み込みシリアライザーのうちのいくつかは、次のように、javaType パラメーターと予想されたタイプを実際に比較します。
if(!javaType.equals(Foo.class)) ... |
ただし、この技法を使用することはお勧めしません。タイプラベル不一致のバグの影響を招きやすいためです (参考文献を参照してください)。
オブジェクト引数がヌルの場合、そのタイプに対応するヌル・アクセサーを生成する必要があります。
SoapEncUtils.generateNullStructure(inScopeEncStyle, |
オブジェクトをセクション5に準拠するSOAP XML文書に直列化するには3つのステップが必要であり、アクセサーのための開始エレメントの生成、オブジェクトの値の直列化、およびエレメントの終了を行います。
最初のステップは、次のユーティリティー・メソッドを呼び出すことによって、簡単に行なうことができます。
SoapEncUtils.generateStructureHeader(inScopeEncStyle,
javaType,
context,
sink,
nsStack,xjmr);
|
このコードは、queryElementType を呼び出して、javaType 用にマップされたQName を検索します。
<context xsi:type="QName"> |
オブジェクト引数src が単純タイプである場合には、2番目のステップであるオブジェクトの値の直列化は、単純に、src.toString() メソッドを呼び出してそれを書き出すだけで済みます。それ以外の場合、オブジェクトを構成する各部分を識別し、それらをよりプリミティブなシリアライザーに個別に渡す必要があります。組み込みシリアライザーのソースを調べると、これらの構成部分を多くの方法で識別できることが分かります。
- Javaリフレクション (例えば、
BeanSerializer) -
Listデータ構造の反復 (例えば、ArraySerializer) - クラスについての事前知識による直接アクセス (つまり、シリアライザーが1つの特定クラスだけを操作することがあらかじめ分かっている場合)
その他のシリアライザーを識別すると、次のような呼び出しを行なってそれらに代行させることができます。
xjmr.marshall(inScopeEncStyle,
componentType,
componentValue,
accessorName,
sink, nsStack, ctx); |
ここで、componentType とcomponentValue はそれぞれ、オリジナルのsrc パラメーターの構成部分に関する実行時タイプとオブジェクトの参照を表しています。marshall() メソッドは、関連するシリアライザーを検索するために実際にquerySerializer を呼び出し、その後で関連するシリアライザーのmarshall() メソッドを呼び出します。いうまでもなく、この方法を使用できるのは、タイプをマップするレジストリー内のすべてのコンポーネントに関するシリアライザーを登録してある場合にかぎります。
最後のステップであるエレメントの終了は、アクセサーの終了タグを書き出すだけで完了させることができます
sink.write("</" + context + '>'); |
最後に、現行のネームスペース有効範囲を終了させて、クリーンアップしなければなりません。
nsStack.popScope(); |
デシリアライザーはorg.apache.soap.util.xml.Deserializer をインプリメントし、単一のメソッドを認識します。
Bean unmarshall(
java.lang.String inScopeEncStyle,
QName elementType,
org.w3c.dom.Node src,
XMLJavaMappingRegistry xjmr,
SOAPContext ctx)
|
unmarshall() メソッドの目的は、パラメーターをJavaオブジェクトとして再構成することです。そのためには、src DOMノードによって組み込まれているXMLフラグメントを処理する必要があります。そのためのプログラミング・モデルとしては、org.apache.soap.utils.xml.DOMUtils 内で、タイプをマップするレジストリーと一緒にDOMラッパー・メソッドを使用するとよいでしょう。一般に、デシリアライゼーションにおけるDOMUtils は、シリアライゼーションにおけるSoapEncUtils に相当します。
src に含まれているXMLには、複数参照値が含まれないことが保証されているという点に注目してください。すべての複数参照href は、ルート・デシリアライザーParameterSerializer によって解決され、実際の値に戻されています。
したがって、デシリアライザーの調理法は次のようになります。
次のようにして、属性がヌルであるかどうかを検査するとよいでしょう。
Element root = (Element)src;
if (SoapEncUtils.isNull(root))
{
return new Bean(Your.class, null);
}
|
Javaオブジェクトを再構成するプロセスは、そのデータ型がどのカテゴリーに属するのかによって異なります(これらの型カテゴリーの詳細については、第1回を参照してください)。
単純タイプ
単純タイプをデシリアライゼーションする場合には、戻されるオブジェクトを初期化するためにそれを使用する前に、DOMUtils.getChildCharacterData(Element) を使用してsrc というストリング値を検索し、オプションとしてそのストリング値を再処理してください (例えば、"NaN" をFloatDeserializer 内のFloat.NaN にマップします)。
複合タイプ
複合タイプは、2つのカテゴリーに大別されます。最初のカテゴリーは、エレメントが反復される同一構造のタイプからなります。例えば、java.util.List およびjava.util.Map をインプリメントするJava配列およびクラスがこれに当たります。もう1つのカテゴリーは、任意の構造を示すその他のすべてのJavaクラスを表すものです。したがって、デシリアライゼーション・プロセスとは結局、次のように、XML構造をナビゲーションして関係のある子孫エレメントを識別したうえで、デシリアライゼーション処理をよりプリミティブなデシリアライザーに代行させることにほかなりません。
-
DOMのナビゲート最初のカテゴリーの複合タイプを扱う場合には、
DOMUtils.getFirstChildElement()およびDOMUtils.getNextSiblingElement()を使用して、そのすべての反復メンバーをナビゲートしてください。それ以外の場合には、DOM APIを使用して、メンバー・プロパティーを表すエレメント を識別してください。 -
他のデシリアライザーへのデシリアライゼーションの代行最初に、SOAPタイプを抽出する必要があります。
QName soapType = SoapEncUtils.getTypeQName(rootElement);
次に、さらにプリミティブなデシリアライザーに代行させます。
xjmr.unmarshall(inScopeEncStyle, soapType, rootElement, ctx);
xjmr.unmarshallは内部的にqueryDeserializerを呼び出し、戻されたデシリアライザーでunmarshallを起動します。上記の2つのステップは、デシリアライゼーションをParameterSerializerに代行させることにより、1つにまとめることができます。これが行なわれるのは、xsi:type属性が抜けている場合に、私たちが、soapTypeをQName{""}/Xに設定して (このXは、ルート・エレメントのtagNameです)xjmr.unmarshall()を起動しようとするからです。これを行なうためのコードは、すでにParameterSerializer.unmarshall()の中に便利な形でパッケージ化されているため、このプロセスを短縮すると次のようになります。Bean paramBean = xjmr.unmarshall(inScopeEncStyle, RPCConstants.Q_ELEM_PARAMETER, rootElement, ctx);
-
ターゲット・オブジェクトの初期化ターゲット・オブジェクト は、再構成の対象となるオブジェクト・インスタンスです。メンバー・プロパティーがデシリアライゼーションされた後で、次のようにターゲット・オブジェクトでmutatorメソッドを起動して、メンバー・プロパティーの値を復元することができます。
Foo foo = new Foo(); foo.setS( paramBean.value );
Bean クラスは、実行時タイプと実際に戻されたインスタンスをカプセル化します。デシリアライザーは、ほとんどの場合、特定のクラスに特有ですので、どのクラスを戻すべきかを認識します。BeanSerializer やArraySerializer などの一般的なデシリアライザーの場合、タイプのマップにおいてjavaType プロパティーが、戻されるタイプを伝えます。
return(new Bean(Foo.class, foo)); |
カスタムencodingStyles を導入したい場合には、ルート・(デ)シリアライザーを作成しなければならないということはすでに述べました。ルート・(デ)シリアライザーは、1つの小さな相違点を除き、通常の(デ)シリアライザーと同じ方法でインプリメントされます。その相違点とは、すべてのルート・(デ)シリアライザーが、特別に設計されたQNameおよびJavaタイプを使用してタイプをマップするレジストリーに登録される、ということです。このQNameおよびJavaタイプは、Apache SOAPに対し、encodingStyle プロパティーに基づいて(デ)シリアライゼーション・プロセスをブートストラップするように指示します。下記のサンプル・コードの、強調表示された値に注意してください。ルート・(デ)シリアライザーを登録するときには、これらの値を使用する必要があります。
[Client]
smr.mapTypes(customEncURI,
RPCConstants.Q_ELEM_PARAMETER,
Parameter.class,
customSerializer, null);
[Server]
<isd:map encodingStyle="customEncURI"
xmlns:x="http://schemas.xmlsoap.org/soap/envelope" qname="x:Parameter"
javaType="org.apache.soap.rpc.Parameter"
java2XMLClassName="foo.customSerializer" />
|
このセクションでは、複雑なタイプを(非)直列化するための、BeanSerializer の代替ソリューションについて説明します。この技法 (スキーマに制約されたSOAP と呼ぶことにします) では、RPCパラメーターのリテラルXML構造を記述するためにXMLスキーマを使用します。ここでは、クライアントおよびサーバー上のデータ・モデルにかかわらず、メッセージの形式に厳密に従って相互操作することにします。混乱を避けるために、RPC呼び出しは引き続きセクション5を使用してエンコードされますが、パラメーターはそうではないということに注意する必要があります。
この技法を、サンプル・アプリケーションを使用して説明します。後述する参考文献から、その完全なコードをダウンロードすることができます。クライアントはWebサービスに購入注文を送信し、Webサービスが確認通知ストリングでそれに応答します。したがって、このWebサービスによってエクスポートされるメソッド・シグニチャーは、次のようになります。
public String eatPo (PurchaseOrder p); |
この技法が機能するためには、XML/ オブジェクトのデータ結合フレームワークが必要です。この例では、ExolabのCastorツールキットを使用することにします(Castorへのリンクおよびその他の、JSX、JAXB、Schema2Javaなどのシリアライゼーション・フレームワークのリストについては、後述する参考文献セクションを参照してください)。
この技法のステップは、次のとおりです。
-
PurchaseOrderのためのXML形式について合意する。 - Castorを使用してJavaクラスを生成する。
- カスタム・(デ)シリアライザーを作成する。
- 各クライアントおよびサーバーのためのタイプのマップ・コードを記述する
ステップ1: PurchaseOrderのためのXML形式について合意する
このユース・ケースでは、単純化のためにPurchaseOrder スキーマからオーダー詳細情報セクションを除去しました。また、PONumber 属性により、このスキーマがセクション5のエンコード方式に準拠しなくなっていることに注意してください。
図2. PurchaseOrder.xsd
ステップ2: Castorを使用してJavaクラスを生成する
CastorのSourceGenerator コマンド行ツールを実行して、PurchaseOrder.xsd 内のスキーマをインプリメントするJavaクラスを生成します。
java org.exolab.castor.builder.SourceGenerator
-i PurchaseOrder.xsd
-package com.raverun.po.castor
|
SourceGenerator ツールは、最新のスキーマ・ネームスペースであるhttp://www.w3.org/2001/XMLSchema だけを認識します。
次に、Javaクラスのセットをコンパイルします。生成されたファイルはSAX 1.0 APIを使用しますので、-deprecation オプションを使用する必要があります。このような手作業のコンパイルを避けるために、Exolabでは、コンパイルを自動化するためのAnt taskdefを開発中です。
次に、PurchaseOrder クラスで示された対応メソッドを利用して、PurchaseOrderSerializer において(デ)シリアライゼーション・メソッドをインプリメントします。シリアライゼーションの場合、
PurchaseOrder をjava.io.Writer またはorg.xml.sax.DocumentHandler に合わせてマーシャルすることができます。
リスト1 に示すように、PurchaseOrder のmarshal() メソッドにシリアライゼーションを代行させます。1つ注意しなければならないことがあります。それは、
marshal() メソッドによって生成されたXMLストリームにはXMLプロローグが含まれる、ということです。
PurchaseOrderSerializer は、java.io.FilterWriter であるFilterXmlProlog でsink をラッピングすることにより、このプロローグを除去します。
リスト2 には、デシリアライゼーション・プロセスにおいて発生し得るいくつかの例外ケースが含まれています。
リスト1. PurchaseOrderSerializer内のmarshal() メソッドからの抜粋
----o<---------
SoapEncUtils.generateStructureHeader(inScopeEncStyle,
javaType,
context,
sink,
nsStack,
xjmr);
PurchaseOrder po = (PurchaseOrder)src; try{
po.marshal( new FilterXmlProlog(sink) );
}catch(Exception e){ throw (new java.io.IOException("Castor: Error marshalling"));
}
sink.write( StringUtils.lineSeparator );
sink.write("</" + context + '>');
----o<---------
|
リスト2. PurchaseOrderSerializerにおけるデシリアライゼーション中の例外ケース
(b1) Null PO.
---------------------------
<po xmlns:ns2="urn:raverun" xsi:type="ns2:po"
xsi:null="true"/>
---------------------------
(b2) Non null but nothing submitted in the body.
---------------------------
<po xmlns:ns2="urn:raverun" xsi:type="ns2:po" />
---------------------------
(b3) PO that violates the schema.
---------------------------
<po xmlns:ns2="urn:raverun" xsi:type="ns2:po">
<foo bar="123"/>
</po>
---------------------------
|
ステップ4: 各クライアントおよびサーバーのためのタイプのマップ・コードを記述する
最後に、カスタム・(デ)シリアライザーを参照するためにタイプのマップ・コードを宣言する必要があります。PurchaseOrder のためのエンコード方式としてセクション5が指定されているのは、読者にとって意外かもしれません。これは、使いやすさを考慮したためです。このようにすると、ParameterSerializer を使用して、デシリアライゼーション・プロセスをブートストラップしたり、シリアライゼーション・コード内でSoapEncUtils を使用したりすることができます。
[Client]
SOAPMappingRegistry smr = new SOAPMappingRegistry();
smr.mapTypes(Constants.NS_URI_SOAP_ENC,
new QName("urn:raverun", "po"),
PurchaseOrder.class, pos, null);
[Server]
<isd:map
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:raverun" qname="x:po"
javaType="com.raverun.po.castor.PurchaseOrder"
xml2JavaClassName="com.raverun.po.PurchaseOrderSerializer" />
|
スキーマに制約されたSOAPの例を検討する際には、以下の問題に注意してください。
-
標準に準拠するためには、
<po>エレメントにおけるセクション5のエンコード方式に関して何も指定しないでださい(より仕様に準拠したSOAP XMLインスタンスについては、リスト3 を参照してください)。SOAP 1.1仕様 (参考文献を参照) では、この要件が次のように記述されています。ゼロ長のURI ("") の値は、含まれているエレメントのエンコード・スタイルについて何も指定されていないことを明示的に示す。
ヌルの
encodingStyleに対する代替方式として、ユーザーの通信ニーズに合わせて調整したカスタムencodingStyleURIを導入するという手段があります。 -
Castorには、注意すべきバグがいくつかありますが、すべてのバグには回避策が設けられています。0.9.3よりも古いバージョンのCastorを使用している場合には、スキーマ妥当性検査を予期したとおりに行なうことができません。解決策は、最新リリースにアップグレードすることです。その一方で、Castor 0.9.3 (私が使用したバージョン) は、標準出力ストリームに誤ったメッセージを生成します。私が受け取ったメッセージは次のようなものです。
Warning : preserved is a bad entry for the whiteSpace value.
Castorの最新バージョン0.9.3.9では、この警告は生成されません。
-
PurchaseOrderSerializerは、複数参照値には直列化されません。ただし、複数参照値の非直列化は、正しく行ないます。これはPurchaseOrderSerializer自体の機能ではなく、ParameterSerializerの機能です。
リスト3. より仕様に準拠したSOAPインスタンス
<ns1:eatPo xmlns:ns1="urn:poservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<po xmlns:ns2="urn:raverun" xsi:type="ns2:po"
SOAP-ENV:encodingStyle="">
<purchaseOrder xmlns="http://www.example.com/PO1">
<header PONumber="9999-1212">
<Date>2001-09-25T14:40:13.453</Date>
</header>
...
</purchaseOrder>
</po>
</ns1:eatPo>
|
Apache SOAPの最新の公式リリース (バージョン2.2) は2001年3月に登場しました。開発の焦点はAxis (現在はベータ1) に移っていますが、バグ修正は引き続き行なわれています。私たちは2.3リリース (そういうものがあれば) を待っているのですが、公式リリースのユーザーは、特にSOAPMappingRegistry およびその関連クラスについて、コードベースで大きな更新が行なわれたことに注意する必要があります。これらの修正との連係操作を行うには、既存のコードに何らかの変更を加える必要があるでしょう。
注意すべき変更内容を以下にリストします。
- スキーマ・ネームスペースが、デフォルトで2001勧告のネームスペースを参照するようになりました。バージョン2.2では、1999ネームスペースを参照していました。
- したがって、
SOAPMappingRegistryをその引数なしコンストラクターによってインスタンス化すると、2001ネームスペースを認識するインスタンスが戻されます。
-
SOAPMappingRegistryのインスタンス作成が、静的ファクトリー・パターンに合わせて再設計されました。したがって、コンストラクターSOAPMappingRegistry(schemaURI)をオーバーロードする代わりに、ファクトリー・メソッドgetBaseRegistry(schemaURI)を使用するようにしてください。public static SOAPMappingRegistry getBaseRegistry (String schemaURI);
- バージョン2.2では、チェーン・レジストリーの機能が提供されています。最近、以下のメソッドが追加されました。
public SOAPMappingRegistry(SOAPMappingRegistry parent); public SOAPMappingRegistry(SOAPMappingRegistry parent, String schemaURI); public SOAPMappingRegistry getParent() public String getSchemaURI()
タイプのマップを解決する場合には、一致するものが見つかるまで、そのチェーンをたどって行なわれます。
-
DeploymentDescriptorクラスは、タイプのマップ宣言でオプションの属性としてqname属性を扱います。
今回の記事の例により、このシリーズの第1回の記事で概要を示した理論的な概念が明瞭になったことを期待しています。ネットワーク上の多くのマシンを使用して運用されるWebサービスを現実のものとして広く行き渡らせるためには、開発者は、プログラムで扱うオブジェクトが、あるマシンから別のマシンにどのように伝送されるのかを理解していなければなりません。SOAPにおけるタイプのマップ機能をよく理解しておくと、よりすぐれた分散アプリケーションおよびサービスを構築しやすくなります。
-
Apache SOAP は、Javaプログラム言語のためのオープン・ソースのSOAPツールキットです。
-
Apache Axis は、Apache SOAPをしのぐ次世代のツールキットです。
- Brendan MacmillanのJava Serialization to XML (JSX) ツールキットには、いくつかの便利なツールが含まれています。
- SunのJava Architecture for XML Binding (JAXB) の初期アクセス・リリースをダウンロードしてください。
-
Schema2Java は、Creative Science Systemsによる商用のXMLデータ結合製品です。
- この記事に含まれているサンプル・コードを、PurchaseOrder.zip またはPurchaseOrder.tar.gz としてダウンロードしてください。
- XMI (XML Metadata Interchange) について詳しく学ぶためには、IBM XMI Framework を調べてください。
- SOAP 1.1仕様は、W3C Technical Note として使用可能になっています。
-
Sanjiva Weerawaranaによるこの投稿は、Apache SOAPにおける
xsi:type要件の緩和について述べています。 - Apache SOAPと他のツールキットとのインターオペラビリティーについては、Web Servicesインサイダー: 第3回、James Snell著 (developerWorks、2001年5月) に記載されています。
-
SOAP Messages with Attachments のW3C Noteには、SOAPがMIMEにどのように組み込まれているのかが述べられています。
- Eric E. Allenは、developerWorksのコラムJavaコードの診断 の中で、型詐欺師のバグ・パターンについて説明しています。
-
W3C XML Schema, Part 1 では、XML Schemaの中核的な概念と構文が説明されています。
-
W3C XML Schema, Part 2 では、XML Schemaでサポートされるデータ型について述べられています。
Gavin Bong氏は、マレーシアのクアラルンプール出身のJava開発者です。氏は、サービス指向のアーキテクチャーとワイヤレスJavaに関心を持っています。同氏の連絡先はgavinb@eutama.com です。図1を完成するに当たってYing Pee Eng氏の協力に感謝しています。