RESTおよび ケーブルを利用したJAVAと.NETの相互運用に対する単純で依存度の低いソリューションについての考察
この記事では、単純なテクノロジーと文書を中心としたアプローチを組み合わせることによって、独自のミドルウェアや複雑な Web サービススタックを利用せずに、価値の高いビジネスサービスを実現する方法について説明します。この発想は、REST のアーキテクチャ様式や HTTP 上で XML を移動する機能から生まれたものです。
Web サービスの方法
この手法を導入するには、単純な Web サービスの例と対比するのが最もよい方法です。温度と気圧をオブジェクトにラップして返す WeatherQuery という Web メソッドを露出するような単純な気象サービスについて考えてみましょう。通常は、既存のコードを取り出し、ツールを使ってメソッドを露出し WSDL を生成します。
この誇大広告を信じるならば、WSDL において相当するJAVAツールをポイントし、スタブメソッドを生成するだけで十分です。
残念ながら、物事はそれほど単純ではありません。WSDL は広範な規格です。実際に、自由に解釈できるほどに広範です。当社 (ThoughtWorks, Inc) の場合、.NET によって文書アプローチが有効になり、当社のJAVA ツールがその逆の役割(RPC)を果たすことがわかりました。また、ネーム空間の混合、つまり WSDL を分解するスキーマやツールの包括に関する問題点も判明しました。要するに、テクノロジーは、当社が解決しようとしている実際の問題点から離れ始めたということです。
さらに悪いことに、Web サービス用のツール内に不整合性があることも判明しました。たとえば、Internet Information Server と Web Services Enhancements の各バージョン間、または自動発行された WSDL 文書に対応する JAVA 相当物とには部分的にしか互換性がありません。
私たちは、手直しすることによって今日は機能しているものが、サービスの将来のバージョンでもっと複雑な Web メソッドが必要になった場合、明日になったら機能しなくなるかもしれないという状況にほとほと嫌気がさしていました。
もっと REST 的な様式
上述のアプローチでは、2つの重要な仮定を行ないました。1つは、既存のメソッドの呼び出しを露出するだけで、意味のあるサービスを実現できるのではないかという仮定、もう 1 つはツールによって、ありふれた Web サービスを通じてそのサービスに到達できるのではないかという仮定です。
要求のパラメータや戻りのタイプについて考えるのではなく、要求のタイプとそのパラメータを組み込む文書を要求とみなすことができます。その文書を、モデル化しようとしているビジネスプロセスの契約の一部を表すものであると考えてみましょう。同じメソッド WeatherQuery の場合、通常の XML 要素に記述すると、以下のようになります。
また、文書としても、戻りのタイプは以下のようになります。
これで、文書と同じフィールドを表す単純なクラスの設計を以下のように定義することができるようになりました。
これら 2つの文書に関して興味深い点は、.NET と JAVA のどちらにおいても、いずれの文書も比較的簡単にシリアル化、非シリアル化できるということです。.NET の場合、組み込み XML シリアル化(コメント付き)がうまく機能する。同じクラスの C# を以下に示します。
JAVA の場合は、それほど都合よくはいきません。JAVA には XML をシリアル化するためのツールが組み込まれていません。しかし、XStream (http://xstream.codehaus.org ) (英語)といううってつけのオープンソースのツールがあります。
現在、私たちの気象サービスでは文書を容易に交換することしかできないが、その結果、Web サービスの代わりに平易な HTTP を利用することができます。
このような移行によって、システムへの同じエントリーポイントを使って、複数の文書タイプについて考えることができ、さらに拡張性の高いアプローチが可能になります。
JAVA サーバーのコーディング
サービスの JAVA 実装化に利用したテクノロジーは、シリアル化ライブラリ XStream のテクノロジーとサーブレット内のサービスをホストするために選択した任意のサーブレットコンテナです。XStream はオープンソースです。サーブレットコンテナとしては、WebLogic、WebSphere、JBoss、Geronimo、Orion のいずれかを使うことができます。または、J2EE の E の小さいほうが必要な場合は、単に Resin、Tomcat、Jetty を使ってもかまいません。
私たちのサーブレットでは、doGet() メソッドではなく、doPost() メソッドを実装すべきです。私たちは、XML に名前と値の組み合わせは使用せずに、HTTPの仕様からは多少外れますが、単に POST 本体全体を使いました。クライアントとサーバー上で同じ結果になるのであれば、これは単なる好みの問題となりますが。
要求が来たら、XStream を使って XML を非シリアル化してコマンドオブジェクトに変換し、それをしかるべく処理します。
.NET サーバーのコーディング
.NET のサーバーテクノロジーはもっと単純です。私たちは単に、Internet Information Server (IIS) と .NET の組み込み XML シリアル化を利用しました。組み込みシリアル化では、C# 属性を使ってフィールドを XML 属性としてではなく、XML 要素としてマークする必要があります。XStream の .NET ポートがあり、これを使うと状況をさらに単純化することができますが、このポートはまだ使ったことはありません。また、オープンソース界で別のポートが発表されるという噂があります。
JAVA クライアントのコーディング
XStream 以外に JAVA クライアントでは、Apache の HttpClient ライブラリ(およびその付属品)を使っています。
http://jakarta.apache.org/commons/httpclient (英語) を参照してください。HttpClient ライブラリはいたって簡単に使用でき、POST 処理をプログラム構築してから実行できます。POST 本体は、名前と値の組み合わせ、またはその HTTP 構造がない要求全体として XStream が出力した XML であることを忘れてはなりません。サービス用のテスト Web フォームを作成したいのであれば、前者がよいかもしれません。
.NET クライアントのコーディング
.NET クライアントの場合は、フレームワークのみが必要です。バージョンは、1.1でも 2.0でもかまいません。
POST 処理に対しては、組み込みの WebRequest クラスと組み込みのシリアル化機能を利用できます。
拡張性と互換性の実現
コマンドを表す XML を単に POST することのメリットは、メッセージ実装を変更せずに、あとからコマンドを増やすことができることです。サーバーは、XML を処理できるかどうかを実行時に決定することができます。
可能性がある多数のタイプに対する解決策としては、各タイプのハンドラーを登録することによって、大きなif/else ブロックや switch/case ブロックを回避するのがよいでしょう。
XML を利用する場合、関係するスキーマ上で過度な中継をしたくなってしまでしょう。スキーマの検証と顧客が実際に必要としているであろう情報との違いを理解するように注意する必要があります。
実行時にスキーマの検証を実行すると、開発担当者は安心感を覚えますが、これは間違った安心感です。すでにエラーが発生している可能性があります。つまり、間違った XML が送信されている可能性があるということです。どのような事態が発生するのでしょうか。スキーマ無効例外メッセージが発生している可能性があります。または、クラスの設計にマッピングされた XML で、正しいオブジェクトがあった、または欠落しているフィールドがあった可能性もあります。このような状況では、本当の例外は本当の理由で破棄され、消費者に向けたクリアな XML 返信メッセージに簡単に変換することができます。重要な違いは、必要な情報が欠落しているとき以外は、除外は発生しないということです。それ以外は変更可能です。
本質的にこの設計では、要素が XML(フィールドからクラス)に加えられ、API を1段階前に移動することが可能になります。慎重なテストを行なうことによって、古いバージョンの要求文書を送信する消費者にサービスが対応することができます。API の変更および「特別なフィールド」のレベルであることもほとんどありえないことです。
ただし、http://x.com/weather/WeatherQuery/2.0 (英語) のように、バージョン番号をコード化して URL に組み入れるのがよいかもしれません。
Web サービスにラッピングする
同じサーバーに別のサービスを組み入れることによって、同じサービスに対する正式な Web サービスの要求を受け入れることを阻止するものは何もありません。ただ、WSDL で指定した以下のような1つのメソッドを記述するだけで十分です。
ツールとしては、.NET または Glue、AXIS、JAX-WS に対応した WSE 2.0/3.0 や JAVA 用の J2EE コンテナのいずれかに対応した組み込みアダプター用を利用できます。SOAP でコード化したメソッドについては、単に純粋な REST 実装用に開発された同じ demarshal-execute-marshal コードに任せることができます。こうすることで、企業標準ポリスを回避することもできます。
メッセージングに拡張する
Tibco Rendezvous を活用して、要求の同じXML 表現を送信して、暗黙的に非同期のサービスに対して実行することができました。MQ シリーズは試していないが、機能するはずです。
当社の例の場合、気象の詳細の要求は直ちに満たされないということです。その代わり、あとで応答が返ってくる可能性もあります。これは、API に対して持っている単純な考えの一部を変えたり放棄したりすることになる可能性を秘めた大きな移行です。たとえば、あとに続く見せかけのメソッドは、以下のように記述しなければならないかもしれません。
所定の場所に、それぞれ1つのメソッドを持つ2つのインターフェイスが適切かもしれません。
メッセージングのパターンに関しては習得しなければならないことが数多くありますが、ここでは詳細には触れません。しかし、考慮すべき全体的な考え方が2つあることを覚えておくとよいかもしれません。1つはキューに関する考え方で、ユーザーからの要求は、そのユーザーに当てられた応答以外は受け取らないということでしょう。もう1つはマルチキャストという概念で、ケーブル上には多くの加入者に送信されているイベントがあるということです(pub/sub)。また、暗黙的に、訂正された詳細をある期間にわたって継続的にストリーミングするようなキューを設計できる可能性もあります。 JMS に詳しければ、このような点で Rendezvous は若干異なる機能を果たします。
WSDL の歩む道
私たちがコーディングした製作者と消費者という考え方は、シンプルな設計の XML になります。しかし、私たちの考え方には、正式な Web サービス考え方の発見段階に固有の仕様チェックが欠落しています。
仕様チェックは、必ずしも必要ではないと私たちは暗に考えています。その代わり、Agile の考えに完全に従って、統合テスト用の総合的な常時統合スイートを持っていればよいのです。サービスの非互換性は、運用を開始する前に発見されます。したがって、複雑な WSDL 仕様ではなく、プロバイダーと消費者の両方の観点からサービスに関する表明を行なう一連のユニットテストを持っていることになります。とにかく、WSDL は、リカバリーが非常に困難な場合、実行時に非互換性にフラグを立てるに過ぎません。これはまがい物の神なのでしょうか?
Schematron は、プラットフォームに依存せずに、このようなテストを作成する1つの方法です。
デバッグや文書作成を簡単にするために、以下のようにいくつかのサンプル文書をホストすることをお勧めします。
また、XML スキーマ(XSD)で、文書フォーマットを制御してもかまいません。
XSD とサンプル XML に静的に対応するのは、よい考えかもしれません(偶然、著者たちの XSD に対する考え方は異ります)。静的に対応しているということは、Web ブラウザを使って人間が API に問い合わせを行なえるということです。
http://x.com/weather/xsd/WeatherQuery (英語)
http://x.com/weather/sample/WeatherQuery (英語)
XSD とサンプル文書はどちらもオプションであり、簡単に作成できることも覚えておく必要があります。
要約とキーメッセージ
ここでの魔法は、Codehaus の XStream を使って、GET ではなく HTTP-POST 処理によって、.NET と要素ノーマルな文書交換を行なったことです。これまで、ほとんどすべてのことがブログの記事として取り上げられ、報告書化されてきました。XStream を選ぶこと、それはメッセージの指定は WS-* 仕様で通常発生する XML ベースの設計ではなく、JAVA や C# で行なわれということでした。
また、従来の REST の知恵から、コマンドのエンコーディングには、HTTP-GET を使うほうがよいことがわかります。
http://x.com/weather/WeatherQuery?locn=Chicago (英語)
・・・ 特に、Web サーバーが結果をキャッシュできる場合は。キャッシュする試みが無意味なやり取りの場合、おそらくわたしたちのやり方がベストでしょう。GET を使ったアプローチには、私たちのアプローチで失くしてしまったその他のメリットがあります。このアプローチは、より洗練されたものであり、完全な URL のおかげで人間がブラウザを使ってテストできることは明らかです。しかし、単にパラメータの名前と値の組み合わせ以上のことが可能な POST で実現できる柔軟性を欠いています。XML のペイロードは、任意に複雑にできます。もちろん、大規模なソリューションでは、GET や POST の余地はあります。
この文書の作成中に、XStream チームに、(パッチによって)必要に応じて属性に対応できる能力を増大させることができる提案を行ないました。XStream チームは、必要な機能を実装したので、XStream の将来のバージョンは XML 属性をサポートし、.NET とのシームレスな相互運用が実現します。
また、Tibco RV と同様、このアプローチは非同期移送で機能することも示唆しました。現在の WS-* 仕様ツールはこの点に関する機能とはほとんど関係ありません。
結局は、これは POST-REST (REST) なのか、それともキャッシュ能力が大きくなく、URL の簡潔さがない古きよき REST なのかははっきりしません。また、新しい用語も作られていないのです。
原文はこちらです:http://www.infoq.com/articles/REST-INTEROP
(このArticleは2006年5月12日にリリースされました)