サービスインタフェースにおける文字列型による 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 ドキュメントのパッケージング
この課題の対処法では、ドキュメント指向のサービスで文字列型を用いて XML ドキュメントを記述する際のデザイン時の考慮事項に焦点を当てています。これらの対処法については、ドキュメント指向のサービスエントリを参照してください。
対処法
クライアントサービスの間で交換される XML ドキュメントを xsd:string
を用いて記述する際の問題点をいくつか考えてみましょう。
ここでは、クライアントから、注文書を受け取るサービスに PurchaseOrder XML ドキュメントを渡す例を使用して、この対処法を説明します。交換される注文書は、注文書 ID や連絡先情報、購入する商品の品目などのデータを含む一般的な注文書です。
対処法: 文字列型によるドキュメントの記述
XML ドキュメントは、クライアントとサービス間で文字列として交換することができます。この対処法では、XML ドキュメントは、そのドキュメントのすべての要素と内容を含む 1 つの文字列に変換されます。このため、シリアライザを作成したり、基の要素に対するエンコーディング・デコーディングを行うことなく、複雑なビジネス文書を簡単に渡すことができます。開発者によっては文字列の扱いに慣れており、これは簡単に作成できるインタフェースです。このことは、Java インタフェースがドキュメントのパラメータとして、public void submitPO(String PO)
などの文字列型を持ち、WSDL ファイルが xsd:string の入力パラメータを持つことを意味します。
以下は、この対処法のコード例です。WSDL ファイル、対応する Java サービスインタフェース、および実装クラスはすべて文字列型を使用して、XML ドキュメントを記述することに注意してください。ここで大切なことは、注文書が文字列で表されるということです。コード例 1 は、文字列型を使用して記述された注文書 XML ドキュメントを交換するサービスの WSDL ファイルからの抜粋です。
<?xml version="1.0"
encoding="UTF-8"?>
<definitions name="StringPurchaseOrderService"
targetNamespace="urn:StringPurchaseOrderService"
xmlns:tns="urn:StringPurchaseOrderService"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<schema
targetNamespace="urn:StringPurchaseOrderService"
xmlns:tns="urn:StringPurchaseOrderService"
xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://www.w3.org/2001/XMLSchema">
<complexType name="submitPO">
<sequence>
<element name="String_1"
type="string" nillable="true"/>
</sequence>
</complexType>
...
<element name="submitPO" type="tns:submitPO"/>
...
</schema>
</types>
<message name="StringPurchaseOrderServiceSEI_submitPO">
<part name="parameters"
element="tns:submitPO"/>
</message>
...
</definitions>
コード例 1: 注文書の XML ドキュメントを文字列型で記述しているサービスの WSDL ファイルからの抜粋
このサービスの WSDL ファイルに対応する、コード例 2 の Java インタフェースでもまた、注文書 XML ドキュメントの型として文字列型を指定することに注意してください。このことは、String xmlPO がすべてのドキュメントデータばかりでなく、その値として設定された XML タグも持つことを意味します。
public interface
PurchaseOrderServiceSEI extends Remote
{
public String submitPO(String xmlPO)
throws InvalidPOException, RemoteException;
}
コード例 2: サービスの WSDL ファイルに対応する注文書の Java インタフェース
サービスインタフェースとまったく同じで、Java 実装もまた、注文書 XML ドキュメントを文字列型として処理する必要があります。コード例 3は、このサービスインタフェースの実装例です。この例では、サービスインタフェースを EJB Bean 実装していますが、代わりに、Web コンポーネントを使用して実装することもできます。
public class PurchaseOrderServiceBean
implements SessionBean {
...
public String submitPO(String xmlPO) throws
InvalidPOException, RemoteException {
String id =null;
//スキーマとドキュメントを照合
if (!(validate(xmlPO))) {
throw new InvalidPOException("Error parsing the purchase order XML
document!!!");
}
try {
//ドキュメントから PO ID を抽出し、クライアントに返す
id =
getID(xmlPO);
} catch (Exception e) {
throw new EJBException("StringPurchaseOrderService implementation had
trouble parsing PO.xml, some system or
configuration problem " + e.getMessage(), e);
}
// アプリケーションに固有の例外のスローを紹介することのみを目的としたコード
if(id.equals("100"))
throw new InvalidPOException("Invalid ID for the purchase order!!! " +
"For demo purposes, we throw " +
"an application defined exception for the ID value of 100.");
return id;
}
}
コード例 3: 注文書のサービスエンドポイント実装クラス
エンドポイントの開発者は、文字列型でドキュメントを記述するインタフェースアーティファクトを作成するばかりでなく、このドキュメントの処理方法も考える必要があります。エンドポイントの一般的な要件の 1 つは、受信した注文書を妥当性検査することです。注文書は 1 つの文字列であるため、ほかの対処法を採用したときと異なり、JAX-RPC 実行時環境でそのスキーマと照合をすることはできません。このため、注文書をスキーマと照合するためのコードを作成する必要があります。つまり、この対処法の 1 つの弱点は、実行時環境の提供するスキーマ妥当性検査を利用できず、サービスがメモリー上のドキュメントを読み取り、処理するまでドキュメントのエラーが発見されないことです。
エンドポイントに共通するもう 1 つの要件は、ドキュメントを処理する必要があることです。このことは、PurchaseOrder.java や対応する LineItem.java オブジェクトなどのいくつかの Java 型へのバインドを意味することが普通です。しばしば、このバインドは、既存の Java データモデルを持つことがあるビジネス処理層に委託する前に、サービス対話層で行われます。注文書スキーマの詳細を WSDL に埋め込み、スキーマ定義型を用いて XML ドキュメントを記述するなどのほかの方法の場合、このバインドは、JAX-RPC 実行時環境によって自動的に行われます。このため、開発者は、文字列型ドキュメントを、そのドキュメントを表す Java オブジェクトに変換する処理を担当するコードを作成する必要があります。開発者の作業が少し増え、多少パフォーマンスに影響する可能性があります。
サービスが文字列型を使用して、交換するドキュメントを記述している場合のクライアントコードへの影響を考えてみましょう。WSDL ファイルの定義にしたがってサービスを利用するには、クライアントはその PurchaseOrder.xml ドキュメントを受け取り、その文字列版を作成する必要があります。文字列への変換後、クライアントはビジネスドキュメントをサービスに渡すことができます。文字列版の XML ドキュメント作成というのは、エンドポイントが文字列型を使用して XML ドキュメントを記述する場合にクライアントが行う必要がある余分なステップです。また、WSDL では、注文書のパラメータを文字列型と定義するため、実際には WSDL では、サービスインタフェースが綿密には記述されません。ドキュメントの型が文字列と WSDL ファイルに指定されている場合、クライアントの開発者は、どのようにそのドキュメントのスキーマを知るのでしょうか。この逆に、スキーマ定義型を用いて XML ドキュメントを記述する方法では、注文書 XML ドキュメントのスキーマが WSDL に含まれるため、サービスの記述がより完全で、クライアントはサービスの要件を容易に特定できます。WSDL で文字列型を使用して注文書 XML ドキュメントを記述している場合、サービスが自身にアクセスしようとするクライアントを助けるには、ほかのどこかでサービス記述を公開する必要があります。これは、サービスと交換される XML ドキュメントを文字列型で記述する、この対処法の弱点です。
文字列型ドキュメントがクライアントからサービスに渡されると、そのドキュメントはペイロードのようにシリアルライズされて送信されます。JAX-RPC 実行時環境は、下記の SOAP 要求に見られるように、タグおよび引用符に対する適切なエスケープ文字を XML 内に作成します。文字列をエンコーディングするための情報を追加すると、その分、メッセージのサイズが大きくなる可能性があることに注意してください。コード例 4 は、注文書の文字列エンコーディングを示しています。このために特別に追加されている内容があることが分かります。その実装クラスでサーバーが受信する文字列には、クライアント側で作成された元の XML が含まれます。元のドキュメントは少し小さくなることに注意してください。
POST /xmlstring/jaxrpc HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: 1397
SOAPAction: ""
User-Agent: Java/1.4.2_03
Host: localhost:9090
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schema.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:enc="http://schema.xmlsoap.org/soap/encoding/"
xmlns:ns0="http://www.examples.com/types">
<env:Body>
<ns0:submitPO>
<String_1><?xml
version="1.0" encoding="UTF-8"?>
<PurchaseOrderDocument>
<createDate>11-15-04</createDate>
<shipTo>
<street>abc st</street>
<city>abc city</city>
<state>CA</state>
<zipCode>99999</zipCode>
</shipTo>
<billTo>
<street>abc st</street>
<city>abc city</city>
<state>CA</state>
<zipCode>99999</zipCode>
</billTo>
<items>
<itemname>Glass Ceiling
Fan</itemname>
<price>2</price>
<quantity>200.0</quantity>
</items>
<items>
<itemname>Stainless Steel Blender
</itemname>
<price>1</price>
<quantity>75.0</quantity>
</items>
</PurchaseOrderDocument>
</String_1>
</ns0:submitPO>
</env:Body>
</env:Envelope>
コード例 4: 文字列型で記述された XML ドキュメントの SOAP 要求
参考資料
この項目に関する詳細は、次の資料を参照してください。
© 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.