Apache | WS |
WebServices - Axisクライアント側 Axis内容目次
はじめにこのドキュメントでは Axis を利用したWebサービスのクライアント側の開発に関連する問題を見ていきます。 Axis は SOAP をサポートしていて、SOAP は HTTP の上で構築されていて、HTTP は TCP/IP の上で構築されているプロトコルです。何が行われているか理解するには、下部レベルを理解することが重要です。 TCP/IP 概念の核心TCP/IP を詳細に説明するつもりはありません。なぜなら TCP/IP はあまりにも複雑だからです。ですが TCP/IP 技術のいくつかの概念と特徴はここで扱う価値があります。 TCP/IP は2つのコンピュータ、すなわちホスト、の間に信頼できるチャネルを構築します。TCP を走らせているコンピュータは1から65535までのどのポートに来るメッセージも受け取ることができます。それはマシン上のプログラムがソケットを生成して、そのポートをリスンしている場合です。そうでない場合、接続拒否のメッセージを見ることになるでしょう。 クライアントがホストに接続する前に、クライアントはホストのアドレスを探す必要があります。TCP/IP の最も広くサポートされたバージョンである IPv4 は 127.0.0.1 (これは特別なアドレスで、ローカルシステムを意味します) のような32ビットのアドレスを利用します。ホストに接続するにはアドレスか、あるいはアドレスにマッピングできる "www.w3.org" のようなマシンの名前のいずれかが必要です。このマッピングは DNS によって提供されます。DNS は階層的なネットワークであり、インフラ全域で偏在しており、私達は普段当然のものと思っているものです。基本的に、DNS サーバはホスト名を受け取り、IP アドレスかエラーメッセージを返します。DNS サーバがどのようにアドレスを解決するかはこのドキュメントの範囲外なので、単にローカル DNS サーバはそれが必要だと思ったら他の DNS サーバに問い合わせるものだと思ってください。 すべてのシステムが DNS サポートを持っているわけではありません。システムは設定によって自分独自のホスト表を持つことができます。Unix システムでは /etc/hosts に、Windows システムでは c:\windows\system32\drivers\etc\hosts にあります。このファイルを編集して完全に DNS を迂回することができますが、維持管理は悪夢となります。もしあなたのユーザが DNS ではなく静的なホスト表を利用しているのであれば、深刻な嘆きなしにホストのネットワークアドレスを変更することはできません。 マシンは静的アドレス (ネットワーク管理者がアドレスを割り当て、長期に渡って維持します) か動的アドレスのいずれかを持ちます。後者はクライアントシステム、特にラップトップ、デスクトップPC、ダイアルアップコンピュータで一般的です。ブロードバンドコンピュータの多くは静的アドレスを持っていますが、それは ISP によります。 アドレスを解決した後、クライアントプログラムはソケットを生成し、サーバに接続を試みます。この時点で TCP プロトコルが作動し、クライアントは目的地にデータグラムを送信することで会話を開始します。これによりリンクの設定が開始され、数個 (3個) のパケットが行き交います。一度接続がなされて作動すると、サーバに呼び出し側のことが伝えられ (サーバはクライアントの IP アドレスを取得できます)、サーバはクライアントと結び付いたソケットを接続期間中持ちます。クライアントとサーバは (a) もしデータが到着するのであれば、ソケットに書き込まれた順に到着する、そして (b) もし到着しなければエラーメッセージが得られる、という保証の元、お互い任意のバイナリデータを送信することができます。 知っておくべきいくつかの特別なことを挙げます。
ネットワーク上の通信において、待機時間と帯域幅が大きな制約となります。待機時間は通信するのにかかる時間で、ネットワーク配線と同様に、ルータやファイアーウォールのようなハードウェアも全て待機時間に追加されます。帯域幅は1秒間にどれだけ送信できるかの指標です。短い待機時間 (良い) のリンクは小さい帯域幅 (悪い) を持っているかもしれませんし、一方、距離が離れたリモートサーバのように、大きな帯域幅の接続は長い待機時間になるかもしれません。 ファイアーウォールは現代ネットワークの重要な機構です。ファイアーウォールは入ってくる呼び出しに対してポートを遮断します。ステートフルファイアーウォールはすべてのパケットを調べ、現在の TCP 会話の入ってくるパケットのみ許すものであり、さらに優れています。ファイアーウォールはセキュリティ的な理由から必要不可欠なもので、外の世界に向けてより多くのサービスをネットワークの後ろにさらすことができます。入ってくる呼び出しを制限するのと同様に、ファイアーウォールはしばしば外向きの接続を制限します。例えば、ポート80 (HTTP) への外向きの接続を遮断して HTTP プロキシサーバを利用させようとしたり (下をご覧下さい)、ポート143 (IMAP) への外向きの接続を遮断して外部のメールサーバへの接続をやめさせたりします。SOAP クライアントと SOAP サーバの間のネットワーク中にファイアーウォールがあることを想定する必要があり、それゆえサーバからクライアントへのコールバックは不可能となるでしょう。 HTTP 概念の核心HTTP は基本的なもので、とても単純なプロトコルです。クライアントはリモートシステム上のあるポート、普通はポート番号80ですが、に対して TCP 接続をオープンします。次にクライアントは HTTP リクエスト (GET、POST、PUT のような動詞か、あるいはその他の標準リクエスト)、サーバに関連する URL、HTTP バージョン文字列を発行します。次にクライアントは0個以上のヘッダ (名前:値 の組が別々の行にある) と、ヘッダの終わりの示す空行を送信します。POST のようなデータアップロードを伴うリクエストは引き続きデータをアップロードします。そしてクライアントはサーバが返信するのを待ちます。 サーバは、ある数字、自身のいくつかのヘッダ、そして普通はリクエストのボディから構成される HTTP エラーコードで応答することができます。一般的にヘッダは MIME 型宣言と、"content-length" と "expires" のようなその他の有用なものが含まれています。 ファイアーウォールを通り抜けるには、多くの組織はプロキシサーバを走らせています。これは外部ネットワークにアクセスできるマシンであり、その他のイントラネットのマシンが外部ネットワークにアクセスできないのとは異なっています。クライアントはプロキシサーバにリクエストを送信する必要があり、次にそのリクエストは実際のサーバに転送されます。キャッシングプロキシサーバはリクエスト/レスポンスの組をキャッシュするので、よくあるリクエストは帯域幅を消費しません。これはとても有用ですが、キャッシュ可能なリクエスト (伝統的には GET リクエストのみ) に対してのみ機能します。透過プロキシはプロキシの特殊形で、潜在的なネットワーク設定により HTTP リクエスト (特にポート80の HTTP リクエスト) を、アプリケーション設定なしにプロキシサーバを通して送信するプロキシです。一般的にこれらは不具合が生じない限り目に見えません。不具合が生じた場合、あなたのお気に入りのWebサービスがまるで人間に行くことになっている HTML を返すように見えます。これによりいくつかの興味深いサポート呼び出しを行うことができます。 HTTP 上の SOAP は、この下に横たわるプロトコル上で機能します。SOAP リクエストは XML 本体付きの POST であり、SOAP レスポンスは HTTP ステータスコードと理想的には XML メッセージから構成されます。通常の HTTP と同様に、ステータスコード 200 は全てが良好であることを意味しています。エラーコード 500 は内部サーバエラーを意味するか、SOAP スタックとサービスの両方、あるいは片方が SOAPFault をスローしたことを指し示すことができます。SOAPFault は標準化された XML メッセージで、受信者がパースできる情報を含んでいます。ある状況下では他の HTTP レスポンスコードが返されるかもしれませんが、WS-I 機関は、いつ、どのようにこれらが許されるかについての規則を規定しています。 SOAP は一般的に HTTP の上で実行されるので、認証とセッション管理 (すなわちクッキー) に対して古典的な HTTP 手法が全て適用されます。将来ある時点で別のトランスポートがより一般的になるかもしれず、その場合その HTTP 手法は機能しなくなることに注意してください。これが、多くの人が SOAP に基づく代替品、一般的には SOAP ヘッダを利用して構築されますが、を書いている理由です。Axis はそのコードベース内に別のトランスポートのプロトタイプをいくつか持っていますが、そのどれもが (まだ) 製品としての準備はできていません。 JAX-RPCJAX-RPC 仕様は、クライアント側の Axis を構築する上で基盤となった仕様です。もしクライアントを書いているのであればお読みください。 SOAP メッセージを処理するサーバの URL である SOAP エンドポイントを呼び出すために JAX-RPC を利用するのに、基本的には2通りの方法があります。1つめの方法は、javax.xml クラスを利用して手で SOAP 呼び出しを構築し、リモートサーバを呼び出す方法です。これは面倒ですが、現場の裏で何が行われているかの知識を得ることができます。つまり、XML メッセージが構築され、リモートサーバに送信され、そのレスポンスがパースされて分解されます。このレベルで書かれたクライアントコードは、どの JAX-RPC 実装でも実行できるはずです。 もう1つの方法は、呼び出しの詳細を Axis に隠させて、Webサービス用のラッパクラスを生成させる方法です。これはサービスの WSDL 記述を受け取り、そして各操作に対して SOAP リクエストを構築し、結果を宣言された戻り値に後処理する、これらに適した低レベル呼び出しを作成する Java クラスを生成します。Axis は WSDL 内に含まれるサービスの全ての URL の注釈を受け取り、これをクラスにコンパイルします。ですからクライアントは WSDL が宣言している URL、これはしばしば WSDL が取り出された (デプロイ) サーバの URL ですが、に自動的にバインドされます。 この、プロキシクラスの自動生成は有用です。なぜならこれは、リモートWebサービスの呼び出しをローカルオブジェクトの呼び出しとほとんど同じように見えさせるからです。しかしながらこれには開発者が注意する必要があるいくつかの不都合があります。
個人的な経験に基づきますが、スタブクラスの動的生成はとても有用です。なぜならそれによりクライアント側のコードを簡素化し、いつサービスが互換性のない方法で操作のシグネチャを変更したかをクライアントソースが認識する手助けとなるからです。もし操作のパラメータが変更されたら、Java メソッドのパラメータも変更されるので、それゆえそのアプリケーションはもはや構築されません。 しかしながら、Webサービスはローカルオブジェクトではないということを常におぼえておくことは間違いなく重要です。プロキシクラスはローカルのように見えますが、サーバは細い接続ではるか遠くにあるかもしれません。 GUI スレッドからWebサービスにブロック呼び出しを絶対にしないでください。 テストAxis サービスをテストしたいのであれば、Wsdl2Java に対してリモートサービスが実装する1つ1つの操作全てのテストケースを含むスタブ JUnit テストクラスを生成するように指定することができます。これらのスタブテストケースは、有効なテストデータと、それに続く、結果の有効性を確かめる関連するアサーションで埋められる必要があります。 生成されたテストケースは IDE や Ant に基づいたビルドプロセスや Maven に基づいたビルドプロセスで実行することができます。 クライアント、すなわちテストケースをテストする際に、分散アプリケーションが経験するであろう特別な障害形態を実験しましょう。プログラムの異なる場所でネットワークコネクタを抜いてください。同じホスト上の無効な URL や、存在しないホストにサービスを接続するように設定してください。プロキシサーバを経由することを試してください。遅い接続を利用することを試してください。これは TCP Monitor プログラムがシミュレートしてくれます。 Webサービスのテストを手助けしてくれるサードパーティのアプリケーションもあります。SOAP monitor の提供や、形式に基づいた SOAP リクエストの構築などです。これらは便利ですが、それらに対してお金を払う必要はありません。 sourceforge にある Anteater [英語] は SOAP 呼び出しの Ant に基づいたテスト方法です。あなたはペイロードを提供し、次にその結果の有効性を確認するために xpath パスを利用します。これはいくぶん低レベルに思えるかもしれませんが、とても強力です。 クライアント側のハンドラの設定TODO Axis はクライアント側 JAX-RPC と Axis ハンドラの両方を提供しています。サーバ側のハンドラと同様に、これらのハンドラはメッセージが送信される前と受信した後に呼ばれます。 再配布Axis を実行しているアプリケーションを再配布するには以下のものを再配布する必要があります。
Axis JAR は署名されていないので、Java の Web Start 機構にある自動ダウンロードとしては利用できません。 現在のところ、wsdl は実行時に処理されていないので、wsdl4j.jar を含める必要はありません。これは doc/lit メッセージをサポートするのに SOAP メッセージの構造についての知識がさらに必要なった (つまり WSDL ファイルや、コンパイル時に WSDL ファイルから生成されたその他のメタデータの制限された実行時処理を意味します) 将来のある時点で変更されるかもしれないということに注意してください。 Webサービスの動的発見と動的バインディングAxis が WSDL からクライアントプロキシクラスコードを生成する際、Axis はコードを WSDL 内で指定しているエンドポイント URL (これは一般的には入ってくるリクエストの URL から生成される URL です) にバインドします。WSDL ページを取ってくるのに http://localhost URL を利用すると、クライアントコードも localhost に提供されたサービスにバインドされることになり、再配布可能なものでは望ましくないでしょう。同様に、WSDL を取ってくる際にホスト名を利用する場合でも、短い名前ではなく完全修飾ドメイン名が必要で (http://s1/ ではなく http://s1.example.org/)、さもなければあなた自身のドメイン内やサブネット内の呼び出し者しかサーバを見つけることができません。手で書かれた WSDL ではこの問題は発生しません。なぜなら WSDL 内のエンドポイントは著者が打ち込んだものだからです。 クライアント上の URL を更新する何らかの方法を提供することはほとんど必要不可欠です。最も簡単なのは、Axis コマンドラインツールで利用されているように、何らかのコマンドライン上書きオプションです。より高度なものとしては URL を入力するためのダイアログボックスで、さらに高度なものは何らかの自動化された発見機構です。 Axis はその JAR 内で発見機構を一切提供していません。UDDI レジストリへのアクセスを提供する姉妹プロジェクト jUDDI [英語] があります。また Axis CVS ツリー内に Axis と機能するマルチキャスト発見 jar があります。これは XML メッセージを利用する概念実証機構ですが、どの既存の標準とも互換性はありません。LAN ネットワーク上では機能しますが、より広い領域で利用されるように設計されてはいません。 TODO: サービス内で URL を設定する方法 Call 設定Call オブジェクトは呼び出しが作成される前に設定することができます。org.apache.axis.client.Call は javax.xml.rpc.Call インターフェースの Axis 版実装です。JAX-RPC 標準インターフェースは呼び出し者がプロパティを設定できる setProperty() メソッドを定義しています。あなたが設定できるものとして JAX-RPC 標準プロパティと Axis 独自のプロパティの両方があります。 全てのプロパティは、Call クラス内の public static final 宣言で定義されている名前である、文字列名を持っています。 標準プロパティ
Axis プロパティ
ポータブルクライアントでもこれらの Axis 特有のプロパティを設定することができます。もちろんこれらのオプションは他の JAX-RPC 実装では機能しません。 ネットワーク設定Axis は JVM 内で実行され、JVM パラメータはクライアントの振る舞いを制御します。利用される JVM 設定オプションを以下に挙げます。
これらのオプションのほとんどはプロキシサーバ設定を制御します。もしそれらの設定オプションがなく、かつインターネットアクセスにプロキシサーバが必要であれば、クライアントはある種の接続エラーやその他のものを受け取ることになるでしょう。もし設定オプションがあり、かつ間違っていれば、クライアントは同じように接続エラーを受け取るでしょう。ユーザは、アプレットをホストする際に JVM のプロキシ設定を設定することができますが、この設定はアプリケーションに反映されないことに注意してください。これは Java ネットワークの多くの謎のうちの1つです。 どのWebサービスクライアントアプリケーションも、プロキシサーバ設定を設定するための何らかの方法を提供する必要があります。サポート呼び出し診断のためにこれらをどこかに表示しておいても有用です。 最後の2つのプロパティは厄介です。これらはあまり知られていないのでなおさら厄介です。これらを調べるには java.net.InetAddress の下にある "Address Caching" をご覧下さい。あるいは単にあなたの DNS サーバを数分止めて、DNS サーバがない時にあなたのアプリケーションが接続に失敗することだけでなく、DNS サーバが再び立ち上がった時にサーバは到達不能のままであることを観察してください。 何が起こっているかというと、ランタイムは DNS クエリを利用して解決したホスト名の IP アドレスをキャッシュしています。デフォルトではこれらは永久にキャッシュされるので、長い間実行されている Java アプリケーションは、クライアントの生存期間中にリモートサーバの IP アドレスが変更されると切断されます。同様に、ランタイムはアドレスに解決できなかったホスト名をキャッシュします。Java1.3 ではこれらの失敗した検索は永久にキャッシュされます。つまりもし DNS が停止していたり、ネットにつながっていないラップトップの場合、クライアントは二度と探しあてることはできなかったのです。 重要なアプリケーションに対して、キャッシュされたホスト名のための実用的な存続期間でキャッシュオプションを設定することは明らかに必要不可欠です。(Java1.4 では) これらの値は Java Security Properties で、これらは java.security.Security.setProperty() を利用して設定します。Java1.3 以前のバージョンではコマンドライン上でのみ実行できた、プロパティを扱うなんらかの別の機構がありました。私達が忘れない限り、そのプロパティが何であるか伝えます。 ネットワーク問題のトラブルシューティング分散システムの古典的な定義は以下の通りです。 “あるコンピュータがクラッシュした時に、それによってあなたの仕事ができなくなるということをあなたは聞いたことがないかもしれませんが、実際にクラッシュした時に仕事ができなくなったというトラブルをあなたは抱えたことがあるはずです” Leslie Lamport これは滑稽に聞こえるかもしれませんが、分散システムの状況の情けないほど的中したモデルです。ウェブサイトが時々オフラインであったり、ページが時々不完全のまま提供されている、あるいは結果の代わりにいくつかのエラートレースが出ていたりすることを誰もが知っています。 Webサービスも同様ですが、人間がウェブブラウザに表示されたエラーページを読む替わりに、クライアントソフトウェアがエラーを受け取ってそれを扱ったり報告したりする必要があること、は異なります。 Axis クライアントコードがエラーを受け取ると例外、特に java.rmi.RemoteException のサブクラスをスローします。これは AxisFault でもいいし、その他のものでもかまいません。どちらにしてもトラブルを意味しています。一般的には例外のフォルト文字列は経験豊かなアプリケーション開発者に意味のあるエラーテキストを提供しますが、エンドユーザやサポートチームにとってはあまり意味がないでしょう。 以下に、クライアントアプリケーションが受け取るであろうネットワークに関連するエラーレスポンスのリストを示します。Axis の adminclient アプリケーションは SOAP クライアントなので、adminclient もこれらのレスポンスを見ることができます。Sitefinder コメントは、VeriSign SiteFinder やその後継がそれぞれ独自の目標のために DNS の標準的な振る舞いを覆す、つまりWebサービスの標準的な失敗モードを複雑にする行為、の場合にのみ特有です。
そのようなメッセージへのサポートラインの初期レスポンスは全て同じにするべきです。 接続問題が疑わしい場合、問題が発生している URL を取得し、呼び出し側に彼らのウェブブラウザで見させ、あなた自身で見れるか確かめます。 これは、Webサービスプロトコル (REST、XML-RPC、SOAP) が全て HTTP 上で構築されていて、URL によるサービス定義という共通基盤概念を利用しているという事実の利点を活かす場面です。それらの同じ URL を提供することにより何らかの人間が読みやすいコンテンツ (たとえそれが XML メッセージだとしても) を生成し、エンドユーザとサポート窓口はお互い彼らのウェブブラウザ内で表示することができます。この行動は、接続問題を診断する上での核心となるテクニックです。なぜなら本来、HTTP インフラ (サーバ、プロキシ、クライアント) はこの診断プロセスをサポートするために設計されているからです。 Webサービスプロバイダは以下によって上記プロセスを単純化できます。
その他の有用なテクニックとしては、サービスに "Ping" デザインパターンを提供させることです。サービスはすぐに戻ってくる簡単な "ping" 操作をサポートする必要があります。この操作は、その他の副作用やサーバにそれほど負荷を与えることさえなくサービスの存在を証明するために、クライアントによって利用されます。クライアントアプリケーションは最初にピングすることによってサーバとの通信 (アップロード、複雑なリクエストなど) を初期化する必要があります。これにより早い段階で、うまくいけば低いコストで、不具合を検出できます。 Webサービスクライアントアプリケーションの開発者は何ができる?ネットワークは基本的には信頼できません。ラップトップはあちこち移動してオフラインになり、サービスはスイッチオフになります。 あなたのアプリケーションは、接続問題を扱い、問題が診断できてかつ訂正できるように失敗する必要があります。Axis は自身でこれを行わないので、あなたが手助けする必要があります。
|