この章では、サーブレットの主な機能とAPI、WebSphereでのサーブレットAPIとその標準に対する拡張機能のサポート、およびOC4JでのサーブレットAPIのサポートについて説明します。また、WebSphere上にデプロイされているサーブレットからOracle Application Server のOC4Jコンテナへの移行パスの手順も示します。
サーブレットは、Webコンテナおよびサーブレット・エンジンで実行されるJavaクラスのインスタンスです。サーブレットを使用して、動的なWebページを生成します。サーブレットでは、通常はHTTPプロトコルを使用して、Webクライアントからのリクエストの受信および応答が行われます。
サーブレットには、従来のCGIプログラミングと比較すると次のメリットがあります。
各サーブレットは、別のプロセスでは実行されません。したがって、リクエストごとに新しいプロセスを作成するというオーバーヘッドが解消されます。
サーブレットは、リクエストを終了してから次のリクエストを行うまでの間もメモリーに保持されます。CGIプログラム(および大規模なランタイム・システムまたはインタプリタ)は、CGIのリクエストごとにロードして起動する必要があります。
すべてのリクエストを同時に処理する1つのみのインスタンスが存在します。これによって、メモリーが節約され、永続的なデータをサーブレットで簡単に管理できます。
サーブレットは、(アプレットがWebブラウザのサンドボックス内で実行される方法と同様の方法で)制限付きのサンドボックス内でサーブレット・エンジンによって実行できるため、安全に使用できます。
サーブレットは、スケーラブルであり、複数のアプリケーション・サーバー構成をサポートしています。サーブレットでは、データのキャッシュ、データベースへのアクセス、および他のサーブレット、JSPファイル、(環境によっては)Enterprise JavaBeansなどとのデータの共有も可能です。
サーブレットAPIは、javax.servletおよびjavax.servlet.httpという2つのJava拡張パッケージで指定されています。ただし、ほとんどのサーブレットでは、サーブレットAPIの標準的な実装であるjavax.servlet.GenericServletおよびjavax.servlet.http.HttpServletのいずれかが拡張されています。これらのうち、javax.servletのクラスおよびインタフェースはプロトコルに依存しませんが、javax.servlet.httpにはHTTPに固有のクラスが含まれています。
サーブレットAPIのサポートは、次の4つのカテゴリで提供されています。
サーブレットのライフ・サイクル管理
サーブレット・コンテキストへのアクセス
ユーティリティ・クラス
HTTP固有のサポート・クラス
使用する目的に応じて、サーブレットAPIクラスが識別されます。
| 目的 | クラスまたはインタフェース |
|---|---|
|
サーブレットの実装 |
|
|
サーブレットの構成 |
|
|
サーブレットの例外 |
|
|
リクエスト/レスポンス |
|
|
セッション・トラッキング |
|
|
サーブレット・コンテキスト |
|
|
サーブレット・コラボレーション |
|
サーブレットは、Webサーバー自体と同じプロセスの一部として、Webサーバー・プラットフォームで実行されます。Webサーバーでは、各サーブレット・インスタンスの初期化、起動、および破棄が行われます。Webサーバーでは、javax.servlet.Servletという単純なインタフェースを介してサーブレットとの通信が行われます。
このインタフェースは、次の3つの主要メソッドで構成されています。
init()
service()
destroy()
また、次の2つの補助メソッドも含まれています。
getServletConfig()
getServletInfo()
init()メソッドサーブレットが初めてロードされると、init()メソッドが起動され、ファイルのオープン、サーバー接続の確立などの初期プロセスが開始されます。サーブレットは、サーバーに永続的にインストールされた場合、サーバーの起動時にロードされます。
そうでない場合、サーブレットは、サーブレットによって提供されるサービスへの最初のクライアント・リクエストがサーバーで受信されると、サーバーによってアクティブ化されます。init()メソッドは、service()メソッドへのコールなどの他のコールがサーブレットに行われる前に終了することが保証されています。init()メソッドは、1回のみコールされます。サーブレットがサーバーによって再ロードされないかぎり、再度コールはされません。
init()メソッドは、ServletConfigオブジェクトへの参照である1つの引数を取ります。このオブジェクトによって、サーブレットに初期化引数が提供されます。このオブジェクトには、サーブレットの環境に関する情報が格納されているServletContextオブジェクトを戻すgetServletContext()メソッドが含まれています。
service()メソッドservice()メソッドは、サーブレットの中心的な機能です。クライアントからのリクエストごとに、サーブレットのservice()メソッドが1回コールされます。service()メソッドでは、次の2つのパラメータを使用して、リクエストの読取りおよびレスポンスの生成が行われます。
クライアントからのデータが含まれているServletRequestオブジェクト。データは、パラメータの名前/値のペアおよびInputStreamで構成されています。クライアントのパラメータ情報を戻すいくつかのメソッドが提供されています。クライアントのInputStreamは、getInputStream()メソッドを使用して取得できます。このメソッドによってServletInputStreamが戻されます。これを使用して、クライアントから追加データを取得できます。バイト・レベルではなく文字レベルでデータを処理する必要がある場合は、かわりにgetReader()を使用してBufferedReaderを取得できます。
クライアントに戻すサーブレットの応答を表すServletResponse。レスポンスを準備する場合は、まずメソッドsetContentType()をコールして、応答のMIMEタイプを設定します。次に、getOutputStream()メソッドを使用してServletOutputStream取得するか、またはgetWriter()メソッドを使用してPrintWriterを取得し、データをクライアントに戻します。
クライアントがサーブレットに情報を送信するには2つの方法があります。1つはパラメータ値を送信する方法で、もう1つはInputStream(またはReader)を使用して情報を送信する方法です。パラメータ値は、URLに埋め込むことができます。service()メソッドのジョブは単純です。このジョブでは、ホスト・サーバーから送信されてくるクライアント・リクエストごとにレスポンスが作成されます。ただし、同時に処理されるサービス・リクエストが複数存在する場合があります。サービス・メソッドでファイル、データベース、外部データなどの外部リソースが必要な場合、リソースへのアクセスは、スレッドセーフにする必要があります。
destroy()メソッドdestroy()メソッドをコールすると、サーブレットがアンロードされる前に、サーブレットのすべてのリソース(オープンされているファイル、データベース接続など)をクリーンアップできます。このメソッドは、クリーンアップ操作が不要な場合、空にすることができます。
サーバーは、すべてのサービス・コールが完了するか、または一定の時間が経過するまでdestroy()メソッドのコールを待機します。つまり、destroy()メソッドは、実行時間が長いservice()メソッドの実行中にコールされる可能性があります。destroy()メソッドは、すべてのservice()コールが完了するまで必要なリソースがクローズされないように記述する必要があります。
HTTPは、ステートレスなプロトコルであるため、クライアントがリソースをリクエストするたびにサーバーに対して別の接続がオープンされます。また、接続間でコンテキストが保持されないため、各トランザクションは独立したものとなります。ただし、ほとんどのWebアプリケーションはステートレスではありません。堅牢なWebアプリケーションでは、ユーザーと対話し、ユーザーのリクエストの性質を記憶し、あるリクエストでユーザーに関して収集したデータを、同じユーザーからの次回のリクエストで利用できるようにする必要があります。代表的な例には、インターネット商取引でのショッピング・カート・アプリケーションがあります。サーブレットAPIでは、複数の接続にまたがる場合でも、セッションの識別およびセッションへのデータの関連付けのための技術が提供されます。これらの技術には、次のものがあります。
Cookie
URLリライティング
非表示のフォーム・フィールド
(使用されている技術に関係なく)アプリケーション・コード内のセッション情報を手動で管理する必要性をなくすには、JavaサーブレットAPIのHttpSessionクラスを使用します。HttpSessionインタフェースを使用すると、サーブレットで次の処理を実行できます。
セッションに関する情報の表示および管理。
複数のページ・リクエストおよび接続を含めるための複数のユーザー接続にまたがる情報の保持。
Cookieがセッション・トラッキングの最も一般的な方法です。Cookieでは、クライアント・マシン上の人間が判読可能なファイルに、セッションに関する情報が格納されます。後続のセッションでは、Cookieにアクセスして情報を抽出できます。サーバーでは、CookieからのセッションIDがそのセッションのデータに関連付けられます。関連するCookieが複数ある場合、Cookieの有効期限を決定する必要がある場合、および一意のセッション識別子が多数必要な場合、この処理は複雑になります。また、Cookieには、最大サイズが4KB、ドメイン当たりの最大数が20個という制限もあります。Cookieには、ユーザーのプライバシの問題もあります。自身のローカル・ディスクの情報をプログラムによって格納および取得されることを好まず、Cookieを無効にしたり、Cookieを完全に削除するユーザーもいます。したがって、セッション・トラッキングのメカニズムをCookieのみに頼ることはできません。
HttpSessionオブジェクトセッション・データは、収集する方法にかかわらず、格納する場所が必要です。HttpSessionオブジェクトを使用すると、サーブレットのセッション・データを格納し、ユーザーに関連付けることができます。
HttpSessionオブジェクトを使用する場合の基本的な手順は、次のとおりです。
セッション・オブジェクトを取得します。
セッション・オブジェクトに対して読取りまたは書込みを行います。
セッションを強制的に終了するか、または自動的に期限切れさせて終了します。
セッションは、サーブレットに設定されている値に応じて、特定の期間または永続的に持続します。同じクライアントからサーバーへの複数のリクエストの追跡に、一意のセッションIDが使用されます。永続性は、複数のサーブレットが含まれている可能性があるWebアプリケーションのコンテキスト内で有効です。サーブレットでは、別のサーブレットによって保存されているオブジェクトにアクセスできます。オブジェクトは、名前で識別され、セッションにバインドされているとみなされます。これらのオブジェクト(setおよびgetメソッドがこれらに対して実行される場合は属性と呼ばれる)は、リクエスト、セッションまたはアプリケーションの有効範囲内の他のサーブレットで使用できます。
サーブレットは、リクエスト間の状態を維持するために使用しますが、従来のCGIおよび多くのCGIに代わる方法で実装する場合、この操作は煩雑になります。1つのみのサーブレット・インスタンスが作成され、リクエストごとに、サーブレットのサービス・メソッドをコールする新しいスレッドが生成されます(サービス・メソッドによってdoGetまたはdoPostがコールされます)。このため、共有データは、サーブレットの通常のインスタンス変数(フィールド)に配置する必要のみがあります。したがって、サーブレットでは、ブラウザによるページの再ロード時に実行中の計算に適切にアクセスできます。また、リクエストの結果を新しい順にN個保持できるため、最近行ったリクエストのパラメータと同じパラメータが新しいリクエストで指定された場合、すぐに結果が戻されます。サーブレットにも、作成者は共有データへのマルチスレッド・アクセスを同期させる必要があるという通常のルールが適用されます。
また、サーブレットでは、ServletContextオブジェクト(getServletContextメソッドを介して使用可能)に永続的なデータを格納することもできます。ServletContextにはsetAttributeおよびgetAttributeメソッドが含まれています。これらのメソッドによって、指定したキーに関連付けられている任意のデータを格納できます。データをインスタンス変数に格納する場合とServletContextに格納する場合の相違点として、ServletContextがサーブレット・エンジンまたはWebアプリケーション内のすべてのサーブレットで共有される点があげられます。
サーブレット仕様に定義されているとおり、Webアプリケーションは、サーブレット、JavaServer Pages(JSP)、Javaユーティリティ・クラスとライブラリ、静的ドキュメント(HTMLページ、イメージ、クライアント・サイドのアプレット、Bean、クラスなど)、およびサーブレット対応のすべてのWebサーバーに移植性を保持した状態でデプロイされるようにセットアップされたその他のWebリソースの集合です。Webアプリケーションは、そのまま1つのアーカイブ・ファイルに格納できます。また、そのファイルを特定のディレクトリに配置することによってデプロイできます。
Webアプリケーション・アーカイブ・ファイルの拡張子は.warです。WARファイルは、(jarユーティリティを使用して作成された).jar ファイルを別の拡張子で保存したファイルです。JAR形式では、JARファイルを圧縮形式で保存し、そのコンテンツにデジタル署名できます。特定の操作用の.jarファイルを区別するために、.jarファイル拡張子のかわりに.warが選択されています。WARファイル・リストの例を次に示します。
index.html howto.jsp feedback.jsp images/banner.gif images/jumping.gif WEB-INF/web.xml WEB-INF/lib/jspbean.jar WEB-INF/classes/MyServlet.class WEB-INF/classes/com/mycorp/frontend/CorpServlet.class WEB-INF/classes/com/mycorp/frontend/SupportClass.class
インストール時に、WARファイルをサーバー上の任意のURI接頭辞パスにマッピングできます。その接頭辞で始まるすべてのリクエストが、このWARファイルで処理されます。たとえば、前述のWARファイルが接頭辞/demoの下にインストールされた場合、サーバーでは/demoで始まるすべてのリクエストの処理にこのWARファイルが使用されます。/demo/index.htmlに対するリクエストでは、WARファイルのindex.htmlファイルが使用されます。/demo/howto.jspまたは/demo/images/banner.gifに対するリクエストの場合も、WARファイルのコンテンツが使用されます。
WEB-INFディレクトリの概要WEB-INFディレクトリは、特殊なディレクトリです。このディレクトリ内のファイルは直接クライアントには提供されません。これらのファイルにはJavaクラスとWebアプリケーションの構成情報が含まれています。 このディレクトリは、JARファイルのMETA-INFディレクトリと同様に機能します。このディレクトリには、アーカイブ・コンテンツに関するメタ情報が含まれています。WEB-INF/classesディレクトリには、Webアプリケーションのサーブレットおよびサポートするクラスのクラス・ファイルが格納されます。WEB-INF/libには、JARファイルに格納されたクラスが含まれています。Webサーバー・クラス・ローダーによって、自動的にWEB-INF/classesおよびWEB-INF/libでクラスが検索されます。追加のインストール手順は不要です。
Webアプリケーションのサンプル・リストのWEB-INFの下にあるサーブレットは、/demo/servlet/MyServlet、/demo/servlet/com.mycorp.frontend.CorpServletなどのURIを使用して起動できます。
このアプリケーションへのすべてのリクエストは、サーブレットへのリクエストの場合でも、/demoで始まることに注意してください。
WEB-INFディレクトリ内のweb.xmlファイルによって、Webアプリケーションの記述子が定義されます。web.xmlファイルには、このファイルが存在しているWebアプリケーションの構成情報が含まれています。web.xmlファイルは、サーブレットの登録、サーブレット初期化パラメータの定義、JSPタグ・ライブラリの登録、セキュリティ制約の定義、他のWebアプリケーション・パラメータの定義に使用されます。
J2EE仕様のサーブレットAPIは、進化し続けています。2年の間にサーブレットAPI 2.0、2.1および2.2が公開されており、このドキュメントを記述している時点での最新バージョンはサーブレットAPI 2.3です。サーブレットの基本アーキテクチャに大きな変更はないため、ほとんどのAPIはそのまま機能します。ただし、強化点および新機能がいくつかあり、一部のAPIは非推奨となりました。
この項では、サーブレットAPI 2.0、2.1、2.2および2.3ドラフト仕様での主な相違点について説明します。
サーブレットAPI 2.1の特徴は、次のとおりです。
リソース(サーブレット)ごとのリクエスト・ディスパッチャ・ラッパー
リクエスト・ディスパッチャは、HTTPリクエストの処理が可能なリソース(サーブレット、JSPなど)およびそのリソースに関連するファイル(静的なHTMLやGIFなど)のラッパーです。サーブレットまたはJSPがインスタンス化されるたびに、サーブレット・エンジンによってリクエスト・ディスパッチャが1つ生成されます。このリクエスト・ディスパッチャがクライアント・リクエストを受信して、リソースにディスパッチします。
アプリケーションごとのサーブレット・コンテキスト
サーブレットAPI 2.0では、サーブレット・エンジンによって、すべてのサーブレットで共有されるサーブレット・コンテキストが1つ生成されました。サーブレットAPI 2.1では、アプリケーションごとに1つのサーブレット・コンテキストが生成されるため、アプリケーションのパーティション化が簡単に行われます。アプリケーション・プログラミング・モデルの説明のとおり、同じ仮想ホスト上のアプリケーションは、互いのサーブレット・コンテキストにアクセスできます。
非推奨のHTTPセッション・コンテキスト
サーブレットAPI 2.0では、HttpSessionContextインタフェースによって、特定のWebサーバーのすべてのセッションが1つのセッション・コンテキストにグループ化されていました。セッション・コンテキストのインタフェース・メソッドを使用して、サーブレットでセッション・コンテキストのセッションIDリストを取得し、特定のIDに関連付けられたセッションを取得することが可能でした。サーブレットAPI 2.1では、セキュリティ上の安全のため、このインタフェースは非推奨となりました。このインタフェース・メソッドは、NULLを戻すように再定義されています。
サーブレットAPI 2.2仕様では、「サーブレット・エンジン」という用語が「サーブレット・コンテナ」に変更されました。この変更は、JavaサーブレットAPIがJava 2 Platform Enterprise Edition(J2EE)仕様での必須APIになり、J2EEの用語全体で「コンテナ」が「エンジン」より優先使用されるようになったことを示しています。サーブレットAPI 2.2では、次の新機能が導入されました。
Webアプリケーション(前述のとおり)。
外部データソース(JNDIなど)への参照。JNDI参照表にリソース(データベース接続など)を追加できます。単純な名前参照を使用して、サーブレットでリソースを指定できます。
アプリケーションのパラメータ情報(アプリケーションの初期化パラメータ)。
サーブレット名の登録。サーブレットを登録し、サーブレットに名前を付ける場所が提供されています。以前は、サーブレットを登録するプロセスがサーバーごとに異なっていたため、デプロイが困難でした。
サーブレット初期化パラメータ。初期化時に、サーブレット・パラメータにパラメータを渡すことができます。これは、以前はサーバー依存のプロセスであった処理を実現するための新しい標準的な方法です。
サーブレットのロード順序。事前ロードするサーブレットおよびそのロード順序を指定します。
セキュリティ制約。保護する必要があるページおよびその保護メカニズムを指定します。フォーム・ベース認証が組み込まれています。
サーブレットAPI 2.3では、サーブレットのコア部分にほとんど変更はありません。追加および変更された内容は、次のとおりです。
JDK 1.2以上が必要です。
フィルタ・メカニズムが作成されています。
アプリケーション・ライフ・サイクル・イベントが追加されています。
国際化サポートがさらに追加されています。
JAR間の依存関係を表現する技術が正式に定義されています。
クラスのロード規則が明確化されています。
エラー属性およびセキュリティ属性が追加されています。
HttpUtilsクラスは非推奨になっています。
DTDの動作の多くが拡張され、明確化されています。
サーブレット2.3 APIの一部として、フィルタリング機能がサポートされています。WebSphere Advanced Edition 3.5.3では、同様のフィルタリング機能がWebSphere固有のパッケージで実現されています。OC4Jでは、Javaサーブレット2.3のフィルタリング仕様がサポートされています。
フィルタリングは、Webサーバーでサーブレットをロードおよび起動する方法の1つです。ローカル・サーブレットとリモート・サーブレットのいずれも、サーブレット・チェーン(後述)の一部にすることができます。ただし、ローカルの内部サーブレットをチェーン化する場合は制約があり、その制約は使用するJ2EEコンテナに固有のものになります。たとえば、WebSphereでは、内部サーブレットをチェーンで使用する場合、内部サーブレットをチェーンの最初のサーブレットにする必要があります。内部サーブレットには、fileサーブレット、pageCompileサーブレット、ssIncludeサーブレットおよびtemplateサーブレットがあります。
一部のリクエストでは、1つのサーブレットのみではなく、順序付けられたサーブレットのチェーンを起動できます。ブラウザからの入力がチェーンの最初のサーブレットに送信され、チェーンの最後のサーブレットからの出力が、ブラウザに返信されるレスポンスになります。チェーン内の各サーブレットによって、直前のサーブレットからの入力が受信され、直後のサーブレットに出力が送信されます。次のものを使用して、受信リクエストに対してサーブレット・チェーンをトリガーすることができます。
リクエストに対するサーブレット・チェーンを示すサーブレットの別名
チェーン内の次のサーブレットをトリガーするMIMEタイプ
WebSphereバージョン3.5.2および3.5.3では、既存のアプリケーションとの互換性を保ちながら、同時にJavaサーブレットAPI 2.2仕様もサポートしています。ただし、このサポートは部分的なものであり、選択できるのはこのうちの1つです。互換性を確保するために、Administrative Consoleのサーブレット・コンテナのプロパティに新しいオプションが追加されました。この新しいオプション「Select Servlet Engine Mode」は、「Servlet Engine Properties」ビューにあります。「Select Servlet Engine Mode」オプションは、次の2種類の実行時モードを切り替えます。
このモードでは、既存のWebSphere Application Server v3.5およびv3.5.1アプリケーションに対する動作が維持されますが、JavaサーブレットAPI 2.2仕様に完全には準拠していません。互換モードでは、後述するメソッドおよび動作の変更を除いて、サーブレット・エンジンはサーブレット2.2の仕様レベルに準拠します。この機能は、既存のWebSphere Advanced Edition v3.5およびv3.5.1アプリケーションが、サーブレット2.2の仕様レベルに完全準拠するアプリケーションに移行されるまでの間、正常に実行されるために用意されています。
このモードでは、JavaサーブレットAPI 2.2仕様に準拠しますが、既存のWebSphere Application Server v3.5およびv3.5.1アプリケーションとの互換性は失われます。
デフォルトのモードは、準拠モードです。モードを選択するには、Administrative Consoleの「Servlet Engine General」タブを使用します。
WebSphere Advanced Edition 3.5.3では、サーブレット2.2 APIを部分的にサポートしています。サポートされているAPIの機能は次のとおりです。
レスポンス・バッファリング
複数エラー・ページのサポート
ウェルカム・ファイル・リスト
新しいリクエスト・マッピングのロジック
Webアプリケーションごとのセッション・タイムアウト
WebアプリケーションごとのMIMEマッピング表
名前によるリクエスト・ディスパッチャ
相対パスによるリクエスト・ディスパッチャ
重複ヘッダーのサポート(addHeader()、getHeaders(name)の各API)
Webアプリケーションの初期化パラメータ
国際化に関する機能強化(getLocale()、getLocales())
新しいAPIであるgetServletName()
サーブレット2.2 APIの機能のうち、次に示すものはサポートされません。
WebSphere Application Serverには、JavaサーブレットAPIを拡張および追加する独自のパッケージがあります。これらの拡張と追加は、セッションの状態の管理、パーソナライズしたWebページの作成、サーブレットのエラー・レポート生成機能の強化およびデータベース・アクセスを目的としています。
Application ServerのAPIパッケージとクラスは次のとおりです。
com.ibm.servlet.personalization.sessiontracking
サイト訪問者がWebサイトにアクセスする際の参照元ページを記録し、そのサイト内での訪問者の現在位置を追跡し、ユーザーIDとセッションを結び付けます。セッション・クラスタリングのサポートもAPIに追加されています。
com.ibm.websphere.servlet.session.IBMSessionインタフェース
セッション・サポートに関するHttpSessionの機能を拡張し、セッション・クラスタ環境におけるWeb管理者の制御範囲を広げます。
com.ibm.servlet.personalization.userprofileパッケージ
Web訪問者に関する詳細な情報を保持し、アプリケーションに取り込むためのインタフェースを提供します。これによって、パーソナライズされたユーザー・エクスペリエンスが実現されます。この情報は、データベースに保存されます。
com.ibm.websphere.userprofileパッケージ
ユーザー・プロファイルに関する機能を拡張します。
com.ibm.websphere.servlet.error.ServletErrorReportクラス
アプリケーションでエラーが発生したときに、カスタマイズされた詳細なメッセージをクライアントに返すことができます。
com.ibm.websphere.servlet.eventパッケージ
アプリケーション・ライフ・サイクル・イベント、サーブレット・ライフ・サイクル・イベントおよびサーブレットのエラーを通知するためのリスナー・インタフェースを提供します。このパッケージには、リスナーを登録するためのインタフェースも含まれています。
com.ibm.websphere.servlet.filterパッケージ
サーブレット・チェーンをサポートするクラスがあります。このパッケージには、ChainerServlet、ServletChainオブジェクトおよびChainResponseオブジェクトが含まれています。
com.ibm.websphere.servlet.requestパッケージ
抽象クラスHttpServletRequestProxyが含まれています。これは、サーブレット・エンジンのHttpServletRequestオブジェクトをオーバーロードするためのものです。オーバーロードされたリクエスト・オブジェクトは、別のサーブレットに転送されて処理されます。このパッケージに含まれているServletInputStreamAdapterクラスは、InputStreamをServletInputStreamに変換し、InputStreamへのすべてのメソッド・コールをかわりに処理します。
com.ibm.websphere.servlet.responseパッケージ
抽象クラスHttpServletResponseProxyが含まれています。これは、サーブレット・エンジンのHttpServletResponseオブジェクトをオーバーロードするためのものです。オーバーロードされたレスポンス・オブジェクトは、別のサーブレットに転送されて処理されます。このパッケージに含まれているServletOutputStreamAdapterクラスは、OutputStreamをServletOutputStreamに変換し、OutputStreamへのすべてのメソッド・コールをかわりに処理します。
このパッケージにはStoredResponseオブジェクトも含まれています。これは、天気予報などの一定期間変化しないと考えられるデータが格納されているサーブレット・レスポンスをキャッシュするときに便利です。
Oracle Application Server OC4Jは、Javaサーブレット2.2および2.3仕様に完全準拠して実装されています。したがって、Javaサーブレット2.2の標準コードが正常に動作します。一方、WebSphere 3.5.3は、前述のとおり、Javaサーブレット2.2仕様を部分的にサポートしています。特に、セキュリティのサポートはサーブレット2.1の仕様レベルのままであり、Webアプリケーションに対応するweb.xmlファイルで通常定義されているはずのJ2EE参照をサポートしていません。また、J2EE Webアプリケーションを直接サポートしていません。
APIサポートとWebSphereの拡張機能において、このようなサポートの相違点が存在するので、アプリケーションで、拡張機能や非推奨となっているメソッド・コールを使用している場合は、コード・レベルを変更しなければ移行できないことがあります。WebSphereはJ2EEのデプロイメント・ディスクリプタをサポートしていないので、既存のアプリケーションをOracle Application ServerのOC4Jにデプロイするには、J2EE Webアプリケーション構造にパッケージする必要があります。
オラクル社は、WebSphere Advanced Edition 3.5.3付属のサンプル・サーブレットを移行しました。サンプルの中には、WebSphere固有の拡張機能を使用していることが原因で移行できなかったサーブレットがあります。たとえば、AbstractLoginServletは、WebSphere固有のシングル・サインオン・パッケージを使用しているので移行できませんでした。
移行に成功したサーブレットは次のとおりです(これらはWebSphereInstallHome/Servletsにあります)。
Custom Login Servlet
HelloWorldServlet
SessionServlet
この他にも、WebSphere固有のデプロイメント・ディスクリプタを使用する、パッケージ化されたWebアプリケーションも移行しました。
これらのサンプルは、コードを変更することなく移行されています。次のディレクトリに配置するだけで済みます。
<ORACLE_HOME>/j2ee/home/default-web-app/WEB-INF/classes(UNIXの場合)
または
<ORACLE_HOME>\j2ee\home\default-web-app\WEB-INF\classes(NTの場合)
OC4Jのサーブレット・コンテナは、これらのサーブレットを自動的にロードします。これらのサーブレットをブラウザから起動する際にはURLを、http://<hostname>:7777/j2ee/servlet/HelloWorldServletのように指定します。
WebSphereには、スタンドアロン・サーブレット(初期化パラメータおよび構成情報を必要とするサーブレット)をデプロイするための別の方法があります。このサーブレットは、サーブレット名の後に.servletを付けたデプロイメント・ディスクリプタを使用して、WebSphereにデプロイされます。このWebSphere固有のデプロイメント・ディスクリプタをJ2EE Webアプリケーションのデプロイメント・ディスクリプタに移行しなければ、OC4Jにはデプロイできません。
例3-1 SnoopServlet.servletのデプロイメント・ディスクリプタ
<servlet>
<name>snoop</name>
<description>snoop servlet</description>
<code>SnoopServlet</code>
<servlet-path>/servlet/snoop/*</servlet-path>
<servlet-path>/servlet/snoop2/*</servlet-path>
<init-parameter>
<name>param1</name>
<value>test-value1</value>
</init-parameter>
<autostart>false</autostart>
</servlet>
.servletファイル: SnoopServlet.servletSnoopServletを移行するには、その.classファイルを<ORACLE_HOME>/j2ee/home/default-web-app/WEB-INF/classes(UNIXの場合)または<ORACLE_HOME>\j2ee\home\default-web-app\WEB-INF\classes(NTの場合)に置きます。
その後、次のディレクトリにあるweb.xmlを編集します。
UNIXの場合: <ORACLE_HOME>/j2ee/home/default-web-app/WEB-INF
NTの場合: <ORACLE_HOME>\j2ee\home\default-web-app\WEB-INF
移行後のSnoopServletのデプロイメント・ディスクリプタは次のようになります。
<web-app>
<servlet>
<servlet-name>snoop</servlet-name>
<description>snoop servlet</description>
<servlet-class>SnoopServlet</servlet-class>
<servlet-path>/servlet/snoop/*</servlet-path>
<servlet-path>/servlet/snoop2/*?/servlet-path?
<init-param>
<param-name>param1</param-name>
<param-value>test-value1</param-value>
</init-param>
<autostart>false</autostart>
</servlet>
</web-app>
クラスタリングとロード・バランシングは、エンタープライズ・アプリケーション・サーバーの主要機能です。これらの機能によって、アプリケーション・サーバーは、可用性が高く、フォルト・トレラントでスケーラブルなものになります。ロード・バランサは、個々のノードの状態をインスタンスのクラスタにレプリケートすることによって、あるノードに障害が発生してもその状態情報が別のノードで保持されるようにします。OC4Jでのクラスタ構成によって、次のことが実現されます。
リソース使用の最大化
アプリケーションがマシンのリソースを最大限に利用できないときも、OC4Jはプロセッサの能力をより効率的に使用するようにします。
スループットの最大化
OC4Jでは、1つのアプリケーションが同時に処理できるリクエストの数が大幅に増加しています。
シングル・ポイント障害によるリスクの最小化
OC4Jでは、構成が冗長化されます。あるインスタンスに障害が発生しても、他のインスタンスが引き続きリクエストを処理します。
WebSphereおよびOracle Application Server OC4Jのどちらでも、クラスタリングとセッション・フェイルオーバーのロード・バランシングが可能です。OC4Jでは、クラスタリングを使用しないRMIリクエストおよびレスポンスのHTTPトンネリングもサポートしています。WebSphere上で実行されているクラスタ対応アプリケーションは、OC4Jインスタンス(複数のOC4Jプロセスからなり、クラスタに相当)への移行が可能です。
OC4J構成には、アイランドの概念が採用されています。アイランドとは、同一のアプリケーション構成を持ち、アプリケーションの状態がレプリケートされるOC4Jプロセスの集合です。アイランドは、OC4Jインスタンス内のプロセスからなるサブセットです。
|
注意: この項では、アイランドを手動で構成する手順について説明します。この手順は、OC4Jがスタンドアロン・モードで実行されている開発環境で行うことができます。OracleASクラスタでアイランドを構成する場合は、 Oracle Enterprise Manager 10g Application Server ControlコンソールのWebページまたはdcmctlコマンドライン・ユーティリティを使用してください。これらの使用方法については、『Oracle Application Server管理者ガイド』および『Oracle Application Server Containers for J2EEユーザーズ・ガイド』を参照してください。 |
OC4Jアイランドを構成する手順は次のとおりです。
Webアプリケーションを、クラスタ内のすべてのノード上にインストールします。
まず、クラスタ内で使用している各ノード上に同じWebアプリケーションがインストールされていることを確認します。アプリケーションを2箇所にインストールしないようにする場合は、両サーバーからアクセス可能な共有ドライブ上に配置します。
すべてのノードを起動して、各ノード上でWebアプリケーションが正しく動作していることを確認します。
Webアプリケーションの状態がクラスタにレプリケートされるようにセットアップします。
Webアプリケーションのorion-web.xmlデプロイメント・ディスクリプタを編集します。このファイルは次のディレクトリにあります。
UNIXの場合: <ORACLE_HOME>/j2ee/home/application-deployments/application-name/web-app-name/
NTの場合: <ORACLE_HOME>\j2ee\home\application-deployments\application-name\web-app-name\
サイト内のすべてのWebアプリケーションをクラスタリングするには、次のディレクトリにあるグローバルWebアプリケーションのorion-web.xmlを編集します。
UNIXの場合: <ORACLE_HOME>/j2ee/home/config/global-web-application.xml
NTの場合: <ORACLE_HOME>\j2ee\home\config\global-web-application.xml
<orion-web-app>タグの本体部分に、次の文字列を追加します。
<cluster-config/>
オプション: クラスタ・データを送受信するポートを指定します。
クラスタ内でノードを識別するためのID(番号)を指定します。デフォルトはlocalhostです。
オプション: クラスタ内のすべてのノードについて、手順4から6を繰り返します。
これで、HTTPSessionデータはレプリケートされるようになりました(シリアライズ可能、またはEJB参照であるかぎり)。ただし、EJBが存在するサーバーが停止しているときは、その参照は無効になります。ServletContextデータもレプリケートされます。
アイランドを構成します。
アイランドの接続先は、Webアプリケーションではなく特定のサイトです。アイランドを構成する手順は次のとおりです。
ロード・バランサに関する指示をサーバーに与えます。同じファイル、つまりWebサイトのweb-site.xmlの中で、そのサイトのロード・バランサが存在する場所を指定します。
<website>タグの本体部分に、次の文字列を追加します。
<frontend host="balancer_hostname" port="balancer_port" />
balancer_hostnameとbalancer_portは、ロード・バランサを実行するサーバーのホスト名とポートです。
アプリケーションの/WEB-INF/web.xmlまたはNTでの対応するファイルに、次のタグを追加します。
</distributable>
ブラウザからロード・バランサのホストとポートにアクセスします。リクエストがサーバーにどのように送信されるかを確認してください。同じクライアントから同一ページを再度リクエストすると、そのリクエストはおそらく同じサーバーに送信されますが、異なるクライアントから同一ページへのリクエストが行われているときは、そのクライアント・リクエストがロード・バランシングされることがわかります。
状態のレプリケートをテストするには、次のディレクトリにあるサーブレットにアクセスします。
UNIXの場合: <ORACLE_HOME>/j2ee/home/servlet/SessionServlet
NTの場合: <ORACLE_HOME>\j2ee\home\servlet\SessionServlet
リクエストを1回行って、どのサーバーがセッションのプライマリ・サーバーとなっているかを確認してください。そのサーバーを停止して、リクエストをもう一度行います。リクエストは前回と同じセッションの一部になりつつも、別のノードで処理されることが予期されます。また、カウンタが正常に更新されるはずです。
すべてのアイランドでは、ロード・バランサとして機能する1つのOC4Jインスタンスがあり、リクエストをアプリケーションのクローンにディスパッチします。
新しいリクエストがそのサイトに接続したことのないIPアドレスからのものであり、またセッションに関連付けられていない場合、そのリクエストはランダムにOC4Jインスタンスの1つに送信されます。クラスタ内に同じサイトを処理できるアイランドが複数ある場合は、アイランドの1つがランダムに選択されます。その後、選択されたアイランド内のノードの1つがランダムに選択されます。
状態のレプリケートは、すべてこの選択されたノードのアイランド内で行われます。リクエストのIPアドレスをそのWebサイトへの接続に以前使用したことがある場合は、リクエストが前回のリクエストと同じサーバーに送信されます(その構成で、IPアドレスに基づくリクエスト・ルーティングを行わないよう指定されている場合を除く)。
デフォルトでは、ロード・バランシングはリクエストではなくクライアントに基づいて行われます。つまり、統計的には、デフォルトのロード・バランシングによってアイランド内の各ノードに振り分けられるクライアントの数は等しくなります。アイランド内の各ノードへのクライアント数が均等であっても、サーバーへのリクエスト数が均等になるわけではありません。クライアントが発信するリクエスト数は、それぞれ異なるからです。
リクエストに基づいてロード・バランシングを行うには、OC4Jアイランドの強力な機能であるdontuseIPスイッチを使用します。
リクエストがキープ・アライブ・ソケットで行われたとき、そのリクエストは前のリクエストと同じサーバーに送信されます。ただし、コマンドライン・オプション-dontUseKeepalivesまたはload-balancer.xmlのuse-keepalives="false"で、キープ・アライブを使用しないよう指定している場合を除きます。
リクエストがセッション内のユーザーから発信された場合は、リクエストがそのセッションのプライマリ・サーバーに送信されます。セッションのプライマリ・サーバーが応答しない場合は、同じアイランド内の別のサーバーにリクエストが送信されます。状態はすでにレプリケートされているので、他のサーバーでもユーザーの状態は同じです。