はじめに
データの変更を追跡することは、多くのソフトウェア、アプリケーション、およびビジネス統合シナリオで必要とされる基本機能です。一般的な変更のデルタ(差分)をモデル化し、取り扱うことは非常に込み入った作業であり、この基本機能を厳密に実装することは比較的難しい課題です。一方で、すべてのアプリケーションにこの機能を重複して実装するのは無駄です。デルタ処理モデルは同じものをさまざまな状況に応用できますし、大半のケースで求められる機能はよく似ているからです。BEA Systems社とIBM社の主導で進められているService Data Object(SDO)は、異種データアクセスのための汎用ソリューションを定義するJSRで、開発者はこのメカニズムを使用してシステムレベルのデータ履歴追跡機能を簡単に実装できます。
この記事では、SDOのJava実装であるApache Tuscanyバージョン1.0を使って、XMLデータをSDOで処理する方法の例を示します。SDOは(まだ)XML処理の標準ソリューションではないため、SDOの基本XMLデータ操作についても説明して、前後関係を明らかにします。
3フェーズからなるXMLデータ処理
この記事のXMLデータ処理例では、次の3つのフェーズがそれぞれ別のグループによって担当されることを前提とします。
- 作成
- 処理
- 元に戻す
XMLデータは、ファイルシステムを通じてこれらの3フェーズ(および3グループ)間でやり取りされます。この例の基本シナリオはこうです。最初のグループが作成したXMLファイルに第2のグループが変更を加え、この変更を記録します。この記録は、第3のグループがXMLデータを元に戻すときに利用されます。Microsoft Wordの変更履歴機能を使用したことがあれば、この機能の値打ちがすぐに理解できるでしょう。
この種の機能は、多くのアプリケーションで必要とされます。たとえば、オプティミスティック同時実行制御や、オフラインアプリケーションデータと稼動中データベースとの同期、ビジネスプロセス管理(BPM)システムなどを実装するには不可欠です。以降のセクションでは、SDOを利用してこれらの機能を簡単に実装できることをサンプルコードを示して説明します。
サンプルのXMLデータ(基はSDO 2.1.0仕様書のサンプル)は、注文処理をモデル化したものです(スキーマ「po_original.xsd」についてはリスト1を参照)。次のセクションでは、SDOを使ってこのスキーマに基づく注文処理を作成し、ファイルシステムに永続化する手順を説明します。このサンプルでは動的APIを使用します。SDOではあらゆるデータソースを扱うための静的APIもサポートされています。
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/PO" targetNamespace="http://www.example.com/PO"> <xsd:import namespace="commonj.sdo/xml" schemaLocation="sdo.xsd"/> <xsd:element name="purchaseOrder" type="PurchaseOrderType"/> <xsd:element name="comment" type="xsd:string"/> <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="StatusType"> <xsd:sequence> <xsd:element name="status" type="xsd:string"/> <xsd:element name="contact" type="xsd:string"/> <xsd:element name="changeDate" type="xsd:date"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="USAddress"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> <xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="price" type="xsd:decimal"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>