blob: 75f380517d144c42ac2d55f3eef6b30241f91e07 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../skin/tigris.css" type="text/css">
<link rel="stylesheet" href="../skin/mysite.css" type="text/css">
<link rel="stylesheet" href="../skin/site.css" type="text/css">
<link media="print" rel="stylesheet" href="../skin/print.css" type="text/css">
<title>WebServices - Axis</title>
</head>
<body bgcolor="white" class="composite">
<div id="banner">
<table width="100%" cellpadding="8" cellspacing="0" summary="banner" border="0">
<tbody>
<tr>
<td align="left">
<div class="groupLogo">
<a href="http://ws.apache.org/"><img border="0" class="logoImage" alt="The Apache WebServices Project" src="../images/project-logo.jpg"></a>
</div>
</td><td align="right">
<div class="projectLogo">
<a href="http://ws.apache.org/axis/"><img border="0" class="logoImage" alt="The Apache Axis Project" src="../images/axis.jpg"></a>
</div>
</td><td valign="top" rowspan="2" align="right" class="search">
<form target="_blank" action="http://www.google.co.jp/search" method="get">
<table summary="search" border="0" cellspacing="0" cellpadding="0">
<tr>
<td bgcolor="#a5b6c6" colspan="3"><img height="10" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td>
</tr>
<tr>
<td colspan="3"><img height="8" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td>
</tr>
<tr>
<td><img height="1" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td><td nowrap="nowrap"><input value="ws.apache.org" name="sitesearch" type="hidden"><input value="ja" name="hl" type="hidden"><input value="UTF-8" name="ie" type="hidden"><input size="10" name="q" id="query" type="text"><img height="1" width="5" alt="" src="../skin/images/spacer.gif" class="spacer"><input name="Search" value="検索" type="submit">
<br>WS を検索
</td><td><img height="1" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td>
</tr>
<tr>
<td colspan="3"><img height="7" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td>
</tr>
<tr>
<td class="bottom-left-thick"></td><td bgcolor="#a5b6c6"><img height="1" width="1" alt="" src="../skin/images/spacer.gif" class="spacer"></td><td class="bottom-right-thick"></td>
</tr>
</table>
</form>
</td>
</tr>
</tbody>
</table>
</div>
<table width="100%" cellpadding="0" cellspacing="0" border="0" summary="nav" id="breadcrumbs">
<tbody>
<tr class="status">
<td><a href="http://www.apache.org/">Apache</a> | <a href="http://ws.apache.org/">WS</a><a href=""></a></td><td id="tabs">
<div class="tab">
<span class="selectedTab"><a class="base-selected" href="../index.html">WebServices-Axis</a></span>
</div>
</td>
</tr>
</tbody>
</table>
<table id="main" width="100%" cellpadding="8" cellspacing="0" summary="" border="0">
<tbody>
<tr valign="top">
<td id="leftcol">
<div id="navcolumn">
<div class="menuBar">
<div class="menu">
<span class="menuLabel">Axis</span>
<div class="menuItem">
<a href="../index.html">はじめに</a>
</div>
<div class="menuItem">
<a href="../news.html">お知らせ</a>
</div>
<div class="menuItem">
<a href="http://wiki.apache.org/ws/ja/axis">FAQ/Wiki</a>
</div>
<div class="menu">
<span class="menuLabel">活動に参加</span>
<div class="menuItem">
<a href="../overview.html">概要</a>
</div>
<div class="menuItem">
<a href="../cvs.html">CVS リポジトリ</a>
</div>
<div class="menuItem">
<a href="../mail.html">メーリングリスト</a>
</div>
<div class="menuItem">
<a href="../ref.html">リファレンスライブラリ</a>
</div>
<div class="menuItem">
<a href="../bugs.html">バグ</a>
</div>
<div class="menuItem">
<a href="../howtobuild.html">サイト構築方法</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">Axis (Java)</span>
<div class="menuItem">
<a href="../java/index.html">ドキュメント</a>
</div>
<div class="menuItem">
<a href="../java/install.html">インストール</a>
</div>
<div class="menuItem">
<a href="../java/user-guide.html">ユーザガイド</a>
</div>
<div class="menuItem">
<a href="../java/developers-guide.html">開発者ガイド</a>
</div>
<div class="menuItem">
<a href="../java/integration-guide.html">統合ガイド</a>
</div>
<div class="menuItem">
<a href="../java/architecture-guide.html">アーキテクチャガイド</a>
</div>
<div class="menuItem">
<a href="../java/reference.html">リファレンスガイド</a>
</div>
<div class="menuItem">
<a href="../java/reading.html">読書ガイド</a>
</div>
<div class="menuItem">
<a href="../java/requirements.html">要件</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">Axis (C++)</span>
<div class="menuItem">
<a href="../cpp/index.html">Axis C++ 最新版</a>
</div>
<div class="menuItem">
<a href="../cpp/documentation.html">ドキュメント</a>
</div>
<div class="menuItem">
<a href="../cpp/download.html">ダウンロード</a>
</div>
<div class="menuItem">
<a href="http://wiki.apache.org/ws/FrontPage/AxisCPP">Wiki ページ [英語]</a>
</div>
<div class="menuItem">
<a href="../cpp/who.html">メンバ紹介</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">ダウンロード</span>
<div class="menuItem">
<a href="../releases.html">リリース</a>
</div>
<div class="menuItem">
<a href="../interim.html">暫定版</a>
</div>
<div class="menuItem">
<a href="http://cvs.apache.org/viewcvs/ws-axis/">ソースコード [英語]</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">翻訳</span>
<div class="menuItem">
<a href="http://ws.apache.org/axis/jp/">日本語</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">関連プロジェクト</span>
<div class="menuItem">
<a href="http://ws.apache.org/wsif/">WSIF [英語]</a>
</div>
<div class="menuItem">
<a href="http://cvs.apache.org/viewcvs/*checkout*/ws-wsil/java/README.htm">WSIL [英語]</a>
</div>
<div class="menuItem">
<a href="http://www-124.ibm.com/developerworks/projects/wsdl4j/">WSDL4J [英語]</a>
</div>
<div class="menuItem">
<a href="http://www.uddi4j.org/">UDDI4J [英語]</a>
</div>
</div>
<div class="menu">
<span class="menuLabel">その他</span>
<div class="menuItem">
<a href="../who.html">メンバ紹介</a>
</div>
<div class="menuItem">
<a href="../contact.html">連絡先</a>
</div>
<div class="menuItem">
<a href="../legal.html">法関連</a>
</div>
<div class="menuItem">
<a href="../docs.html">メモ/ドキュメント</a>
</div>
</div>
</div>
</div>
</div>
</td><td>
<div id="bodycol">
<div class="app">
<div align="center">
<h1>WebServices - Axis</h1>
</div>
<div class="h3">
<a name="Client-SideAxis"></a>
<div class="h3">
<h3>クライアント側 Axis</h3>
</div>
<p>内容目次</p>
<ul>
<li>
<a href="#Introduction">はじめに</a>
</li>
<li>
<a href="#CoreTCPIPConcepts">TCP/IP 概念の核心</a>
</li>
<li>
<a href="#CoreHTTPConcepts">HTTP 概念の核心</a>
</li>
<li>
<a href="#JAX-RPC">JAX-RPC</a>
</li>
<li>
<a href="#Testing">テスト</a>
</li>
<li>
<a href="#ConfiguringClient-sideHandlers">クライアント側のハンドラの設定</a>
</li>
<li>
<a href="#Redistribution">再配布</a>
</li>
<li>
<a href="#DynamicallyDiscoveringAndBindingToAWebService">Webサービスの動的発見と動的バインディング</a>
</li>
<li>
<a href="#CallConfiguration">Call 設定</a>
</li>
<ul>
<li>
<a href="#StandardProperties">標準プロパティ</a>
</li>
<li>
<a href="#AxisProperties">Axis プロパティ</a>
</li>
</ul>
<li>
<a href="#NetworkConfiguration">ネットワーク設定</a>
</li>
<li>
<a href="#TroubleshootingNetworkProblems">ネットワーク問題のトラブルシューティング</a>
</li>
<ul>
<li>
<a href="#WhatCanTheDeveloperOfAWebServiceClientApplicationDo">Webサービスクライアントアプリケーションの開発者は何ができる?</a>
</li>
</ul>
</ul>
<a name="Introduction"></a>
<div class="h4">
<h4>はじめに</h4>
</div>
<p>このドキュメントでは Axis を利用したWebサービスのクライアント側の開発に関連する問題を見ていきます。</p>
<p>Axis は SOAP をサポートしていて、SOAP は HTTP の上で構築されていて、HTTP は TCP/IP の上で構築されているプロトコルです。何が行われているか理解するには、下部レベルを理解することが重要です。</p>
<a name="CoreTCPIPConcepts"></a>
<div class="h4">
<h4>TCP/IP 概念の核心</h4>
</div>
<p>TCP/IP を詳細に説明するつもりはありません。なぜなら TCP/IP はあまりにも複雑だからです。ですが TCP/IP 技術のいくつかの概念と特徴はここで扱う価値があります。</p>
<p>TCP/IP は2つのコンピュータ、すなわち<i>ホスト</i>、の間に信頼できるチャネルを構築します。TCP を走らせているコンピュータは1から65535までのどの<i>ポート</i>に来るメッセージも受け取ることができます。それはマシン上のプログラムが<i>ソケット</i>を生成して、そのポートをリスンしている場合です。そうでない場合、<i>接続拒否</i>のメッセージを見ることになるでしょう。</p>
<p>クライアントがホストに接続する前に、クライアントはホストのアドレスを探す必要があります。TCP/IP の最も広くサポートされたバージョンである IPv4 は 127.0.0.1 (これは特別なアドレスで、ローカルシステムを意味します) のような32ビットのアドレスを利用します。ホストに接続するにはアドレスか、あるいはアドレスにマッピングできる "www.w3.org" のようなマシンの名前のいずれかが必要です。このマッピングは DNS によって提供されます。DNS は階層的なネットワークであり、インフラ全域で偏在しており、私達は普段当然のものと思っているものです。基本的に、DNS サーバはホスト名を受け取り、IP アドレスかエラーメッセージを返します。DNS サーバがどのようにアドレスを解決するかはこのドキュメントの範囲外なので、単にローカル DNS サーバはそれが必要だと思ったら他の DNS サーバに問い合わせるものだと思ってください。</p>
<p>すべてのシステムが DNS サポートを持っているわけではありません。システムは設定によって自分独自のホスト表を持つことができます。Unix システムでは /etc/hosts に、Windows システムでは c:\windows\system32\drivers\etc\hosts にあります。このファイルを編集して完全に DNS を迂回することができますが、維持管理は悪夢となります。もしあなたのユーザが DNS ではなく静的なホスト表を利用しているのであれば、深刻な嘆きなしにホストのネットワークアドレスを変更することはできません。</p>
<p>マシンは静的アドレス (ネットワーク管理者がアドレスを割り当て、長期に渡って維持します) か動的アドレスのいずれかを持ちます。後者はクライアントシステム、特にラップトップ、デスクトップPC、ダイアルアップコンピュータで一般的です。ブロードバンドコンピュータの多くは静的アドレスを持っていますが、それは ISP によります。</p>
<p>アドレスを解決した後、クライアントプログラムはソケットを生成し、サーバに接続を試みます。この時点で TCP プロトコルが作動し、クライアントは目的地に<i>データグラム</i>を送信することで会話を開始します。これによりリンクの設定が開始され、数個 (3個) のパケットが行き交います。一度接続がなされて作動すると、サーバに呼び出し側のことが伝えられ (サーバはクライアントの IP アドレスを取得できます)、サーバはクライアントと結び付いたソケットを接続期間中持ちます。クライアントとサーバは (a) もしデータが到着するのであれば、ソケットに書き込まれた順に到着する、そして (b) もし到着しなければエラーメッセージが得られる、という保証の元、お互い任意のバイナリデータを送信することができます。</p>
<p>知っておくべきいくつかの特別なことを挙げます。</p>
<ol>
<li>TCP は機能的リンクを探るために公開接続上でメッセージを (デフォルトでは) 送信しません。接続上で <i>keepalive</i> パケットを要求することによってこれを有効にすることができますが、帯域幅の無駄です。</li>
<li>TCP 接続が Nagle アルゴリズムで実行されることがデフォルトで有効になっています。これは、送信側が、受信側が扱える割合でのみ送信することにより、帯域幅の消費を制限する協調的な方法です。このアルゴリズムは適応しますが、遅さが増加します。もし無効にしたければソケット上で TCP_NODELAY を設定してください。</li>
</ol>
<p>ネットワーク上の通信において、<i>待機時間</i><i>帯域幅</i>が大きな制約となります。待機時間は通信するのにかかる時間で、ネットワーク配線と同様に、ルータやファイアーウォールのようなハードウェアも全て待機時間に追加されます。帯域幅は1秒間にどれだけ送信できるかの指標です。短い待機時間 (良い) のリンクは小さい帯域幅 (悪い) を持っているかもしれませんし、一方、距離が離れたリモートサーバのように、大きな帯域幅の接続は長い待機時間になるかもしれません。</p>
<p>ファイアーウォールは現代ネットワークの重要な機構です。ファイアーウォールは入ってくる呼び出しに対してポートを遮断します。<i>ステートフルファイアーウォール</i>はすべてのパケットを調べ、現在の TCP 会話の入ってくるパケットのみ許すものであり、さらに優れています。ファイアーウォールはセキュリティ的な理由から必要不可欠なもので、外の世界に向けてより多くのサービスをネットワークの後ろにさらすことができます。入ってくる呼び出しを制限するのと同様に、ファイアーウォールはしばしば外向きの接続を制限します。例えば、ポート80 (HTTP) への外向きの接続を遮断して HTTP プロキシサーバを利用させようとしたり (下をご覧下さい)、ポート143 (IMAP) への外向きの接続を遮断して外部のメールサーバへの接続をやめさせたりします。SOAP クライアントと SOAP サーバの間のネットワーク中にファイアーウォールがあることを想定する必要があり、それゆえサーバからクライアントへのコールバックは不可能となるでしょう。</p>
<a name="CoreHTTPConcepts"></a>
<div class="h4">
<h4>HTTP 概念の核心</h4>
</div>
<p>HTTP は基本的なもので、とても単純なプロトコルです。クライアントはリモートシステム上のあるポート、普通はポート番号80ですが、に対して TCP 接続をオープンします。次にクライアントは HTTP リクエスト (GET、POST、PUT のような動詞か、あるいはその他の標準リクエスト)、サーバに関連する URL、HTTP バージョン文字列を発行します。次にクライアントは0個以上のヘッダ (名前:値 の組が別々の行にある) と、ヘッダの終わりの示す空行を送信します。POST のようなデータアップロードを伴うリクエストは引き続きデータをアップロードします。そしてクライアントはサーバが返信するのを待ちます。</p>
<p>サーバは、ある数字、自身のいくつかのヘッダ、そして普通はリクエストのボディから構成される HTTP エラーコードで応答することができます。一般的にヘッダは MIME 型宣言と、"content-length" と "expires" のようなその他の有用なものが含まれています。</p>
<p>ファイアーウォールを通り抜けるには、多くの組織はプロキシサーバを走らせています。これは外部ネットワークにアクセスできるマシンであり、その他のイントラネットのマシンが外部ネットワークにアクセスできないのとは異なっています。クライアントはプロキシサーバにリクエストを送信する必要があり、次にそのリクエストは実際のサーバに転送されます。キャッシングプロキシサーバはリクエスト/レスポンスの組をキャッシュするので、よくあるリクエストは帯域幅を消費しません。これはとても有用ですが、キャッシュ可能なリクエスト (伝統的には GET リクエストのみ) に対してのみ機能します。<i>透過プロキシ</i>はプロキシの特殊形で、潜在的なネットワーク設定により HTTP リクエスト (特にポート80の HTTP リクエスト) を、アプリケーション設定なしにプロキシサーバを通して送信するプロキシです。一般的にこれらは不具合が生じない限り目に見えません。不具合が生じた場合、あなたのお気に入りのWebサービスがまるで人間に行くことになっている HTML を返すように見えます。これによりいくつかの興味深いサポート呼び出しを行うことができます。</p>
<p>HTTP 上の SOAP は、この下に横たわるプロトコル上で機能します。SOAP リクエストは XML 本体付きの POST であり、SOAP レスポンスは HTTP ステータスコードと理想的には XML メッセージから構成されます。通常の HTTP と同様に、ステータスコード 200 は全てが良好であることを意味しています。エラーコード 500 は内部サーバエラーを意味するか、SOAP スタックとサービスの両方、あるいは片方が <i>SOAPFault</i> をスローしたことを指し示すことができます。SOAPFault は標準化された XML メッセージで、受信者がパースできる情報を含んでいます。ある状況下では他の HTTP レスポンスコードが返されるかもしれませんが、WS-I 機関は、いつ、どのようにこれらが許されるかについての規則を規定しています。</p>
<p>SOAP は一般的に HTTP の上で実行されるので、認証とセッション管理 (すなわちクッキー) に対して古典的な HTTP 手法が全て適用されます。将来ある時点で別のトランスポートがより一般的になるかもしれず、その場合その HTTP 手法は機能しなくなることに注意してください。これが、多くの人が SOAP に基づく代替品、一般的には SOAP ヘッダを利用して構築されますが、を書いている理由です。Axis はそのコードベース内に別のトランスポートのプロトタイプをいくつか持っていますが、そのどれもが (まだ) 製品としての準備はできていません。</p>
<a name="JAX-RPC"></a>
<div class="h4">
<h4>JAX-RPC</h4>
</div>
<p>JAX-RPC 仕様は、クライアント側の Axis を構築する上で基盤となった仕様です。もしクライアントを書いているのであればお読みください。</p>
<p>SOAP メッセージを処理するサーバの URL である SOAP <i>エンドポイント</i>を呼び出すために JAX-RPC を利用するのに、基本的には2通りの方法があります。1つめの方法は、javax.xml クラスを利用して手で SOAP 呼び出しを構築し、リモートサーバを呼び出す方法です。これは面倒ですが、現場の裏で何が行われているかの知識を得ることができます。つまり、XML メッセージが構築され、リモートサーバに送信され、そのレスポンスがパースされて分解されます。このレベルで書かれたクライアントコードは、どの JAX-RPC 実装でも実行できるはずです。</p>
<p>もう1つの方法は、呼び出しの詳細を Axis に隠させて、Webサービス用のラッパクラスを生成させる方法です。これはサービスの WSDL 記述を受け取り、そして各操作に対して SOAP リクエストを構築し、結果を宣言された戻り値に後処理する、これらに適した低レベル呼び出しを作成する Java クラスを生成します。Axis は WSDL 内に含まれるサービスの全ての URL の注釈を受け取り、これをクラスにコンパイルします。ですからクライアントは WSDL が宣言している URL、これはしばしば WSDL が取り出された (デプロイ) サーバの URL ですが、に自動的にバインドされます。</p>
<p>この、<i>プロキシクラス</i>の自動生成は有用です。なぜならこれは、リモートWebサービスの呼び出しをローカルオブジェクトの呼び出しとほとんど同じように見えさせるからです。しかしながらこれには開発者が注意する必要があるいくつかの不都合があります。</p>
<ul>
<li>これらの生成されたクラスは Axis とのみ互換性があります。これは JAX-RPC 仕様で許されています。JAX-RPC 仕様は実行時の互換性ではなくコンパイル時の互換性の観念があるからです。もし Sun や BEA の SOAP 実装と機能するスタブクラスがほしいのであれば、それらのプラットフォームツールを利用して WSDL からすタブクラスを生成する必要があるでしょう。スタブクラスは全て同じ名前と同じメソッドを持つべきであり、ですから残りのコードは変更すべきではありません。</li>
<li>JAX-RPC 標準は、サービスの操作とパラメータ名から、有効な Java メソッドと変数名への変換を定義しています。結果はあなたが望んでいたものと違うかもしれません。</li>
<li>Webサービス URL へバインドするのはコンパイル時では早すぎます。いくつかの設定や動的バインディングルーチンを追加する必要があります。</li>
<li>リモートWebサービスはローカルオブジェクトと同じではありません。リモートWebサービスはあなたを道に迷わせようとするふりをします。特に、ローカルオブジェクトのメソッド呼び出しはしばしば数ミリ秒しかかかりませんが、一方、リモートサービスの呼び出しは数十秒かかり、処理中に原因不明のネットワークエラーで失敗し、呼び出しが成功したか失敗したかどうかユーザを不安にさせます。WebサービスからWebサービスへのブロック呼び出しをするとエンドユーザはとても不幸な経験をすることになるでしょう。</li>
<li>サービスのデプロイにも関係するかもしれませんが、クライアントをコンパイルする前に WSDL が必要であるため、より複雑なビルドプロセスになります。</li>
</ul>
<p>個人的な経験に基づきますが、スタブクラスの動的生成はとても有用です。なぜならそれによりクライアント側のコードを簡素化し、いつサービスが互換性のない方法で操作のシグネチャを変更したかをクライアントソースが認識する手助けとなるからです。もし操作のパラメータが変更されたら、Java メソッドのパラメータも変更されるので、それゆえそのアプリケーションはもはや構築されません。</p>
<p>しかしながら、<i>Webサービスはローカルオブジェクトではない</i>ということを常におぼえておくことは間違いなく重要です。プロキシクラスはローカルのように見えますが、サーバは細い接続ではるか遠くにあるかもしれません。</p>
<p>
<i>GUI スレッドからWebサービスにブロック呼び出しを絶対にしないでください。</i>
</p>
<a name="Testing"></a>
<div class="h4">
<h4>テスト</h4>
</div>
<p>Axis サービスをテストしたいのであれば、Wsdl2Java に対してリモートサービスが実装する1つ1つの操作全てのテストケースを含むスタブ JUnit テストクラスを生成するように指定することができます。これらのスタブテストケースは、有効なテストデータと、それに続く、結果の有効性を確かめる関連するアサーションで埋められる必要があります。</p>
<p>生成されたテストケースは IDE や Ant に基づいたビルドプロセスや Maven に基づいたビルドプロセスで実行することができます。</p>
<p>クライアント、すなわちテストケースをテストする際に、分散アプリケーションが経験するであろう特別な障害形態を実験しましょう。プログラムの異なる場所でネットワークコネクタを抜いてください。同じホスト上の無効な URL や、存在しないホストにサービスを接続するように設定してください。プロキシサーバを経由することを試してください。遅い接続を利用することを試してください。これは TCP Monitor プログラムがシミュレートしてくれます。</p>
<p>Webサービスのテストを手助けしてくれるサードパーティのアプリケーションもあります。SOAP monitor の提供や、形式に基づいた SOAP リクエストの構築などです。これらは便利ですが、それらに対してお金を払う必要はありません。</p>
<p>sourceforge にある <a href="http://aft.sourceforge.net/">Anteater</a> [英語] は SOAP 呼び出しの Ant に基づいたテスト方法です。あなたはペイロードを提供し、次にその結果の有効性を確認するために xpath パスを利用します。これはいくぶん低レベルに思えるかもしれませんが、とても強力です。</p>
<a name="ConfiguringClient-sideHandlers"></a>
<div class="h4">
<h4>クライアント側のハンドラの設定</h4>
</div>
<p>
<i>TODO</i>
</p>
<p>Axis はクライアント側 JAX-RPC と Axis ハンドラの両方を提供しています。サーバ側のハンドラと同様に、これらのハンドラはメッセージが送信される前と受信した後に呼ばれます。</p>
<a name="Redistribution"></a>
<div class="h4">
<h4>再配布</h4>
</div>
<p>Axis を実行しているアプリケーションを再配布するには以下のものを再配布する必要があります。</p>
<ul>
<li>axis.jar</li>
<li>commons-logging.jar</li>
<li>commons-logging と互換性のあるロギング実装です。Java1.4 が持っているロギング機構には互換性があるので、Java1.4 にロギングを含める必要はありません。他のものとして log4j.jar をお勧めします。</li>
<li>あなたが選んだロガーのロギング設定ファイル</li>
<li>XML パーサ。Java1.4 には crimson が付いてきますが、axis チームは xerces を強くお勧めします。</li>
<li>commons-discovery.jar</li>
</ul>
<p>Axis JAR は署名されていないので、Java の Web Start 機構にある自動ダウンロードとしては利用できません。</p>
<p>現在のところ、wsdl は実行時に処理されていないので、wsdl4j.jar を含める必要はありません。これは doc/lit メッセージをサポートするのに SOAP メッセージの構造についての知識がさらに必要なった (つまり WSDL ファイルや、コンパイル時に WSDL ファイルから生成されたその他のメタデータの制限された実行時処理を意味します) 将来のある時点で変更されるかもしれないということに注意してください。</p>
<a name="DynamicallyDiscoveringAndBindingToAWebService"></a>
<div class="h4">
<h4>Webサービスの動的発見と動的バインディング</h4>
</div>
<p>Axis が WSDL からクライアントプロキシクラスコードを生成する際、Axis はコードを WSDL 内で指定しているエンドポイント URL (これは一般的には入ってくるリクエストの URL から生成される URL です) にバインドします。WSDL ページを取ってくるのに http://localhost URL を利用すると、クライアントコードも localhost に提供されたサービスにバインドされることになり、再配布可能なものでは望ましくないでしょう。同様に、WSDL を取ってくる際にホスト名を利用する場合でも、短い名前ではなく完全修飾ドメイン名が必要で (http://s1/ ではなく http://s1.example.org/)、さもなければあなた自身のドメイン内やサブネット内の呼び出し者しかサーバを見つけることができません。手で書かれた WSDL ではこの問題は発生しません。なぜなら WSDL 内のエンドポイントは著者が打ち込んだものだからです。</p>
<p>クライアント上の URL を更新する何らかの方法を提供することはほとんど必要不可欠です。最も簡単なのは、Axis コマンドラインツールで利用されているように、何らかのコマンドライン上書きオプションです。より高度なものとしては URL を入力するためのダイアログボックスで、さらに高度なものは何らかの自動化された発見機構です。</p>
<p>Axis はその JAR 内で発見機構を一切提供していません。UDDI レジストリへのアクセスを提供する姉妹プロジェクト <a href="http://ws.apache.org/juddi/">jUDDI</a> [英語] があります。また Axis CVS ツリー内に Axis と機能するマルチキャスト発見 jar があります。これは XML メッセージを利用する概念実証機構ですが、どの既存の標準とも互換性はありません。LAN ネットワーク上では機能しますが、より広い領域で利用されるように設計されてはいません。</p>
<p>
<i>TODO: サービス内で URL を設定する方法</i>
</p>
<a name="CallConfiguration"></a>
<div class="h4">
<h4>Call 設定</h4>
</div>
<p>Call オブジェクトは呼び出しが作成される前に設定することができます。<span class="codefrag">org.apache.axis.client.Call</span><span class="codefrag">javax.xml.rpc.Call</span> インターフェースの Axis 版実装です。JAX-RPC 標準インターフェースは呼び出し者がプロパティを設定できる <span class="codefrag">setProperty()</span> メソッドを定義しています。あなたが設定できるものとして JAX-RPC 標準プロパティと Axis 独自のプロパティの両方があります。</p>
<p>全てのプロパティは、Call クラス内の public static final 宣言で定義されている名前である、文字列名を持っています。</p>
<a name="StandardProperties"></a>
<div class="h2">
<h2>標準プロパティ</h2>
</div>
<table class="ForrestTable" cellspacing="3" cellpadding="4" border="1">
<col width="85*">
<col width="85*">
<col width="85*">
<thead>
<tr class="b">
<th colspan="1" rowspan="1" width="33%">
<p>プロパティ名</p>
</th>
<th colspan="1" rowspan="1" width="33%">
<p>説明</p>
</th>
<th colspan="1" rowspan="1" width="33%">
<p></p>
</th>
</tr>
</thead>
<tbody>
<tr class="b">
<td colspan="1" rowspan="1" width="33%">
<p>USERNAME_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>認証用のユーザ名</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="33%">
<p>PASSWORD_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>認証用のパスワード</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="33%">
<p>SESSION_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>endpoint? と共にセッションに参加</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>Boolean</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="33%">
<p>OPERATION_STYLE_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>オペレーションの型</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String "rpc" か "document"</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="33%">
<p>SOAPACTION_USE_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>SOAPAction の利用有無</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>Boolean</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="33%">
<p>SOAPACTION_URI_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>もし SOAPAction が利用されているのであれば、これがそのアクションとなる</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="33%">
<p>ENCODING_STYLE_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>データのエンコード方法。<br>デフォルトは SOAP 1.1:</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String. "http://schemas.xmlsoap.org/soap/encoding/"</p>
</td>
</tr>
</tbody>
</table>
<a name="AxisProperties"></a>
<div class="h2">
<h2>Axis プロパティ</h2>
</div>
<table class="ForrestTable" cellspacing="3" cellpadding="4" border="1">
<col width="99*">
<col width="72*">
<col width="85*">
<thead>
<tr class="b">
<th colspan="1" rowspan="1" width="39%">
<p>プロパティ名</p>
</th>
<th colspan="1" rowspan="1" width="28%">
<p>説明</p>
</th>
<th colspan="1" rowspan="1" width="33%">
<p></p>
</th>
</tr>
</thead>
<tbody>
<tr class="b">
<td colspan="1" rowspan="1" width="39%">
<p>SEND_TYPE_ATTR</p>
</td>
<td colspan="1" rowspan="1" width="28%">
<p>XSI 型属性の送信有無
</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>Boolean</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="39%">
<p>CONNECTION_TIMEOUT_PROPERTY</p>
</td>
<td colspan="1" rowspan="1" width="28%">
<p>トランスポートセンダーが利用するタイムアウト(ミリ秒)</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>Integer</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="39%">
<p>TRANSPORT_NAME</p>
</td>
<td colspan="1" rowspan="1" width="28%">
<p>利用するトランスポートハンドラ名</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="39%">
<p>ATTACHMENT_ENCAPSULATION_FORMAT</p>
</td>
<td colspan="1" rowspan="1" width="28%">
<p>添付を MIME (デフォルト) か DIME で送る</p>
</td>
<td colspan="1" rowspan="1" width="33%">
<p>String <br>"axis.attachment.style.mime" か <br>"axis.attachment.style.dime"</p>
</td>
</tr>
</tbody>
</table>
<p>ポータブルクライアントでもこれらの Axis 特有のプロパティを設定することができます。もちろんこれらのオプションは他の JAX-RPC 実装では機能しません。</p>
<a name="NetworkConfiguration"></a>
<div class="h4">
<h4>ネットワーク設定</h4>
</div>
<p>Axis は JVM 内で実行され、JVM パラメータはクライアントの振る舞いを制御します。利用される JVM 設定オプションを以下に挙げます。</p>
<table class="ForrestTable" cellspacing="3" cellpadding="4" border="1">
<col width="97*">
<col width="108*">
<col width="51*">
<thead>
<tr class="b">
<th colspan="1" rowspan="1" width="38%">
<p>名前</p>
</th>
<th colspan="1" rowspan="1" width="42%">
<p>意味</p>
</th>
<th colspan="1" rowspan="1" width="20%">
<p></p>
</th>
</tr>
</thead>
<tbody>
<tr class="b">
<td colspan="1" rowspan="1" width="38%">
<p>http.proxyHost</p>
</td>
<td colspan="1" rowspan="1" width="42%">
<p>プロキシサーバのホスト名</p>
</td>
<td colspan="1" rowspan="1" width="20%">
<p align="center">web-proxy</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" valign="top" width="38%">
<p>http.proxyPort</p>
</td>
<td colspan="1" rowspan="1" valign="top" width="42%">
<p>プロキシサーバのポート</p>
</td>
<td colspan="1" rowspan="1" sdnum="2057;" sdval="8080" valign="bottom" width="20%">
<p align="center">8080</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="38%">
<p>http.proxyUser</p>
</td>
<td colspan="1" rowspan="1" width="42%">
<p>プロキシ認証用の省略可能なユーザ名</p>
</td>
<td colspan="1" rowspan="1" width="20%">
<p align="center">someone</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="38%">
<p>http.proxyPassword</p>
</td>
<td colspan="1" rowspan="1" width="42%">
<p>省略可能なプロキシサーバパスワード</p>
</td>
<td colspan="1" rowspan="1" width="20%">
<p align="center">secret</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" valign="top" width="38%">
<p>networkaddress.cache.ttl
</p>
</td>
<td colspan="1" rowspan="1" valign="top" width="42%">
<p>解決済みのホスト名をキャッシュする秒数<br>-1 == 永久、0 == キャッシュしない</p>
</td>
<td colspan="1" rowspan="1" sdnum="2057;" sdval="120" valign="bottom" width="20%">
<p align="center">120</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" valign="top" width="38%">
<p>networkaddress.cache.negative.ttl</p>
</td>
<td colspan="1" rowspan="1" valign="top" width="42%">
<p>未解決ホスト名をキャッシュする秒数<br>-1 == 永久、0 == キャッシュしない</p>
</td>
<td colspan="1" rowspan="1" sdnum="2057;" sdval="30" valign="bottom" width="20%">
<p align="center">30</p>
</td>
</tr>
</tbody>
</table>
<p>これらのオプションのほとんどはプロキシサーバ設定を制御します。もしそれらの設定オプションがなく、かつインターネットアクセスにプロキシサーバが必要であれば、クライアントはある種の接続エラーやその他のものを受け取ることになるでしょう。もし設定オプションがあり、かつ間違っていれば、クライアントは同じように接続エラーを受け取るでしょう。ユーザは、アプレットをホストする際に JVM のプロキシ設定を設定することができますが、この設定はアプリケーションに反映されないことに注意してください。これは Java ネットワークの多くの謎のうちの1つです。</p>
<p>
<i>どのWebサービスクライアントアプリケーションも、プロキシサーバ設定を設定するための何らかの方法を提供する必要があります。サポート呼び出し診断のためにこれらをどこかに表示しておいても有用です。</i>
</p>
<p>最後の2つのプロパティは厄介です。これらはあまり知られていないのでなおさら厄介です。これらを調べるには <i>java.net.InetAddress</i> の下にある "Address Caching" をご覧下さい。あるいは単にあなたの DNS サーバを数分止めて、DNS サーバがない時にあなたのアプリケーションが接続に失敗することだけでなく、DNS サーバが再び立ち上がった時にサーバは到達不能のままであることを観察してください。</p>
<p>何が起こっているかというと、ランタイムは DNS クエリを利用して解決したホスト名の IP アドレスをキャッシュしています。デフォルトではこれらは永久にキャッシュされるので、長い間実行されている Java アプリケーションは、クライアントの生存期間中にリモートサーバの IP アドレスが変更されると切断されます。同様に、ランタイムはアドレスに解決できなかったホスト名をキャッシュします。Java1.3 ではこれらの失敗した検索は永久にキャッシュされます。つまりもし DNS が停止していたり、ネットにつながっていないラップトップの場合、クライアントは二度と探しあてることはできなかったのです。</p>
<p>重要なアプリケーションに対して、キャッシュされたホスト名のための実用的な存続期間でキャッシュオプションを設定することは明らかに必要不可欠です。(Java1.4 では) これらの値は Java Security Properties で、これらは java.security.Security.setProperty() を利用して設定します。Java1.3 以前のバージョンではコマンドライン上でのみ実行できた、プロパティを扱うなんらかの別の機構がありました。私達が忘れない限り、そのプロパティが何であるか伝えます。</p>
<a name="TroubleshootingNetworkProblems"></a>
<div class="h4">
<h4>ネットワーク問題のトラブルシューティング</h4>
</div>
<p>分散システムの古典的な定義は以下の通りです。</p>
<p>&ldquo;<i>あるコンピュータがクラッシュした時に、それによってあなたの仕事ができなくなるということをあなたは聞いたことがないかもしれませんが、実際にクラッシュした時に仕事ができなくなったというトラブルをあなたは抱えたことがあるはずです&rdquo; Leslie Lamport</i>
</p>
<p>これは滑稽に聞こえるかもしれませんが、分散システムの状況の情けないほど的中したモデルです。ウェブサイトが時々オフラインであったり、ページが時々不完全のまま提供されている、あるいは結果の代わりにいくつかのエラートレースが出ていたりすることを誰もが知っています。</p>
<p>Webサービスも同様ですが、人間がウェブブラウザに表示されたエラーページを読む替わりに、クライアントソフトウェアがエラーを受け取ってそれを扱ったり報告したりする必要があること、は異なります。</p>
<p>Axis クライアントコードがエラーを受け取ると例外、特に java.rmi.RemoteException のサブクラスをスローします。これは AxisFault でもいいし、その他のものでもかまいません。どちらにしてもトラブルを意味しています。一般的には例外のフォルト文字列は経験豊かなアプリケーション開発者に意味のあるエラーテキストを提供しますが、エンドユーザやサポートチームにとってはあまり意味がないでしょう。</p>
<p>以下に、クライアントアプリケーションが受け取るであろうネットワークに関連するエラーレスポンスのリストを示します。Axis の adminclient アプリケーションは SOAP クライアントなので、adminclient もこれらのレスポンスを見ることができます。Sitefinder コメントは、VeriSign SiteFinder やその後継がそれぞれ独自の目標のために DNS の標準的な振る舞いを覆す、つまりWebサービスの標準的な失敗モードを複雑にする行為、の場合にのみ特有です。</p>
<table class="ForrestTable" cellspacing="3" cellpadding="4" border="1">
<col width="70*">
<col width="186*">
<tr class="b">
<td colspan="1" rowspan="1" width="27%">
<p>Connection refused (接続拒否)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>ホストは存在するけど、そのポートの接続に対して何もリスンしていないことを示します。あるいは、ファイアーウォールがそのポートを遮断していることを示しています。<br>
<i>Site Finder: 指定した URL が80以外のポートを利用していて、かつ、.com または .net アドレスが無効であることを意味しています。</i>
</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="27%">
<p>Unknown host (不明ホスト)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>指定した URL のホスト名コンポーネントが無効であるか、クライアントがオフラインであることを意味しています。</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="27%">
<p>404: Not Found (404: 見つかりません)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>そこにWebサーバはありますが、指定したその URL には何もないことを意味しています。プロキシサーバは不明ホストに対して 404 ページを生成することもあります。</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="27%">
<p>302: Moved (302: 移動済み)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>指定した URL の最後の部分のコンテンツが移動されていて、クライアントアプリケーションはリンクをたどらないことを意味しています。</p>
<p>
<i>Site Finder: .com あるいは .net アドレスが無効で、ポートは明示的に (あるいはデフォルトで) ポート80であることを意味しています。</i>
</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="27%">
<p>Other 3xx response (その他の 3xx レスポンス)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>指定した URL の最後の部分のコンテンツが移動されていて、クライアントアプリケーションはリンクをたどらないことを意味しています。</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="27%">
<p>Wrong content type/MIME type (間違った content type、あるいは MIME type)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>指定した URL が間違っているか、あるいはサーバアプリケーションが XML を返していないことを意味しています。<br>
<i>Site Finder: ホストが不明である場合 302 レスポンスを返します。</i>
</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="27%">
<p>XML parser error (XML パーサエラー)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>これはコンテンツが XML ではなく、クライアントアプリケーションが XML を要求している際に発生します。<br>
<i>Site Finder: これは不明ホストに起因する302レスポンスの本体で、クライアントアプリケーションはリターンコードと Content-Type ヘッダをチェックするべきです。</i>
</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="27%">
<p>500: Internal Error (500: 内部エラー)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>SOAP は SOAPFault が戻ってきたことの合図としてこれを利用しますが、'サーバは何らかの内部フォルトを通じて機能していない' ことも意味しています。</p>
</td>
</tr>
<tr class="b">
<td colspan="1" rowspan="1" width="27%">
<p>Connection Timed out/ NoRouteToHost (接続タイムアウト / NoRouteToHost)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>ホスト名を解決することはできますが、届かないことを意味しています。ホストがない (一時的なフォルトの可能性あり) か、ネットワーク問題かファイアーウォール問題がアクセスを妨害しているかのどちらかです。クライアントはそのプロキシサーバを設定する必要があります。これは呼び出し側が完全にオフラインの場合にも現れます。</p>
</td>
</tr>
<tr class="a">
<td colspan="1" rowspan="1" width="27%">
<p>GUI hangs/ long pauses (GUI のハングアップ / 長い一時停止)</p>
</td>
<td colspan="1" rowspan="1" width="73%">
<p>クライアントアプリケーションが検索や接続でタイムアウトになっているかもしれません。</p>
</td>
</tr>
</table>
<p>そのようなメッセージへのサポートラインの初期レスポンスは全て同じにするべきです。</p>
<blockquote>
<i>接続問題が疑わしい場合、問題が発生している URL を取得し、呼び出し側に彼らのウェブブラウザで見させ、あなた自身で見れるか確かめます。</i>
</blockquote>
<p>これは、Webサービスプロトコル (REST、XML-RPC、SOAP) が全て HTTP 上で構築されていて、URL によるサービス定義という共通基盤概念を利用しているという事実の利点を活かす場面です。それらの同じ URL を提供することにより何らかの人間が読みやすいコンテンツ (たとえそれが XML メッセージだとしても) を生成し、エンドユーザとサポート窓口はお互い彼らのウェブブラウザ内で表示することができます。この行動は、接続問題を診断する上での核心となるテクニックです。なぜなら本来、HTTP インフラ (サーバ、プロキシ、クライアント) はこの診断プロセスをサポートするために設計されているからです。</p>
<p>Webサービスプロバイダは以下によって上記プロセスを単純化できます。</p>
<ul>
<li>サービス内で利用される全ての URL において、人間の読めるコンテンツにします。特に、たとえ "ここに SOAP エンドポイントがあります" というようなメッセージを返すだけでも、GET リクエストをサポートするべきです。</li>
<li>人間の読める URL を利用します。短く、電話を通じて表現できるものが理想的です。</li>
<li>段階的拡大パスを提供するための、サポートがアクセス可能なロギングを持つことにより、問題はサーバ側であることが判明します。</li>
</ul>
<p>その他の有用なテクニックとしては、サービスに "Ping" デザインパターンを提供させることです。サービスはすぐに戻ってくる簡単な "ping" 操作をサポートする必要があります。この操作は、その他の副作用やサーバにそれほど負荷を与えることさえなくサービスの存在を証明するために、クライアントによって利用されます。クライアントアプリケーションは最初にピングすることによってサーバとの通信 (アップロード、複雑なリクエストなど) を初期化する必要があります。これにより早い段階で、うまくいけば低いコストで、不具合を検出できます。</p>
<a name="WhatCanTheDeveloperOfAWebServiceClientApplicationDo"></a>
<div class="h2">
<h2>Webサービスクライアントアプリケーションの開発者は何ができる?</h2>
</div>
<p>ネットワークは基本的には信頼できません。ラップトップはあちこち移動してオフラインになり、サービスはスイッチオフになります。</p>
<p>あなたのアプリケーションは、接続問題を扱い、問題が診断できてかつ訂正できるように失敗する必要があります。Axis は自身でこれを行わないので、あなたが手助けする必要があります。</p>
<ol>
<li>フレームワークのエラー/例外を、エンドユーザにとって分かりやすいエラーメッセージに翻訳することは良いことです。XML パーサエラー、HTTP エラーコード、MIME 型の不平については、サポート組織は必要とするかもしれませんが、平均的なエンドユーザにはふさわしくありません。</li>
<li>失敗したターゲット URL は、エンドユーザが手でそれをテストできるように、エンドユーザに公開される必要があります。</li>
<li>どのようなエラーに対しても、レスポンス本体はサポートの利益のために保存する必要があります。</li>
<li>上にリストアップしたフォルト診断マトリクスはクライアントに適応し、ドキュメントに含める必要があります。</li>
<li>もしサービスが Ping オペレーションを実装しているのであれば、それを利用してサービスの存在を探ります。できれば GUI がブロックしないようにバックグラウンドスレッドや非同期呼び出しで行ってください。</li>
<li>クライアントは、遅くて信頼できないネットワークを介してテストする必要があります。Axis tcpmon SOAP monitor/HTTP proxy を利用して遅い HTTP 接続をシミュレートすることができます。</li>
<li>受け取ったコンテンツの MIME 型が、まさにそれに文書化されたものであることを必ず検証してください。</li>
<li>HTTP レスポンスコードと、XML が期待されている時は HTML レスポンスの、クライアントの取り扱いをテストしてください。</li>
<li>java.io.InetAddress の下の "Address Caching" にある Java ドキュメントをご覧下さい。アプリケーションは短期間の DNS 検索 (成功と失敗) のみをキャッシュするように設定する必要があります。</li>
</ol>
<div id="pdf" align="right">
<a href="client-side-axis.pdf"><img alt="PDF" src="../skin/images/pdfdoc.gif" class="skin"><br>
PDF</a>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="footer">
<table summary="footer" cellspacing="0" cellpadding="4" width="100%" border="0">
<tbody>
<tr>
<td colspan="2">
<div align="center">
<div class="copyright">
Copyright &copy; 2000-2005&nbsp;The Apache Software Foundation. All rights reserved.
</div>
</div>
</td>
</tr>
<tr>
<td align="left"></td><td align="right">
<div align="right">
<div class="credit"></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>