|
この章では、CORBA サーバ アプリケーションを作成するための手順について説明します。この章で説明する手順は、決定的なものではありません。サーバ アプリケーションによっては、ほかの手順を行う必要があります。また、これらの手順のいくつかについては順番を変更することができます。ただし、これらの手順は、すべての CORBA サーバ アプリケーションの開発プロセスに共通のものです。
この章では、最初に手順の要約と、このマニュアルで使用する開発ツールおよび開発コマンドのリストを示します。デプロイメント環境によっては、ほかのソフトウェア開発ツールも使用します。このため、この章で説明するツールとコマンドも決定的なものではありません。
この章では、Oracle Tuxedo ソフトウェアに付属の Basic University サンプル アプリケーションの中の例を使用します。Basic University サンプル アプリケーションの詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。このマニュアルで使用するツールとコマンドの詳細については、『Tuxedo CORBA プログラミング リファレンス』を参照してください。
マルチスレッド CORBA サーバ アプリケーションの作成については、「マルチスレッド CORBA サーバ アプリケーションの作成」を参照してください。
サーバ アプリケーションを作成するための基本的な手順は次のとおりです。
ステップ 1: サーバ アプリケーション用の OMG IDL ファイルのコンパイル
ステップ 2: 各インタフェースのオペレーションを実装するメソッドの記述
ステップ 3: サーバ オブジェクトの作成
ステップ 4: メモリ内でのオブジェクトの振る舞いの定義
ステップ 5: サーバ アプリケーションのコンパイルとリンク
ステップ 6: サーバ アプリケーションのデプロイ
Oracle Tuxedo ソフトウェアには、次の開発ツールと開発コマンドが用意されています。
Oracle Tuxedo ドメインで実行されるアプリケーションのクライアントおよびサーバ部分の基本構造は、そのアプリケーションの OMG IDL ファイルに記述される文によって決定されます。アプリケーションの OMG IDL ファイルをコンパイルする場合、IDL コンパイラは、idl
コマンドで指定するオプションに応じて、次の図に示すファイルの一部または全部を生成します。影付きのコンポーネントは、サーバ アプリケーションを作成するために修正するファイルです。
表 2-1 に、IDL コンパイラによって生成されるファイルを示します。
表 2-1 に示したファイルを生成するには、次のコマンドを入力します。
idl [options] idl-filename [icf-filename]
options
は、IDL コンパイラへの 1 つまたは複数のコマンドライン オプションを表す。コマンドライン オプションについては、『Tuxedo CORBA プログラミング リファレンス』を参照。実装ファイルを生成する場合は、-i
オプションを指定する必要がある。idl-filename
は、アプリケーションの OMG IDL ファイルの名前を表す。 icf-filename
は、アプリケーションの実装コンフィグレーション ファイル (ICF ファイル) の名前を表すオプションのパラメータ。ICF ファイルは、オブジェクトのアクティブ化ポリシーを指定するか、または生成するスケルトンおよび実装ファイルのインタフェースの数を制限するために使用する。ICF ファイルの使い方については、「ステップ 4: メモリ内でのオブジェクトの振る舞いの定義」を参照。注意 : | WebLogic Enterprise 5.1 では、プラグマの C++ IDL コンパイラ実装が変更され、CORBA 2.3 機能がサポートされるようになりました。これにより、IDL ファイルが影響を受ける場合があります。CORBA 2.3 機能は、プラグマ接頭辞定義が影響を及す可能性があるスコープを変更します。プラグマはインクルードされる IDL ファイルに含まれる定義には影響を及さず、またインクルードされる IDL ファイル内で行われるプラグマ接頭辞定義はそれらのファイルの外部のオブジェクトに影響を及しません。 |
C++ IDL コンパイラは、プラグマ接頭辞の処理を訂正するよう変更されました。この変更はオブジェクトのリポジトリ ID に影響を与えるため、_narrow
などのオペレーションでエラーが発生する場合があります。
IDL コンパイラと idl
コマンドの詳細については、『Tuxedo CORBA プログラミング リファレンス』を参照してください。
次のコマンドラインは、OMG IDL ファイル univb.idl
のクライアント スタブ ファイル、スケルトン ファイル、初期実装ファイル、スケルトン ヘッダ ファイル、および実装ヘッダ ファイルを生成します。
idl -i univb.idl
idl
コマンドの詳細については、『Tuxedo CORBA プログラミング リファレンス』を参照してください。Oracle Tuxedo University サンプル アプリケーション用のこれらのファイルを生成する方法については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。
注意 : | 非デフォルトのオブジェクトのアクティブ化ポリシーまたはトランザクション ポリシーを指定する場合、または生成するスケルトン ファイルと実装ファイルのインタフェースの数を制限する場合、実装コンフィグレーション ファイル (ICF) を生成し、この ICF ファイルを IDL コンパイラに受け渡す必要があります。詳細については、「ICF でオブジェクトのアクティブ化ポリシーとトランザクション ポリシーを指定する方法」を参照してください。 |
IDL コンパイラには、インタフェースの tie クラス テンプレートを生成するために使用できる -T
コマンドライン オプションも用意されています。CORBA アプリケーションの tie クラスの実装については、「デレゲーション ベースのインタフェース実装」を参照してください。
サーバ アプリケーション プログラマは、アプリケーションの OMG IDL ファイルで定義した各インタフェースのオペレーションを実装するメソッドを記述します。
Tobj_ServantBase::activate_object()
オペレーションと Tobj_ServantBase::deactivate_object()
オペレーション
Tobj_ServantBase::activate_object()
オペレーションと Tobj_ServantBase::deactivate_object()
オペレーションの中で、オブジェクトのアクティブ化または非アクティブ化に関連する特定の手順を実行するコードを記述します。これには、オブジェクトの永続状態のディスクからの読み取りとディスクへの書き込みがそれぞれ含まれます。これらのオペレーションをオブジェクトに実装する場合、実装ヘッダ ファイルを編集して、これらのオペレーションを使用する各実装にそれらの定義を追加する必要があります。
サーバ アプリケーションの実装ファイルはすべて手動で作成できますが、実装ファイルを記述する出発点として、IDL コンパイラが生成する実装ファイルを使用することもできます。IDL コンパイラによって生成される実装ファイルには、アプリケーションのインタフェース用に定義された各オペレーションを実装するメソッドのシグニチャが含まれます。
通常、この実装ファイルは、IDL コンパイラを呼び出すコマンドで -i
オプションを指定することによって 1 度だけ作成します。アプリケーションのインタフェースを繰り返し修正し、これらのインタフェースのオペレーション (オペレーション シグニチャを含む) を変更した場合は、必要なすべての変更を実装ファイルに追加してこれらの変更を反映させる必要があります。
「クライアント アプリケーションがサーバ アプリケーションの CORBA オブジェクトをアクセスおよび操作する方法」で説明したように、クライアント アプリケーションがサーバ アプリケーションによって管理されるオブジェクトを簡単に検索できるようにするためには、ファクトリを作成する必要があります。ファクトリは実装するほかの CORBA オブジェクトに似ていますが、FactoryFinder オブジェクトに登録する必要があります。ファクトリの登録については、「ファクトリを作成および登録するコードの記述」を参照してください。
ファクトリの主要な機能は、オブジェクト参照を作成することです。ファクトリは、TP::create_object_reference()
オペレーションを呼び出すことによってこれを実行します。TP::create_object_reference()
オペレーションでは、次の入力パラメータが必要となります。
たとえば、Basic University サンプル アプリケーションでは、RegistrarFactory
インタフェースは、次のように 1 つのオペレーションだけを指定します。
University::Registrar_ptr RegistrarFactory_i::find_registrar()
RegistrarFactory
オブジェクトの find_registrar() オペレーションには、Registrar
オブジェクトの参照を作成するための TP::create_object_reference()
オペレーションへの次の呼び出しが含まれています。
CORBA::Object_var v_reg_oref =
TP::create_object_reference(
University::_tc_Registrar->id(),
object_id,
CORBA::NVlist::_nil()
);
Registrar
オブジェクトのインタフェース リポジトリ ID をタイプ コードから抽出することによってその ID を指定する。University::_tc_Registrar->id()
Registrar
オブジェクト用に作成されるオブジェクト参照は、それを作成する RegistrarFactory
オブジェクトと同じグループにルーティングされる。CORBA::NVlist::_nil()
オブジェクト参照のルーティング先のグループに影響を与えるルーティング基準の指定については、「Oracle Tuxedo の CORBA サーバ アプリケーションのスケーリング」を参照してください。
Server オブジェクトの実装は、ほかの言語オブジェクトの実装とは異なります。Server オブジェクトのヘッダ クラスは既に作成されており、Server オブジェクト クラスは既にインスタンス化されています。Server オブジェクトを作成するには、パッケージ済みの Server オブジェクト クラスの特定のメソッド セットを実装します。この節では、実装するこれらのメソッドについて説明します。
Server オブジェクトを作成するには、一般のテキスト エディタで新しいファイルを作成し、次のオペレーションを実装します。
どのサーバ アプリケーションにも、Server オブジェクトのインスタンスは 1 つしか存在しません。サーバ アプリケーションが複数の CORBA オブジェクト実装を管理する場合、記述する Server::initialize()
、Server::create_servant()
、および Server::release()
オペレーションにはこれらの実装すべてに適用するコードを組み込む必要があります。
これらのタスクの大部分のコードには、TP フレームワークとの対話が含まれます。以降の節では、これらの Server オブジェクト オペレーションのそれぞれに対して必要なコードについて説明し、Basic University サンプル アプリケーションのサンプル コードを示します。
Server オブジェクトに実装する最初のオペレーションは、サーバ アプリケーションを初期化するオペレーションです。このオペレーションは、Oracle Tuxedo システムがサーバ アプリケーションを起動するときに呼び出されます。TP フレームワークは、サーバ アプリケーションの起動シーケンス中に Server オブジェクトの次のオペレーションを呼び出します。
CORBA::Boolean Server::initialize(int argc, char** argv)
Oracle Tuxedo ドメインの UBBCONFIG
ファイルの SERVERS
セクションに指定する特定のサーバ アプリケーション用の CLOPT
パラメータは、Server::initialize()
オペレーションに argc
および argv
として受け渡されます。サーバ アプリケーションへの引数の受け渡しについては、『Oracle Tuxedo アプリケーション実行時の管理』を参照してください。サーバ アプリケーションに引数を受け渡す例については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。
Server::initialize()
オペレーションの中には、該当する場合、次のことを行うコードを組み込みます。
クライアント アプリケーションがオブジェクトを簡単に検索できるようにするためのファクトリをサーバ アプリケーションが管理する場合、そのファクトリを FactoryFinder オブジェクトに登録するコードを記述する必要があります。このコードは、通常サーバ アプリケーション初期化プロセスの最後のステップとして呼び出されます。
サーバ アプリケーションによって管理されるファクトリを登録するコードを記述するには、次のことを行います。
このステップでは、「ファクトリの実装」で説明したとおりオブジェクト参照を作成します。
このステップでは、TP::create_object_reference()
オペレーションの呼び出しを組み込み、OMG IDL インタフェースのインタフェース リポジトリ ID を指定します。次の例では、RegistrarFactory
ファクトリのオブジェクト参照 (s_v_fact_ref
変数で表される) が作成されます。
University::RegistrarFactory s_v_fact_ref =
TP::create_object_reference(
University::_tc_RegistrarFactory->id(),
object_id,
CORBA::NVList::_nil()
);
このステップでは、サーバ アプリケーションによって管理される各ファクトリに対して次のオペレーションを呼び出します。
TP::register_factory (CORBA::Object_ptr factory_or,
const char* factory_id);
TP::register_factory()
オペレーションは、サーバ アプリケーションのファクトリを FactoryFinder オブジェクトに登録します。このオペレーションでは、次の入力パラメータが必要です。
次の例では、RegistrarFactory
ファクトリが Oracle Tuxedo ドメインに登録されます。
TP::register_factory(s_v_fact_ref.in(),
University::_tc_RegistrarFactory->id());
University::_tc_RegistrarFactory->id() パラメータに注目してください。これは、TP::create_object_reference()
オペレーションで指定したパラメータと同じです。このパラメータは、オブジェクトの OMG IDL インタフェースのインタフェース リポジトリ ID をそのタイプ コードから抽出します。
サーバ アプリケーション初期化プロセスが完了したら、サーバ アプリケーションはクライアント要求を処理できる状態になります。CORBA オブジェクトのオペレーションに対する要求が到着し、それを処理するサーバントがメモリ内に存在しない場合、TP フレームワークは Server オブジェクトの次のオペレーションを呼び出します。
Tobj_Servant Server::create_servant(const char* interfaceName)
Server::create_servant()
オペレーションには、クライアント要求によって必要とされるオブジェクトのサーバントをインスタンス化するコードが含まれます。たとえば、C++ では、このコードにはオブジェクトのインタフェース クラスの new
文が組み込まれます。
Server::create_servant()
オペレーションでは、サーバントは OID に関連付けられません。サーバントと OID の関連付けは、TP フレームワークがそのサーバントの Tobj_ServantBase::activate_object()
オペレーション (オブジェクトのインスタンス化を完了させるオペレーション) を呼び出したときに行われます。オブジェクトのコンストラクタで OID をオブジェクトに関連付けることはできません。同様に、サーバントと OID の関連付けの解除は、TP フレームワークがそのサーバントの deactivate_object()
オペレーションを呼び出したときに行われます。
Oracle Tuxedo システムでのこうしたサーバントの振る舞いにより、TP フレームワークは、オブジェクトの非アクティブ化後、別のオブジェクトのインスタンス化のためにサーバントを使用できます。したがって、オブジェクトの Tobj_ServantBase::deactivate_object()
オペレーションの呼び出しによってそのオブジェクトのデストラクタも呼び出されるとは考えないでください。サーバ アプリケーションでサーバント プール機能を使用する場合、オブジェクトの Tobj_ServantBase::deactivate_object()
オペレーションに TP::application_responsibility()
オペレーションを実装して、サーバントへのポインタを後で使用できるようにサーバント プールに受け渡すことができます。サーバント プールについては、「サーバント プール」を参照してください。
Server::create_servant()
オペレーションでは、入力引数が 1 つ必要です。この引数は、サーバントを作成するためのオブジェクトの OMG IDL インタフェースのインタフェース ポジトリ ID を含む文字列を指定します。
このオペレーション用に記述するコードには、サーバ アプリケーションによって管理されるオブジェクトの OMG IDL インタフェースのインタフェース リポジトリ ID を指定します。実行時に、Server::create_servant()
オペレーションは、要求によって指定されたオブジェクトに対して必要なサーバントを返します。
次のコードは、Basic University サンプル アプリケーションの University サーバ アプリケーションの Server::create_servant()
オペレーションを実装します。
Tobj_Servant Server::create_servant(const char* intf_repos_id)
{
if (!strcmp(intf_repos_id, University::_tc_RegistrarFactory->id())) {
return new RegistrarFactory_i();
}
if (!strcmp(intf_repos_id, University::_tc_Registrar->id())) {
return new Registrar_i();
}
if (!strcmp(intf_repos_id, University::_tc_CourseSynopsisEnumerator->id())) {
return new CourseSynopsisEnumerator_i();
}
return 0; // 未知のインタフェース
}
Oracle Tuxedo システム管理者が tmshutdown
コマンドを入力すると、TP フレームワークは、Oracle Tuxedo ドメインで実行される各サーバ アプリケーションの Server オブジェクトの次のオペレーションを呼び出します。
void Server::release()
Server::release()
オペレーションでは、次のような、サーバ アプリケーションに応じたアプリケーション固有のクリーンアップ タスクを実行できます。
サーバ アプリケーションが停止要求を受信すると、そのサーバ アプリケーションはほかのリモート オブジェクトから要求を受信することができなくなります。これは、管理者がサーバ アプリケーションを停止する順番に影響を与えます。たとえば、あるサーバ プロセスへの Server::release()
オペレーションの呼び出しが別のサーバ プロセスに含まれている場合、最初のサーバ プロセスは停止してはなりません。
サーバの停止中に、次の呼び出しを組み込んでサーバ アプリケーションの各ファクトリの登録を削除できます。
TP::unregister_factory (CORBA::Object_ptr factory_or,
const char* factory_id)
TP::unregister_factory()
オペレーションの呼び出しは、Server::release()
実装の最初のアクションの 1 つである必要があります。TP::unregister_factory()
オペレーションは、サーバ アプリケーションのファクトリへの登録を削除します。このオペレーションでは、次の入力引数が必要です。
次の例では、Basic サンプル アプリケーションで使用されている RegistrarFactory
ファクトリへの登録が削除されます。
TP::unregister_factory(s_v_fact_ref.in(), UnivB::_tc_RegistrarFactory->id());
このサンプル コードでは、グローバル変数 s_v_fact_ref の使い方に注目してください。
この変数は、RegistrarFactory
オブジェクトを登録した Server::initialize()
オペレーションで設定されたもので、ここで再び使用されます。
また、UnivB::_tc_RegistrarFactory->id() パラメータにも注目してください。これも、ファクトリの登録に使用されたインタフェース名と同じです。
「オブジェクト状態の管理」で説明したように、オブジェクトのアクティブ化ポリシーとトランザクション ポリシーを割り当て、オプションでアプリケーション制御の非アクティブ化機能を使用することによって、オブジェクトを非アクティブ化するイベントを指定します。
オブジェクトのアクティブ化ポリシーとトランザクション ポリシーは ICF ファイルに指定し、アプリケーション制御の非アクティブ化は TP::deactivateEnable()
オペレーションを介して使用します。この節では、Basic University サンプル アプリケーションを例として使用して、これらのメカニズムを実装する方法について説明します。
Oracle Tuxedo ソフトウェアは、「オブジェクトのアクティブ化ポリシー」で説明した次のアクティブ化ポリシーをサポートしています。
Oracle Tuxedo ソフトウェアは、第 6 章「トランザクションの CORBA サーバ アプリケーションへの統合」で説明する次のトランザクション ポリシーもサポートしています。
これらのポリシーをアプリケーションのオブジェクトに割り当てるには、次の手順に従います。
genicf
コマンドを入力し、アプリケーションの OMG IDL ファイルを入力として指定して、ICF ファイルを生成します。# genicf university.idl
このコマンドによって、university.icf
というファイルが生成されます。
method
で、デフォルトのトランザクションアクティブ化ポリシーは optional
であることに注意してください。module POA_UniversityB
{
implementation CourseSynopsisEnumerator_i
{
activation_policy ( method );
transaction_policy ( optional );
implements ( UniversityB::CourseSynopsisEnumerator );
};
};
module POA_UniversityB
{
implementation Registrar_i
{
activation_policy ( method );
transaction_policy ( optional );
implements ( UniversityB::Registrar );
};
};
module POA_UniversityB
{
implementation RegistrarFactory_i
{
activation_policy ( method );
transaction_policy ( optional );
implements ( UniversityB::RegistrarFactory );
};
};
RegistrarFactory
インタフェースのスケルトン ファイルと実装ファイルが生成されないようにするには、次の行を削除します。implementation RegistrarFactory_i
{
activation_policy ( method );
transaction_policy ( optional );
implements ( UniversityB::RegistrarFactory );
};
Server オブジェクトとオブジェクト実装のコードの記述が済んだら、サーバ アプリケーションをコンパイルおよびリンクします。
CORBA サーバ アプリケーションをコンパイルおよびリンクするには、buildobjserver
コマンドを使用します。buildobjserver
コマンドの形式は次のとおりです。
buildobjserver [-o servername] [options]
buildobjserver
コマンドの構文要素を次に説明します。
University サンプル アプリケーションのコンパイルとリンクの詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。buildobjserver
コマンドの詳細については、『Tuxedo コマンド リファレンス』を参照してください。
マルチスレッド CORBA サーバ アプリケーションの設計とビルドには、特別な考慮事項が存在します。詳細については、「buildobjserver コマンドの使い方」を参照してください。
注意 : | IBM AIX 4.3.3 システム上で Oracle Tuxedo ソフトウェアを実行する場合、-brtl コンパイラ オプションを使用して CORBA アプリケーションを再コンパイルする必要があります。 |
システム管理者は、この節で説明する手順を使用して CORBA サーバ アプリケーションをデプロイします。University サンプル アプリケーションのビルドとデプロイの詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。
サーバ アプリケーションをデプロイするには、以下の手順に従います。
UBBCONFIG
ファイル) を作成します。TUXDIR
環境変数を設定します。この環境変数は、Oracle Tuxedo ソフトウェアがインストールされている場所を指し示します。TUXCONFIG
ファイルを作成します。 tmloadcf -yapplication-
ubbconfig
-file
コマンドライン引数の application-
ubbconfig
-file
は、アプリケーションの UBBCONFIG
ファイルの名前を表します。古い TUXCONFIG
ファイルを削除してからこのコマンドを実行しなければならない場合があることに注意してください。
tmboot -y
University サンプル アプリケーションの詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。CORBA アプリケーション用の UBBCONFIG
ファイルの作成の詳細については、『Oracle Tuxedo アプリケーションの設定』を参照してください。
クライアント アプリケーションが CORBA オブジェクトのオペレーションを呼び出した場合、その呼び出しの結果として例外が返される場合があります。クライアント アプリケーションに返される有効な例外は次のとおりです。
Oracle Tuxedo システムは、これらの CORBA 定義の制限に違反することがないよう動作します。詳細については、「例外のサーバ アプリケーション ビュー」で説明します。
クライアント アプリケーションが認識する例外セットは制限されているので、クライアント アプリケーションは原因が不明な例外を捕捉する場合があります。Oracle Tuxedo システムは、こうした例外を可能な限りユーザ ログの説明メッセージで補足します。このメッセージは、エラー状態の検出とデバッグに役立ちます。これらのケースについては、次の節で説明します。
Oracle Tuxedo システムは、TP オブジェクトのオペレーションが呼び出された場合、次の例外をアプリケーションに返す場合があります。
TobjS_c.h
ファイルに定義される CORBA UserExceptions
。このファイルに定義される例外の OMG IDL は次のとおり。interface TobjS {
exception AlreadyRegistered { };
exception ActivateObjectFailed { string reason; };
exception ApplicationProblem { };
exception CannotProceed { };
exception CreateServantFailed { string reason; };
exception DeactivateObjectFailed { string reason; };
exception IllegalInterface { };
exception IllegalOperation { };
exception InitializeFailed { string reason; };
exception InvalidDomain { };
exception InvalidInterface { };
exception InvalidName { };
exception InvalidObject { };
exception InvalidObjectId { };
exception InvalidServant { };
exception NilObject { string reason; };
exception NoSuchElement { };
exception NotFound { };
exception OrbProblem { };
exception OutOfMemory { };
exception OverFlow { };
exception RegistrarNotAvailable { };
exception ReleaseFailed { string reason; };
exception TpfProblem { };
exception UnknownInterface { };
}
サーバ アプリケーションは、クライアント呼び出し中に次の場所で例外を生成する場合があります。
サーバ アプリケーションは次のタイプの例外を生成する可能性があります。
TobjS_c.h
ファイルに定義される CORBA ユーザ定義例外。次の例外は、Oracle Tuxedo システムがユーザ ログにメッセージを送るためにサーバ アプリケーションで使用されます。このメッセージは、トラブルシューティングに役立ちます。interface TobjS {
exception ActivateObjectFailed { string reason; };
exception CreateServantFailed { string reason; };
exception DeactivateObjectFailed { string reason; };
exception InitializeFailed { string reason; };
exception ReleaseFailed { string reason; };
}
サーバ アプリケーション コードによって生成され、サーバ アプリケーションによって捕捉されないすべての例外は、Oracle Tuxedo システムによって捕捉されます。これらの例外が捕捉されると、次のいずれかの処理が発生します。
以下の節では、CORBA オブジェクトに対するクライアント呼び出し中にサーバ アプリケーションによって生成される例外を Oracle Tuxedo システムがどのように処理するかについて説明します。
Server::create_servant()
オペレーションで生成された例外
例外が Server::create_servant()
オペレーションで生成された場合、次の処理が行われます。
CORBA::OBJECT_NOT_EXIST
例外がクライアント アプリケーションに返される。TobjS::CreateServantFailed
の場合、メッセージがユーザ ログに送られる。例外のコンストラクタに reason 文字列が指定されている場合、その reason 文字列もメッセージの一部として書き込まれる。Tobj_ServantBase::activate_object()
オペレーションと Tobj_ServantBase::deactivate_object()
オペレーションは呼び出されない。クライアントによって要求されたオペレーションは呼び出されない。
Tobj_ServantBase::activate_object()
オペレーションで生成された例外
例外が Tobj_ServantBase::activate_object()
オペレーションで生成された場合、次の処理が行われます。
Oracle Tuxedo システムでは、オペレーション実装は、CORBA システム例外、またはクライアント アプリケーションによって認識され、OMG IDL に定義されるユーザ定義例外のいずれかを送出する必要があります。これらのタイプの例外がオペレーション実装によって送出された場合、Oracle Tuxedo システムは次のいずれかの状態が存在しない限り、それらをクライアント アプリケーションに返します。
always
トランザクション ポリシーが設定されており、Oracle Tuxedo システムがオブジェクトの呼び出し時に自動的にトランザクションを開始した場合。この場合、トランザクションは Oracle Tuxedo システムによって自動的にロールバックされます。クライアント アプリケーションはこのトランザクションを認識しないので、Oracle Tuxedo システムは、クライアントがトランザクションを開始した場合に生成される CORBA:: TRANSACTION_ROLLEDBACK
例外ではなく CORBA::OBJ_ADAPTER
CORBA システム例外を生成します。TobjS_c.h
ファイルに定義されている場合。この場合、例外は CORBA::BAD_OPERATION
例外に変換され、クライアント アプリケーションに返されます。また、次のメッセージがユーザ ログに送られます。"WARN: アプリケーションが TobjS 例外を捕捉しませんでした。TP フレームワークが CORBA::BAD_OPERATION を送出しています。"
例外が TobjS::IllegalOperation
の場合、次の補足メッセージが書き込まれ、アプリケーションにコーディング エラーが存在する可能性があることを開発者に警告します。
"WARN: アプリケーションが TP::deactivateEnable() を不正に呼び出し、TobjS 例外を捕捉しませんでした。"
これは、TP::deactivateEnable()
オペレーションが、transaction
アクティブ化ポリシーが割り当てられているオブジェクトの内部で呼び出された場合に発生する可能性があります。アプリケーション制御の非アクティブ化はトランザクション バウンド オブジェクトではサポートされません。
CORBA::INTERNAL
例外がクライアントに返されます。一般にこれは、オブジェクトがアクティブ化されているプロセスに関する重大なシステム問題を示します。
CORBA 仕様で定義されているとおり、クライアントに送り返される応答には、オペレーション実装からの結果値か、オペレーション実装で送出された例外のいずれかが含まれ、両方が含まれることはありません。最初のケース、つまり、応答ステータス値が NO_EXCEPTION
の場合、応答にはオペレーションの戻り値と任意の inout
または out
引数値が含まれます。それ以外のケース、つまり、応答ステータス値が USER_EXCEPTION
または SYSTEM_EXCEPTION
の場合、応答には例外のエンコーディングが含まれます。
Tobj_ServantBase::deactivate_object()
オペレーションで生成された例外
例外が Tobj_ServantBase::deactivate_object()
オペレーションで生成された場合、次の処理が発生します。
オブジェクト インスタンスの受け渡し時に生成された CORBA マーシャリング例外
ORB は、オブジェクト インスタンスをオブジェクト参照としてマーシャリングできません。たとえば、次のコードでファクトリ参照を受け渡すと、Oracle Tuxedo システムで CORBA マーシャリング例外が発生します。
connection::setFactory(this);
オブジェクト インスタンスを受け渡すには、次の例のように、プロキシ オブジェクト参照を作成して、そのプロキシを代わりに受け渡します。
CORBA::Object myRef = TP::get_object_reference();
ResultSetFactory factoryRef = ResultSetFactoryHelper::_narrow(myRef);
connection::setFactoryRef(factoryRef);
Oracle Tuxedo システムには、メッセージ文字列を指定できる定義済みの例外セットが用意されています。TP フレームワークは、アプリケーション コードが次のコールバック メソッドでエラーを取得した場合、これらのメッセージ文字列をユーザ ログに書き込みます。
これらの例外は、例外の発生原因に関する明確な情報を送信するための便利なデバッグ支援機能として使用できます。TP フレームワークは、これらのメッセージをユーザ ログにのみ書き込みます。これらのメッセージは、クライアント アプリケーションには返されません。
これらのメッセージは、次の例外で指定します。これらの例外では、オプションで reason 文字列を指定できます。
メッセージ文字列をユーザ ログに送るには、次の例のように、その文字列を例外に指定します。
throw CreateServantFailed("Unknown interface");
これらの例外を送出する場合、reason 文字列パラメータが指定されている必要があります。これらの例外の 1 つで reason 文字列を指定しない場合は、次の例のように、二重引用符を入力する必要があります。
throw ActivateObjectFailed("");
Server オブジェクトの Server::create_servant()
オペレーションの実装は、そのインタフェース ID に基づいてオブジェクトをインスタンス化します。このインタフェース ID は、ファクトリが TP::create_object_reference()
オペレーションを呼び出したときにファクトリに指定されるインタフェース ID と同じである必要があります。インタフェース ID が一致しない場合、通常 Server::create_servant()
オペレーションで例外が発生するか、または NULL サーバントが返されます。この場合、Oracle Tuxedo システムは、CORBA::OBJECT_NOT_EXIST
例外をクライアント アプリケーションに返します。Oracle Tuxedo システムは、TP::create_object_reference()
オペレーションでインタフェース ID の検証を行いません。
このような状態は、開発の過程で、インタフェースの異なるバージョンが開発されるか、IDL ファイルに対して多くの変更が行われる場合に発生する可能性があります。OMG IDL にインタフェース ID の文字列定数を指定し、これらの定数をファクトリと Server::create_servant()
オペレーションで使用する場合でも、オブジェクト実装とファクトリが異なる実行可能ファイルに存在する場合は、不一致が発生する可能性があります。多くの場合、この問題の診断は困難です。
こうした問題を避けるには、開発中に次の予防的プログラミング手法を検討する必要があります。このコードは、アプリケーションのデバッグ バージョンにのみ記述する必要があります。実働バージョンでは受け入れられない性能の低下が発生する可能性があるからです。
TP::create_object_reference()
オペレーションを呼び出す直前に、インタフェース リポジトリをチェックして必要なインタフェースが存在するかどうかを調べるコードを組み込む。すべてのアプリケーション OMG IDL が最新のものになっており、インタフェース リポジトリにロードされていることを確認します。このチェックでインタフェース ID が見つからない場合、不一致が存在すると見なすことができます。TP::create_object_reference()
オペレーションの呼び出しの後に、オブジェクトを ping するコード、つまり、オブジェクトの任意のオペレーション (通常何も行わないオペレーション) を呼び出すコードを組み込む。この呼び出しが CORBA::OBJECT_NOT_EXIST
例外を生成する場合、インタフェース ID の不一致が存在する。オブジェクトを ping すると、そのオブジェクトがアクティブ化され、そのアクティブ化に関連するオーバーヘッドが発生することに注意してください。
Tobj_ServantBase::deactivate_object()
オペレーションは、オブジェクトのアクティブ化境界に達したときに呼び出されます。このオペレーションの実装では、オプションで永続状態をディスクに書き込むことができます。このオペレーションで生成された例外はクライアント アプリケーションに返されないことを理解しておくことが重要です。クライアント アプリケーションは、オブジェクトがトランザクションに参加していない限り、このオペレーションで生成されたエラー状態を認識しません。このため、このオペレーションで状態が正常に書き込まれたかどうかを知ることが重要である場合は、トランザクションを使用することをお勧めします。
Tobj_ServantBase::deactivate_object()
オペレーションで状態を書き込むことを選択し、クライアント アプリケーションがその書き込みオペレーションの結果を知る必要がある場合、次のことを行うことをお勧めします。
method
アクティブ化ポリシーか transaction
アクティブ化ポリシーのいずれかを使用します。また、TP::deactivateEnable()
オペレーションがトランザクション境界の内部で呼び出される場合は、process
アクティブ化ポリシーを使用することもできます。COSTransactions::Current::rollback_only()
オペレーションを呼び出してトランザクションがロールバックされるようにする。これにより、クライアント アプリケーションは次の例外を確実に受け取ることができます。
トランザクションを使用しない場合は、Tobj_ServantBase::deactivate_object()
オペレーションを使用せずに、オブジェクトの個々のオペレーションのスコープの中でオブジェクト状態を書き込むことをお勧めします。エラーが発生した場合、オペレーションはクライアント アプリケーションに返される例外を生成できます。
「サーバント プールと状態をステートレス オブジェクト」で説明したように、サーバント プールを使用すると、メソッド バウンド オブジェクトとトランザクション バウンド オブジェクトのオブジェクト インスタンス化のコストを削減できます。
通常、オブジェクトの非アクティブ化中 (TP フレームワークが Tobj_ServantBase::deactivate_object()
オペレーションを呼び出したとき) に、TP フレームワークはオブジェクトのサーバントを削除します。ただし、サーバント プールを使用する場合、TP フレームワークはオブジェクトの非アクティブ化時にサーバントを削除しません。代わりに、サーバ アプリケーションはプール内のサーバントへのポインタを保持します。それ以降、そのプール内のサーバントによって処理可能な要求がクライアントから送られてくると、サーバ アプリケーションはそのサーバントを再利用して新しいオブジェクト ID を割り当てます。サーバントがプールから再利用される場合、TP フレームワークは新しいサーバントを作成しません。
Server::initialize()
オペレーションに、サーバント プールをセットアップするコードを記述します。サーバント プールは 1 つまたは複数のサーバントへのポインタのセットで構成され、サーバント プールのコードでは特定のクラスのサーバントをプールでどのくらい保持するのかを指定します。Tobj_ServantBase::deactive_object()
オペレーションに、TP::application_responsibility()
オペレーションを実装します。TP::application_responsibility()
オペレーションの実装には、TP フレームワークが Tobj_ServantBase::deactivate_object()
オペレーションを呼び出したときにサーバント プールにサーバントへのポインタを格納するコードを記述します。Server::create_servant()
オペレーションの実装に、クライアント要求が到着したときに次のことを行うコードを記述します。注意 : | このリリースでは、TP::application_responsibility() オペレーションのサポートが変更されています。詳細については、『Tuxedo CORBA プログラミング リファレンス』を参照してください。 |
Oracle Tuxedo CORBA アプリケーションでオブジェクトを実装する主要な方法は、継承とデレゲーションの 2 つです。オブジェクトが POA スケルトン クラスから継承され、それによって CORBA オブジェクトとなった場合、そのオブジェクトは継承によって実装されたと言われます。
ただし、POA スケルトン クラスからの継承が困難または不可能な C++ オブジェクトを CORBA アプリケーションで使用したい場合もあります。たとえば、POA スケルトン クラスから継承するために大幅な書き換えが必要な C++ オブジェクトなどです。こうした非 CORBA オブジェクトを CORBA アプリケーションで使用するには、そのオブジェクト用の tie クラスを作成します。tie クラスは、POA スケルトン クラスから継承されます。また、tie クラスには 1 つまたは複数のオペレーションが含まれ、それらは実装のためにレガシー クラスに委譲されます。これにより、レガシー クラスはデレゲーションによって CORBA アプリケーションに実装されます。
デレゲーション ベースのインタフェース実装を作成するには、IDL コンパイラの -T
コマンドライン オプションを使用して、OMG IDL ファイルに定義されている各インタフェースに対する tie クラス テンプレートを生成します。
CORBA アプリケーションで tie クラスを使用する場合、Server オブジェクトに Server::create_servant()
オペレーションを実装する方法も変わります。以降の節では、Oracle Tuxedo 製品で tie クラスを使用する方法についてさらに詳しく説明し、Server::create_servant()
オペレーションを実装してこれらのクラスをインスタンス化する方法についても説明します。
Oracle Tuxedo CORBA では、tie クラスはサーバントであり、したがって基本的にレガシー クラスのラッパー オブジェクトとして機能します。
次の図に、レガシー オブジェクトのラッパーとして機能する、Account
インタフェースの継承の特性を示します。レガシー オブジェクトには、オペレーション op1
の実装が含まれています。tie クラスは、op1
をレガシー クラスに委譲します。
tie クラスは、クライアント アプリケーションからは見えません。クライアント アプリケーションには、tie クラスは自身が呼び出すオブジェクトの完全な実装のように見えます。tie クラスは、ユーザが提供するレガシー クラスにすべてのオペレーションを委譲します。さらに、tie クラスには次のものが含まれます。
tie クラスは Oracle Tuxedo CORBA に固有のものではなく、CORBA アプリケーションでデレゲーションを実装するための唯一の方法でもありません。ただし、Oracle Tuxedo CORBA の tie クラス用の便利な機能を使用すると、それらの tie クラスの基本的なコンストラクタ、デストラクタ、およびハウスキーピング オペレーションに必要なコーディングの量を大幅に減らすことができます。
tie クラスは、次のいずれかの状況で使用することをお勧めします。
Oracle Tuxedo ドメインのアプリケーションに tie クラスを作成するには、次の手順に従います。
-T
オプションを使用して、OMG IDL ファイルをコンパイルします。
IDL コンパイラは、C++ テンプレート クラスを生成します。このクラスはスケルトンの名前を取り、その後ろに _tie
という文字列が付加されます。IDL コンパイラは、このテンプレート クラスをスケルトン ヘッダ ファイルに追加します。
IDL コンパイラは、tie クラスの実装ファイルを生成しないことに注意してください。このファイルは、次のステップで説明するように手動で作成する必要があります。
Server::create_servant()
オペレーションに、レガシー オブジェクトをインスタンス化するコードを記述します。
次の例では、tie クラス POA_Account_tie
のサーバントが作成され、レガシー クラス LegacyAccount
がインスタンス化されます。
Account * Account_ptr = new LegacyAccount();
AccountFactoryServant = new POA_Account_tie<LegacyAccount> (Account_ptr)
注意 : | UNIX 用の Compaq C++ Tru64 コンパイラで tie クラスをコンパイルする場合、buildobjserver コマンドで使用される CFLAGS または CPPFLAGS 環境変数の定義に -noimplicit_include オプションを指定する必要があります。このオプションを指定すると、C++ コンパイラはサーバ スケルトン ヘッダ ファイル (_s.h ) がインクルードされる場所にサーバ スケルトン定義ファイル (_s.cpp ) を自動的に組み込みません。これは、複数定義のシンボル エラーを回避するために必要です。Tru64 C++ で tie クラスなどのクラス テンプレートを使用する方法については、Compaq の出版物を参照してください。 |