サービスインタフェースにおける xsd:Type による XML ドキュメントの記述
Sean Brydon、Smitha Kangath、Sameer Tyagi
課題
クライアントとサービスが XML ドキュメントを交換する Web サービスとの対話のデザインでは、サービスインタフェース内の XML ドキュメントを記述する型を選択する必要があります。この型の選択は、多くのことに影響します。選択された型は、サービスを記述した WSDL ファイルばかりでなく、サービス実装のコードにも反映されます。J2EE[tm] プラットフォーム (Java[tm] 2 Platform, Enterprise Edition) 1.4 アプリケーションでは、注文書や 請求書などの XML ドキュメントの交換に、JAX-RPC (Java API for XML-based RPC) を使用します。
サービスインタフェースをデザインするときの XML ドキュメントを記述する型の選択肢は数多くあります。
- 文字列型による XML ドキュメントの記述
- スキーマ定義型による XML ドキュメントの記述
- XML フラグメントによる XML ドキュメントの記述 (xsd:anyType を使用)
- XML フラグメントによる XML ドキュメントの記述 (xsd:any を使用)
- アタッチメントによる XML ドキュメントのパッケージング
この課題の対処法では、ドキュメント指向のサービスで xsd:anyType を用いて XML ドキュメントを記述する際のデザイン時の考慮事項に焦点を当てています。これらの対処法については、ドキュメント指向のサービスエントリを参照してください。
対処法
xsd:anyType を含む XML フラグメントを使用して、クライアントサービスの間で交換される XML ドキュメントを記述する際の問題点をいくつか考えてみましょう。
対処法: xsd:anyType を含む XML フラグメントによる XML ドキュメントの記述
この方法では、XML ビジネスドキュメントを XML フラグメントで表現します。サービスの Java インタフェースおよび実装では、このことは、型が SOAPEelement として指定されることを意味します。JAX-RPC では、XML スキーマ型に対する標準の Java マッピングがない場合、型は XML ドキュメントフラグメントとしてマッピングされます。XML と Java 間のマッピングでは、インタフェース javax.xml.soap.SOAPElement を使用して、wsdl:operation 要素の Java マッピングでリテラルメッセージ部を表します。WSDL ファイルの場合は、注文書などの XML ドキュメントを記述する型として xsd:anyType を使用するように選択できます。
WSDL ファイルで xsd:anyType を使用することを考えてみましょう。XML スキーマでは、xsd:anyType は、すべての単純および複合型の派生元である基本型の抽象を表します。anyType 型には、データの内容に関する制限や制約がなく、完全にほかのスキーマ型のように anyType を使用できます。anyType 型を使用して、サービスクライアントとサービスエンドポイントの間で XML ドキュメントをやりとりできます。JAX-RPC 実装は、xsd:anyType を javax.xml.soap.SOAPElement にマッピングします。anyType データ型に頼ることの大きな欠点の 1 つは、JAX-RPC 仕様には、xsd:anyType に対する標準の Java マッピングが定義されていないことです。このため、SOAPElement へのマッピングに際して、J2EE 1.4 のあらゆる JAX-RPC 実装が同じ動作をするとは限りません。実際には、JAX-RPC の実装では、xsd:anyType をサポートするかどうかは任意です。このため、anyType を使用すると、移植性および相互運用性で問題になる可能性があります。XSD:anyType を利用することの利点の 1 つは、アクションとペイロードを一緒に渡せるようになることです。これは、同じオペレーションで複数の種類のドキュメントを受け付ける異種文書プロセッサを作成するときに役立つことがあります。たとえば、それぞれが異なるスキーマに準拠している、異なる種類の一群の注文書を受け付ける 1 つのサービスを考えてみましょう。
anyType の使用に関して注意することの 1 つは、クライアントが、パラメータの要素型に指定された名前 WSDL に一致する親要素内に注文書などの XML ドキュメントをラップせざるを得なくなることです。これは、サービスインタフェースにおける anyType 使用に関するデザインドキュメントで詳しく説明しますが、ここでも簡単に説明します。Web サービスに注文書 XML ドキュメントを送信するオペレーションがあり、その WSDL ファイルの内容がコード例 1 のようであると仮定します。この WSDL ファイルには、submitPO オペレーションに対する入力として受信されたメッセージにマッピングされる BusinessDocumentRequest (<element name="BusinessDocumentRequest" type="anyType"/>
) という要素が宣言されています。このため、注文書に対するスキーマが定義されている場合、基本的に、その要素は親要素に入れ子にされ、サービスに送信された XML は注文書スキーマと異なることになります。たとえば注文書は、コード例 2 に示すような親要素内にラップする必要があります。これは開発者には不便であり、また XML ドキュメントは、スキーマ定義との整合性を維持しません。
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:AnyTypePurchaseOrderService">
<complexType name="submitPO">
<sequence>
<element name="BusinessDocumentRequest"
type="anyType" />
</sequence>
</complexType>
...
<element name="submitPO" type="tns:submitPO"/>
...
</schema>
</types>
...
<message name="AnyTypePurchaseOrderServiceSEI_submitPO">
<part name="parameters"
element="ns1:submitPO"/>
</message>
<portType name="AnyTypePurchaseOrderServiceSEI">
<operation name="submitPO">
<input
message="tns:AnyTypePurchaseOrderServiceSEI_submitPO"/>
...
</operation>
</portType>
コード例 1: anyType を使用するサービスの WSDL からの抜粋
ドキュメントの型に anyType を使用する WSDL ファイルがサービスにある場合、そのクライアントはそのためのコードを作成する必要があります。このため、クライアントに注文書スキーマがある場合、クライアントは、そのスキーマに一致する注文書を作成し、それを親要素内にラップする必要があります。実際には anyType は WSDL 内に名前が指定された要素に対するデータ型の定義であるため、SOAP 本体で渡されるビジネスドキュメントは、WSDL で定義されたこの要素内に置かれます(たとえばコード例 2 では、PurchaseOrder は BusinessDocumentRequest 内にある)。このことは、やりとりされるドキュメントのルート要素が WSDL に指定されているか、ドキュメントそのものが適切に作成されるか、あるいはその場で要素内にラップされる必要があることを意味します。
<BusinessDocumentRequest>
<PurchaseOrder>
.... the rest of purchase order
elements here ...
</PurchaseOrder>
</BusinessDocumentRequest>
コード例 2: WSDL に指定された BusinessDocumentRequest という要素内に注文書 XML を入れ子にする例
xsd:anyType に加えて、サービスインタフェースで XML ドキュメントの記述に xsd:any を使用してデザインされているサービスもあります。xsd:anyType と比較するために、xsd:any を使用するこの代替方法を見てみましょう。XML スキーマでは、<any> 要素を利用することによって、スキーマが指定していない要素で複合型を拡張することができます。JAX-RPC では、xsd:any スキーマ型要素を使用して要素ワイルドカードが表わされている場合、この複合型のマッピングは通常どおり JavaBeans[tm] コンポーネントにマッピングされますが、maxOccurs=1 の <any> 要素が存在すると、_any という追加のプロパティーが生成され、1 つの javax.xml.soap.SOAPElement にマッピングされます (maxOccurs が 1 より大きい場合は、javax.xml.soap.SOAPElement の配列にマッピングされる)。<any> 要素のマッピングを利用すると、document-literal の書式で over-the- wire に XML ドキュメントをトランスポートできます。JAX-RPC 1.1 では、xsd:any のマッピングが SOAPElement にマッピングされるように標準化されており、このことは、アプリケーションサーバーが異なっていても、xsd:any を利用できると考えてよいことを意味します。xsd:any のもう 1 つの利点は、スキーマに定義されていない任意の内容で既存の要素を拡張できることです。このことは、WSDL で要素に名前が指定されていて、渡されたビジネスドキュメントがそれら要素内に現れたとしても、Web サービスおよびそのクライアントは、それらの要素の下にあるものとしてドキュメントの内容を取り込まなくても、XML ドキュメント全体を操作し、スキーマの整合性を維持できることを意味します (これは、anyType を使用する方法では不可能)。XML ドキュメントは、引き続きスキーマ定義との整合性を維持します。
この方法における WSDL での xsd:any と xsd:anyType の使用比較以外の問題もいくつか考えてみましょう。PurchaseOrder などの XML ビジネスドキュメントの記述に XML ドキュメントフラグメントを使用する方法では、クライアントまたはエンドポイント側の開発者は、SOAPElement API を操作して、ドキュメントの処理に対応する必要があります。これらの API はよく知られている API ではなく、少し使いにくいことがあります。ドキュメントを処理するために、開発者が Java オブジェクトを操作する必要がある場合は、PurchaseOrder などのドキュメントに対応する Java オブジェクトにバインドするコードを作成する必要があります。こうしたコードは、パフォーマンスに多少影響を与えることがあります。
参考資料
この項目に関する詳細は、次の資料を参照してください。
© Sun Microsystems 2005. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.