![]() |
![]() |
|
|
Basic CORBA サーバ・アプリケーションの設計とインプリメント
この章では、Basic University サンプル・アプリケーションを例として使用して、CORBA サーバ・アプリケーションを設計およびインプリメントする方法について説明します。この章の内容は、インプリメントするアプリケーションの設計が完了し、OMG IDL に定義されていることを前提にしています。この章では、サーバ・アプリケーション向けの設計およびインプリメンテーションの選択肢に焦点を当てます。
ここでは、以下の内容について説明します。
Basic University サンプル・アプリケーションのしくみ
Basic University サンプル・アプリケーションを使用すると、学生は中央の University データベースからコース情報を参照できます。 この Basic サンプル・アプリケーションでは、学生は次のことを行うことができます。
Basic University サンプル・アプリケーションの OMG IDL
Basic University サンプル・アプリケーションの OMG IDL ファイルには、次のインターフェイスが定義されます。
図 3-1 に、Basic University サンプル・アプリケーションを示します。
図3-1 Basic University サンプル・アプリケーション
Basic University サンプル・アプリケーションで何が発生するかを説明するために、次のイベント・グループについて説明します。
Registrar
オブジェクトのオブジェクト・リファレンスを取得するときです。アプリケーションの起動
次に、Basic クライアント・アプリケーションおよびサーバ・アプリケーションが起動し、クライアント・アプリケーションが Registrar
オブジェクトのオブジェクト・リファレンスを取得するときに行われる一般的な一連のイベントを示します。
RegistrarFactory
オブジェクトのオブジェクト・リファレンスを取得しま
す。
RegistrarFactory
オブジェクトのリファレンスを使用して、クライアン
ト・アプリケーションは RegistrarFactory
オブジェクトの
find_registrar()
オペレーションを呼び出します。
RegistrarFactory
はメモリ内に存在しません (このオブジェクトに対する
要求が以前にサーバ・プロセスに到着していないため)。このため、TP フ
レームワークは Server オブジェクトの Server::create_servant()
オペ
レーションを呼び出して RegistrarFactory オブジェクトをインスタンス化し
ます。
RegistrarFactory
オブジェクトの
find_registrar()
オペレーションが呼び出されます。RegistrarFactory
オブジェクトは、Registrar
のオブジェクト・リファレンスを作成してクラ
イアント・アプリケーションに返します。
コース概要の参照
次に、学生がコース概要のリストを参照するときに発生する一連のイベントを順番に示します。
Registrar
オブジェクトのオブジェクト・リファレンスを使用して、クライ
アント・アプリケーションは get_courses_synopsis()
オペレーションを呼
び出し、次のものを指定します。
number_to_get
で表され、返される概要リストのサイズを指定する整数Registrar
はメモリ内に存在しません (このオブジェクトに対する要求が以
前にサーバ・プロセスに到着していないため)。このため、TP フレームワー
クは Server オブジェクトにインプリメントされている
Server::create_servant()
オペレーションを呼び出します。これにより、
Registrar
オブジェクトがサーバ・マシンのメモリ内にインスタンス化され
ます。
Registrar
オブジェクトはクライアント要求を受信し、
CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレンスを
作成します。CourseSynopsisEnumerator
オブジェクトは、データベースか
らコース概要をフェッチするために Registrar
オブジェクトによって呼び出
されます。
CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレンスを作成するために、Registrar
オブジェクトは次のことを行います。
CourseSynopsisEnumerator
オブジェクトの一意な ID を生成します。
CourseSynopsisEnumerator
オブジェクトのオブジェクト ID を生成しま
す。この ID は、前のステップで生成された一意の ID とクライアントに
よって指定された検索文字列を連結したものです。
CourseSynopsisEnumerator
オブジェクトのインターフェイス・リポジ
トリ ID をそのインターフェイス・タイプ・コードから取得します。
TP::create_object_reference()
オペレーションを呼び出します。こ
のオペレーションにより、最初のクライアント要求で必要な
CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレン
スが作成されます。
Registrar
オブジェクトは CourseSynopsisEnumerator
オブジェクトの
get_next_n()
オペレーションを呼び出して、リスト・サイズを受け渡しま
す。ステップ 1 で説明したとおり、このリスト・サイズはパラメータ
number_to_get
によって表されます。
Server::create_servant()
オペレーションを呼び出して、CourseSynopsisEnumerator
オブジェクトを
インスタンス化します。
CourseSynopsisEnumerator
オブジェクトの
activate_object()
オペレーションを呼び出します。このオペレーション
は、次の 2 つのことを行います。
CourseSynopsisEnumerator
オブジェクトは、Registrar
オブジェクトに次
の情報を返します。
CourseSynopsisList
に指定されるコース概要リスト。これは、最初のコース概要リストを含む sequence
です。number_remaining
パラメータによって指定されます。Registrar
オブジェクトは、クライアント・アプリケーションに
CourseSynopsisEnumerator
オブジェクト・リファレンスを返します。ま
た、そのオブジェクトから取得した次の情報も返します。
number_remaining
変数number_remaining
変数が 0 の場合、Registrar
オブジェクトは CourseSynopsisEnumerator
オブジェクトの destroy()
オペレーションを呼び出し、クライアント・アプリケーションに nil リファレンスを返します。
CourseSynopsisEnumerator
オブジェクトに送信します。
CourseSynopsisEnumerator
オブジェクトはそのクライアント要求を満たす
と共に、更新した number_remaining
変数を返します。
CourseSynopsisEnumerator
オブジェ
クトとのやり取りを終了すると、CourseSynopsisEnumerator
オブジェクト
の destroy()
オペレーションを呼び出します。この結果、
CourseSynopsisEnumerator
オブジェクトは TP::deactivateEnable()
オ
ペレーションを呼び出します。
CourseSynopsisEnumerator
オブジェクトの
deactivate_object()
オペレーションを呼び出します。この結果、
CourseSynopsisEnumerator
オブジェクトが保持しているコース概要のリス
トがサーバ・マシンのメモリから削除されます。これにより、
CourseSynopsisEnumerator
オブジェクトのサーバントを別のクライアント
要求のために再利用できるようになります。
コース詳細の参照
次に、クライアント・アプリケーションがコース詳細を参照するときに行われる一連のイベントを示します。
Registrar
オブジェクトの
get_course_details()
オペレーションを呼び出し、コース番号のリストを
受け渡します。
Registrar
オブジェクトは、一致するコース番号をデータベースから検索
し、指定された各コースの詳細を含んだリストを返します。このリストは、
CourseDetailsList
変数に格納されます。これは、コースの詳細を含んだ
一連の struct
です。
University サーバ・アプリケーションの設計に関する考慮事項
Basic University サンプル・アプリケーションには、University サーバ・アプリケーションが含まれます。このサーバ・アプリケーションは、CORBA サーバ・アプリケーションの基本的な設計問題を処理します。この節では、以下のトピックについて説明します。
この節では、さらに次の 2 つのトピックについても説明します。
オブジェクト・リファレンスの生成に関する設計上の考慮事項
Basic クライアント・アプリケーションでは、University サーバ・アプリケーションによって管理される次のオブジェクトのリファレンスが必要です。
RegistrarFactory
オブジェクトRegistrar
オブジェクトCourseSynopsisEnumerator
オブジェクト次の表に、これらのリファレンスがどのように生成されて返されるかを示します。
University サーバ・アプリケーションがオブジェクト・リファレンスを生成する方法について、以下のことに注意してください。
RegistrarFactory
オブジェクトを FactoryFinder に登録します。この方法により、クライアント・アプリケーションはサーバ・アプリケーション内の基本オブジェクトのオブジェクト・リファレンスを取得するために必要なファクトリを検索できます。Registrar
オブジェクトのオブジェクト・リファレンスは、RegistrarFactory
オブジェクトによって作成されます。これは、クライアント・アプリケーションにオブジェクト・リファレンスを返すためのきわめて一般的かつ基本的な方法を示します。つまり、クライアント・アプリケーションがビジネス・ロジックを実行するために必要な基本オブジェクトのリファレンスを作成して返すための専用ファクトリが存在するということです。 CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレンスは、登録されたファクトリの外部で作成されます。University サンプル・アプリケーションの場合、これは優れた設計です。これは、CourseSynopsisEnumerator
オブジェクトの使い方のためです。つまり、その存在が特定のクライアント・アプリケーション・オペレーションに固有であるからです。CourseSynopsisEnumerator
オブジェクトは、特定のリストと、ほかの問い合わせの結果とは関連性のない結果を返します。Registrar
はそのオペレーションの 1 つで別のオブジェクトのオブジェクト・リファレンスを作成するので、Registrar
オブジェクトはファクトリです。ただし、Registrar
オブジェクトはファクトリとして FactoryFinder に登録されません。このため、クライアント・アプリケーションは Registrar
オブジェクトのリファレンスを FactoryFinder から取得することはできません。オブジェクト状態の管理に関する設計上の考慮事項
Basic サンプル・アプリケーションの 3 つのオブジェクトには、それぞれ独自の状態管理の要件が存在します。この節では、それぞれのオブジェクト状態管理の要件について説明します。
RegistrarFactory オブジェクト
RegistrarFactory
オブジェクトは、特定のクライアント要求に一意なものである必要はありません。また、このオブジェクトをメモリに保持しておき、クライアント呼び出しごとにこのオブジェクトを活性化および非活性化する負担を回避することは合理的です。したがって、RegistrarFactory
オブジェクトには process
活性化方針が割り当てられます。
Registrar オブジェクト
Basic サンプル・アプリケーションは、小規模な環境へのデプロイに適しています。Registrar
オブジェクトは、RegistrarFactory
オブジェクトに似た特性を備えています。つまり、このオブジェクトは特定のクライアント要求に一意なものである必要がありません。また、呼び出しごとにこのオブジェクトを活性化および非活性化する負担を回避することは合理的です。したがって、Basic サンプル・アプリケーションでは、Registrar
オブジェクトには process
活性化方針が割り当てられます。
CourseSynopsisEnumerator オブジェクト
University サーバ・アプリケーションの基本的な設計上の問題は、大きすぎて 1 回の応答ではクライアント・アプリケーションに返すことができないコース概要リストをどのように処理するかです。したがって、この問題の解決策は、次のことが中心となります。
University サーバ・アプリケーションは、この解決策をインプリメントする CourseSynopsisEnumerator
オブジェクトを備えています。このオブジェクトは最初に呼び出されたときに最初の概要リストを返しますが、その後もメモリ内コンテキストに保持されるので、クライアント・アプリケーションは後続の要求で概要の残りを取得できます。メモリ内コンテキストを保持するには、CourseSynopsisEnumerator オブジェクトは状態を持たなければなりません。つまり、このオブジェクトは複数のクライアント呼び出しにわたってメモリ内に常駐します。
クライアントが CourseSynopsisEnumerator
オブジェクトとの会話を終了するときに、このオブジェクトにはメモリからフラッシュされるための手段が必要です。このため、CourseSynopsisEnumerator
オブジェクトの適切な状態管理の方法は、process
活性化方針を割り当て、CORBA アプリケーション制御の非活性化機能をインプリメントすることです。
アプリケーション制御の非活性化は、そのオブジェクトの destroy()
オペレーションによってインプリメントされます。
次のコード例に、CourseSynopsisEnumerator
オブジェクトの destroy()
オペレーションを示します。
void CourseSynopsisEnumerator_i::destroy()
{
// クライアントが列挙子の「破棄」を呼び出すと、
// このオブジェクトは「消滅」する必要がある。
// そのためには、TP フレームワークに
// このオブジェクトとの会話が完了したことを通知する
TP::deactivateEnable();
}
Basic University サンプル・アプリケーションの ICF ファイル
次のコード例に、Basic サンプル・アプリケーション用の ICF ファイルを示します。
module POA_UniversityB
{
implementation CourseSynopsisEnumerator_i
{
activation_policy ( process );
transaction_policy ( optional );
implements ( UniversityB::CourseSynopsisEnumerator );
};
implementation Registrar_i
{
activation_policy ( process );
transaction_policy ( optional );
implements ( UniversityB::Registrar );
};
implementation RegistrarFactory_i
{
activation_policy ( process );
transaction_policy ( optional );
implements ( UniversityB::RegistrarFactory );
};
};
永続状態情報の処理に関する設計上の考慮事項
永続状態情報の処理とは、オブジェクトの活性化中または活性化後のある時点でディスクから永続状態情報を読み取り、必要な場合、非活性化中または非活性化後のある時点でそれを書き込むことです。Basic サンプル・アプリケーションでは、次の 2 つのオブジェクトが永続状態情報を処理します。
Registrar
オブジェクトCourseSynopsisEnumerator
オブジェクト以降の 2 つの節では、この 2 つのオブジェクトが永続状態情報を処理する方法に関する設計上の考慮事項を説明します。
Registrar オブジェクト
Registrar
オブジェクトのオペレーションの 1 つによって、クライアント・アプリケーションにコース情報の詳細が返されます。一般的なシナリオでは、数多くのコース概要を参照した学生は、通常 2 つか 3 つのコースに関する詳細情報を一度に参照しようとします。
このシナリオを効率的にインプリメントするために、Registrar
オブジェクトには get_course_details()
オペレーションが定義されています。このオペレーションは、コース番号のリストを指定するパラメータを入力として受け付けます。次にこのオペレーションは、データベースからコースの詳細を検索し、その詳細をクライアント・アプリケーションに返します。このオペレーションがインプリメントされるオブジェクトはプロセス・バウンドなので、このオペレーションはその呼び出しの完了後に状態データをメモリに保持するのを避ける必要があります。
Registrar
オブジェクトは、永続状態をメモリに保持しません。クライアント・アプリケーションが get_course_details()
オペレーションを呼び出すと、このオブジェクトは関連するコース情報を University データベースからフェッチしてクライアントに送信します。このオブジェクトは、コース・データをメモリ内に保持しません。このオブジェクトの activate_object()
オペレーションと deactivate_object()
オペレーションでは永続状態は処理されません。
CourseSynopsisEnumerator オブジェクト
CourseSynopsisEnumerator
オブジェクトは、自身が University データベースから検索するコース概要を処理します。状態処理に関する設計上の考慮事項は、ディスクから状態を読み取る方法です。このオブジェクトは、状態をディスクに書き込みません。
CourseSynopsisEnumerator
オブジェクトの機能には、次の 3 つの重要な側面があります。これらの側面は、このオブジェクトがその永続状態を読み取る方法に影響を与えます。
この 3 つの側面を考えたとき、このオブジェクトでは次のことを行うのが合理的です。
activate_object()
オペレーションを介してその永続状態情報を読み取ります。 deactivate_object()
オペレーションを介してメモリからコース概要をフラッシュします。したがって、CourseSynopsisEnumerator
オブジェクトが活性化されるときに、そのオブジェクトの activate_object()
オペレーションは次のことを行います。
注記 オブジェクトの Tobj_ServantBase::activate_object()
オペレーションまたは Tobj_ServantBase::deactivate_object()
オペレーションをインプリメントする場合は、インプリメンテーション・ヘッダ・ファイル (つまり、application
_i.h
ファイル) を編集し、これらのオペレーションの定義をそのオブジェクトのインターフェイスのクラス定義テンプレートに追加してください。
University データベースの使い方
University サンプル・アプリケーションが University データベースを使用する方法について、次のことに注意してください。
utils
ディレクトリ内の samplesdb.h
ファイルには、これらのクラスの定義が記述されています。これらのクラスは、University データベース内のコース・レコードと学生レコードを読み書きするために必要なすべての SQL 呼び出しを行います。注記 Wrapper および Production サンプル・アプリケーションの BEA Tuxedo Teller アプリケーションは、University データベース内の口座情報に直接アクセスし、samplesdb.h
ファイルを使用しません。
Basic サーバ・アプリケーションに組み込むファイルの詳細については、『BEA Tuxedo CORBA University サンプル・アプリケーション』を参照してください。
CourseSynopsisEnumerator
オブジェクトは、データベース・カーソルを使用して University データベースから一致するコース概要を検索します。データベース・カーソルは複数のトランザクションにまたがることができないので、CourseSynopsisEnumerator
オブジェクトの activate_object()
オペレーションは一致するすべてのコース概要をメモリに読み取ります。カーソルはイテレータ・クラスによって管理されるため、CourseSynopsisEnumerator
オブジェクトからは見えません。University サンプル・アプリケーションがトランザクションを使用する方法については、「トランザクションの CORBA サーバ・アプリケーションへの統合」を参照してください。 Basic サンプル・アプリケーションがデザイン・パターンを適用する方法
Basic サンプル・アプリケーションは、次のデザイン・パターンを使用します。
この節では、この 2 つのデザイン・パターンが Basic サンプル・アプリケーションに適している理由と、Basic サンプル・アプリケーションがこれらのパターンをインプリメントする方法について説明します。
Process-Entity デザイン・パターン
Process-Entity デザイン・パターンで説明したように、このデザイン・パターンは、クライアント・アプリケーションによって必要とされるデータ・エンティティを処理する 1 つのプロセス・オブジェクトが存在する場合に適しています。データ・エンティティは、クライアント・アプリケーションではなくこのプロセス・オブジェクトによって操作される CORBA struct
としてカプセル化されます。
Process-Entity デザイン・パターンを Basic サンプル・アプリケーションに適用すると、Basic サンプル・アプリケーションは細粒度オブジェクトのインプリメントを回避できます。たとえば、Registrar
オブジェクトは、同じような多数のコース・オブジェクト・セットの有効な代替となります。単一の粗粒度 Registrar
オブジェクトを管理する負荷は、何百、何千もの細粒度のコース・オブジェクトを管理する負荷に比べれば、それほど大きくはありません。
Process-Entity デザイン・パターンの詳細については、デザイン・パターンに関する技術情報を参照してください。
List-Enumerator デザイン・パターン
このデザイン・パターンは、大きすぎて 1 つの応答でクライアント・アプリケーションに返すことができないデータの内部リストをオブジェクトが生成した場合に適しています。このため、オブジェクトは 1 回の応答で最初のデータ・リストをクライアント・アプリケーションに返し、後続の応答で残りのデータを返すことができなければなりません。
また、List-Enumerator オブジェクトは、既に返されたデータの量を同時に追跡して、後続のリストを正確に返すことができるようにする必要があります。List-Enumerator オブジェクトは常に状態を持ち (クライアント呼び出しにまたがって活性化され、メモリに常駐する)、サーバ・アプリケーションはそれらが不要になったときにそれらを非活性化できます。
List-Enumerator デザイン・パターンは、CourseSynopsisEnumerator
オブジェクトに最適です。このデザイン・パターンをインプリメントすると、次のメリットが得られます。
CourseSynopsisEnumerator
オブジェクトは一意で、その内容はこのオブジェクトが作成される原因となった要求によって決まります。また、各 CourseSynopsisEnumerator
のオブジェクト ID も一意です。クライアントが Registrar
オブジェクトの get_courses_synopsis()
オペレーションを呼び出すと、Registrar
オブジェクトは次のものを返します。CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレンスこのため、後続のすべての呼び出しは適切な CourseSynopsisEnumerator
オブジェクトに対して行われます。これは、サーバ・プロセスに CourseSynopsisEnumerator
クラスのアクティブ・インスタンスが複数存在する場合に重要です。
get_courses_synopsis()
オペレーションは一意の CourseSynopsisEnumerator
オブジェクト・リファレンスを返すので、クライアント要求どうしが衝突することはありません。つまり、クライアント要求が間違った CourseSynopsisEnumerator
オブジェクトに誤って送られることはありません。
Registrar
オブジェクトは get_courses_synopsis()
オペレーションを備えていますが、データベース問い合わせと概要リストの知識はすべて CourseSynopsisEnumerator
オブジェクトに埋め込まれます。この場合、Registrar
オブジェクトは単にクライアントが次のデータを取得するための手段として機能します。
CourseSynopsisEnumerator
オブジェクトのリファレンスBEA Tuxedo システムに組み込まれた性能効率化
BEA Tuxedo システムは、同じサーバ・プロセス内の 2 つのオブジェクト間のデータ・マーシャリングを自動的に無効化することによって、性能の効率化を実現します。この効率化は、次の環境が存在するときに得られます。
この例には、Registrar
オブジェクトが CourseSynopsisEnumerator
オブジェクトのオブジェクト・リファレンスを作成し、それによってそのオブジェクトがインスタンス化された場合などがあります。この 2 つのオブジェクト間の要求と応答では、データ・マーシャリングは行われません。
状態を持つオブジェクトの事前活性化
状態を持つオブジェクトの事前活性化機能を使用すると、クライアント・アプリケーションがオブジェクトを呼び出す前にそのオブジェクトを活性化できます。この機能は、University サンプルの CourseSynopsisEnumerator
オブジェクトなどのイテレータ・オブジェクトを作成するときに特に役立ちます。
状態を持つオブジェクトの事前活性化では、TP::create_active_object_reference()
オペレーションを使用します。通常、クライアントがあるオブジェクトに対する呼び出しを発行するまで、CORBA サーバ・アプリケーションでそのオブジェクトは作成されません。ただし、オブジェクトを事前活性化し、TP::create_active_object_reference()
オペレーションを使用してそのオブジェクトのリファレンスをクライアントに受け渡すことによって、クライアント・アプリケーションは既に活性化され、状態を持っているオブジェクトを呼び出すことができます。
注記 状態を持つオブジェクトの事前活性化の機能は、WebLogic Enterprise バージョン 4.2 で最初に導入されました。
状態を持つオブジェクトを事前活性化する方法
事前活性化の機能を使用するためのプロセスは、サーバ・アプリケーションに次のコードを記述することです。
new
文の呼び出しを含めます。
TP::create_active_object_reference()
オペレーションを呼び出して、
新しく作成されたオブジェクトのリファレンスを取得します。このオブジェ
クト・リファレンスは、クライアント・アプリケーションに返すことができ
ます。
このように、事前活性化オブジェクトは、TP フレームワークがそのオブジェクトの Server::create_servant()
オペレーションと Tobj_ServantBase::activate_object()
オペレーションを呼び出さずに作成されます。
事前活性化オブジェクトの使い方に関する注意
事前活性化機能を使用するときには、以下のことに注意してください。
process
活性化方針が割り当てられている必要があります。このため、これらのオブジェクトは、プロセスの終了時か、それらのオブジェクトの TP::deactivateEnable()
オペレーションの呼び出しによってのみ非活性化できます。TP::create_active_object_reference()
オペレーションによって作成されるオブジェクト・リファレンスは一時的なものです。これは、事前活性化オブジェクトは自身が作成されたプロセスの存続期間にわたって存在し、別のサーバ・プロセスで再び活性化してはならないからです。ある一時オブジェクト・リファレンスが作成されたプロセスのシャットダウン後にクライアント・アプリケーションがそのオブジェクト・リファレンスを呼び出した場合、TP フレームワークは次の例外を返します。
CORBA::OBJECT_NOT_EXIST
サーバがクラッシュし、そのときに削除されたオブジェクトをクライアント・アプリケーションが呼び出そうとする状況を回避するには、事前活性化されるオブジェクトに対する Tobj_ServantBase::activate_object()
オペレーションのインプリメンテーションに TobjS::ActivateObjectFailed
例外を追加します。クライアントがサーバ・クラッシュ後にこのようなオブジェクトを呼び出そうとし、TP フレームワークがそのオブジェクトの Tobj_ServantBase::activate_object()
オペレーションを呼び出した場合、TP フレームワークはクライアント・アプリケーションに次の例外を返します。
CORBA::OBJECT_NOT_EXIST
![]() |
![]() |
![]() |
|
Copyright © 2001, BEA Systems, Inc. All rights reserved.
|