ページの先頭行へ戻る
Interstage Application Server アプリケーション作成ガイド(データベース連携サービス編)

3.2.2 ソースの作成

3.2.2.1 アプリケーションの構成

  グローバルトランザクション運用を行うためには、CORBAのクライアントアプリケーションの処理に加えて、CosTransactions::Current::commitメソッドなどのCurrentインタフェースを呼び出して、データベース連携サービスにトランザクション処理を依頼します。
  これらの処理を考慮したクライアントアプリケーションの構成について以下に示します。



初期化処理部

  クライアントアプリケーションをCORBAサービスに登録、およびトランザクションサービスの初期化を行います。


アプリケーション固有部

  アプリケーション固有の処理部です。トランザクションの開始から終了までの流れを記述します。


トランザクション用ライブラリ

  データベース連携サービスが提供するクライアントアプリケーション用ライブラリです。


  クライアントアプリケーションの基本形を以下に示します。

                         :
static  CORBA::ORB_ptr               orb;
static  CosTransactions::Current_ptr Current;
static  CosNaming::NamingContext_ptr obj;
static  CosNaming::NamingContext_ptr naming_obj;
                         :
/* 初期化処理  */
orb = CORBA::ORB_init(argc, argv, FJ_OM_ORBid, *env);
                        :
naming_obj = NamingContext_obj->resolve(*name, *env);     … (1)
                        :
/* トランザクション依頼処理 */
obj = orb->resolve_initial_references
     (CORBA_ORB_ObjectId_TransactionCurrent, *env);       … (2)
Current = CosTransactions::Current::narrow(obj);
Current->begin(*env);                                     … (3)
                        :
srvobj->ope1(para, *env                                   … (4)
                        :
if (env->exception())                                     … (5)
    Current->rollback(*env);
else
    Current->commit(CORBA_TRUE, *env);

  1. ネーミングサービスからサーバアプリケーションのオブジェクトリファレンスを獲得します。

  2. Currentインタフェースのオブジェクトリファレンスを獲得します。

  3. CosTransactions::Current::beginメソッドでトランザクションの開始を宣言します。

  4. サーバアプリケーションを呼び出します。

  5. サーバアプリケーションの復帰状態を確認して、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドでトランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドでトランザクションをロールバックします。


3.2.2.2 形態の説明

  クライアントアプリケーションからサーバアプリケーションを呼び出す形態を以下に示します。


同期型

  サーバアプリケーションを呼び出し、サーバアプリケーションのメソッドが終了した時点でクライアントアプリケーションに制御が戻ります。


非同期型

  サーバアプリケーションを呼び出し、サーバアプリケーションのメソッドの終了を待たずにクライアントアプリケーションに制御が戻ります。クライアントアプリケーションは任意のタイミングでサーバアプリケーションのメソッドの終了を問い合わせます。


同期型

呼出し形態

  同期型呼出しは、クライアントアプリケーションからサーバアプリケーションを呼び出し、そのサーバアプリケーションの処理終了を待ち合わせる呼出し形態です。同期型の呼出し形態について、以下に示します。



インタフェース

  同期型には、以下の2つのインタフェースがあります。詳細については、“リファレンスマニュアル(API編)”を参照してください。

  • 静的起動インタフェース
      サーバアプリケーションのメソッド名を指定して呼び出します。

  • 動的起動インタフェース
      RequestインタフェースのCORBA::Request::invoke()メソッドでサーバアプリケーションを呼び出します。

  動的起動インタフェースにおいて、遅延同期送信を行う場合の注意事項を以下に示します。


遅延同期送信の呼出し

  遅延同期送信の呼出し元は、その呼出しの復帰が完了するまでデータベースの操作を禁止します。


遅延同期送信で呼び出されたサーバ

  遅延同期送信の呼出し先は、データベースを使用する場合には、複数の呼出しが同じデータベースをアクセスできません。


同一データベースへのアクセス

  遅延同期送信で呼び出されたアプリケーションから、同時に同一のデータベースを操作することはできません。



異なるデータベースへのアクセス

  遅延同期送信で呼び出されたアプリケーションから、異なるデータベースを操作することができます。



アプリケーションの処理論理

  同期型を使用する場合のクライアントアプリケーションの処理論理を以下に示します。



  1. サーバアプリケーションAのメソッド1を呼び出します。クライアントアプリケーションは、サーバアプリケーションAのメソッドが終了するまで待ち合わせます。

  2. クライアントアプリケーションは、サーバアプリケーションAのメソッド1の処理が終了した時点で制御が戻ります。

  3. サーバアプリケーションBのメソッド2を呼び出します。クライアントアプリケーションは、サーバアプリケーションBのメソッドが終了するまで待ち合わせます。

  4. クライアントアプリケーションは、サーバアプリケーションBのメソッド2の処理が終了した時点で制御が戻ります。


非同期型


呼出し形態

  非同期型呼出しは、クライアントアプリケーションからサーバアプリケーションを呼び出し、サーバアプリケーションのメソッドの終了を待たずにクライアントアプリケーションに制御が戻ります。クライアントアプリケーションは任意のタイミングでサーバアプリケーションのメソッドの終了結果を問い合わせる呼出し形態です。
  非同期型の呼出し形態を以下に示します。



インタフェース

  RequestインタフェースのCORBA::Request::send_deferred()メソッドを使用します。詳細については、“リファレンスマニュアル(API編)”を参照してください。


アプリケーションの処理論理

  非同期型を使用する場合のクライアントアプリケーションの処理論理を以下に示します。



  1. サーバアプリケーションAのメソッド1を非同期型で呼び出します。

  2. サーバアプリケーションBのメソッド2を非同期型で呼び出します。

  3. メソッド1の処理終了を問い合わせます。

  4. メソッド2の処理終了を問い合わせます。


3.2.2.3 静的起動インタフェース

  静的起動インタフェースでサーバアプリケーションを呼び出す場合の、クライアントアプリケーションの記述例について説明します。


初期化

  初期化処理として、ORBのオブジェクトリファレンスを取得します。オブジェクトリファレンスを取得するには、初期化メソッドを呼び出します。
  記述例を以下に示します。


main(argc, argv )
    int  argc;
    char *argv[];
{

    CORBA::ORB_ptr          orb;                   // ORBのオブジェクトリファレンス
    CORBA::Environment_ptr  env;                   // 例外情報
    int             current_argc = argc;

    env = new CORBA::Environment;                  // 例外情報
    orb = CORBA::ORB_init(current_argc, argv, FJ_OM_ORBid, *env);

ネーミングサービスのオブジェクトリファレンスの獲得

  実行するオブジェクトをネーミングサービスから検索するために、ネーミングサービスのオブジェクトリファレンスを取得します。ネーミングサービスのオブジェクトリファレンスには、CORBAインタフェースのオブジェクトリファレンスの取り出しメソッドを使用します。
  処理の記述例を以下に示します。


// NamingServiceのオブジェクトリファレンスを獲得
CORBA::Object_ptr
obj = orb->resolve_initial_references( CORBA_ORB_ObjectId_NameService, *env );

// NamingContextクラスへの変換
CosNaming::NamingContext_ptr
NamingContext_obj = CosNaming::NamingContext::_narrow( obj );

サーバアプリケーションのオブジェクトリファレンスの獲得

  ネーミングサービスから、実行したいサーバアプリケーションの情報を検索します。サーバアプリケーションの情報を取り出すには、実行するサーバアプリケーションのオブジェクト名をパラメタとしてメソッドを起動し、オブジェクトリファレンス情報が格納されているネーミングコンテキストを取得します。
  処理の記述例を以下に示します。


CosNaming::Name_ptr             name;             // CosNaming::Nameのインスタンス
CosNaming::NameComponent_var    *name_component;  // オブジェクト名格納域
CORBA::Object_ptr               obj;  // サーバアプリケーションのオブジェクトリファレンス

// CosNaming::NameComponent_var領域の獲得
name_component = CosNaming::Name::allocbuf(1);

// オブジェクト名
name_component[0]->id = (const CORBA::Char *)"ODdemo::calculator";
// オブジェクトのタイプ
name_component[0]->kind = (const CORBA::Char *)"";

// CosNaming::Name領域の獲得
name = CosNaming::Name(1,1,name_component,CORBA_TRUE );

// サーバアプリケーションのオブジェクトリファレンスを獲得
obj = NamingContext_obj-> resolve( *name, *env );

// ODdemo::calculatorクラスへの変換
ODdemo::calculator_ptr ap = ODdemo::calculator::_narrow( obj);

トランザクションの開始

  トランザクションを開始するために、Currentインタフェースのオブジェクトリファレンスを取得し、CosTransactions::Current::beginメソッドを呼び出します。
  処理の記述例を以下に示します。


CosTransactions::Current_ptr Current;  /* トランザクション開始オブジェクトリファレンス */
  
/* トランザクション開始インタフェースのオブジェクトリファレンスを獲得 */
 obj = orb->resolve_initial_refarences(
           CORBA_ORB_ObjectId_TransactionCurrent,
           *env);
Current = CosTransactions::Current::_narrow(obj);

/* トランザクション開始メソッドの呼出し */
Current->begin(*env);

サーバオブジェクトのメソッド起動

  メソッド名は、IDLで指定したモジュール名、インタフェース名、およびオペレーション名をコロン2つ(::)でつなげた形式で指定します。この例では、ODdemo、calculator、およびcalculateが該当します。なお、メソッドを呼出し時に、ネーミングサービスから取得したサーバアプリケーションのオブジェクトリファレンスおよびサーバプログラムで例外が発生した場合、例外情報を獲得するためにCORBA::Environment構造体を指定します。
  処理の記述例を以下に示します。


ODdemo::calculator::result      res;    // 復帰値
CORBA::Long                     a, b;   // パラメタ

a = 10;
b = 5;

// メソッドの呼出し
res = ap->calculate( a, b, *env );

トランザクションの完了

  サーバアプリケーションのメソッド呼出しの結果を復帰状態から判断し、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドを呼び出し、トランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドを呼び出し、トランザクションをロールバックします。
  処理の記述例を以下に示します。


/* サーバアプリケーションのメソッド呼出しの復帰状態を確認 */
if(env->exception())
    Current->rollback(*env);
else
    Current->commit(CORBA_TRUE, *env);

3.2.2.4 動的起動インタフェース

  動的起動インタフェースでサーバアプリケーションを呼び出す場合の、クライアントアプリケーションの記述例について説明します。


初期化

  初期化処理として、ORBのオブジェクトリファレンスを取得します。オブジェクトリファレンスを取得するには、初期化メソッドを呼び出します。
  記述例を以下に示します。


main(argc, argv )
    int  argc;
    char *argv[];
{
    CORBA::ORB_ptr          orb;                   // ORBのオブジェクトリファレンス
    CORBA::Environment_ptr  env;                   // 例外情報
    int             current_argc = argc;

    env = new CORBA::Environment;                  // 例外情報
    orb = CORBA::ORB_init(current_argc, argv, FJ_OM_ORBid, *env);
                    :
}

ネーミングサービスのオブジェクトリファレンスの獲得

  実行するオブジェクトをネーミングサービスから検索するために、ネーミングサービスのオブジェクトリファレンスを取得します。ネーミングサービスのオブジェクトリファレンスには、CORBAインタフェースのオブジェクトリファレンスの取り出しメソッドを使用します。
  処理の記述例を以下に示します。


// NamingServiceのオブジェクトリファレンスを獲得
CORBA::Object_ptr
obj = orb->resolve_initial_references( CORBA_ORB_ObjectId_NameService, *env );

// NamingContextクラスへの変換
CosNaming::NamingContext_ptr
NamingContext_obj = CosNaming::NamingContext::_narrow( obj );
CORBA::release(obj);

インタフェースリポジトリのサーバアプリケーション情報の獲得

  インタフェースリポジトリには、IDLで定義されたモジュール名、インタフェース名、オペレーション名、およびパラメタが階層構造で格納されています。インタフェースリポジトリからサーバアプリケーションの情報を獲得する方法について、以下に示します。


(1) InterfaceDefオブジェクトリファレンスの獲得

  インタフェースリポジトリからサーバアプリケーションの情報を取得するためには、InterfaceDefオブジェクトのオブジェクトリファレンスが必要です。InterfaceDefオブジェクトのオブジェクトリファレンスを求めるには、オブジェクト名をパラメタとして、ネーミングサービスからサーバアプリケーションのオブジェクトリファレンスを求めたあと、CORBA_Object::get::interface()メソッドにより、InterfaceDefオブジェクトリファレンスを取得します。
  処理の記述例を以下に示します。


CORBA::Object_ptr       obj;                      // オブジェクトリファレンス格納域
CosNaming::Name_ptr     name;                     // CosNaming::Nameのインスタンス
CosNaming::NameComponent_var    *name_component;  // オブジェクト名格納域

// CosNaming::NameComponent_var領域の獲得
name_component = CosNaming::Name::allocbuf(1);

name_component[0]->id = (const CORBA::Char *)"ODdemo::calculator"; // オブジェクト名
name_component[0]->kind = (const CORBA::Char *)"";                 // オブジェクトのタイプ
name = new CosNaming::Name(1,1,name_component,CORBA_TRUE );        // CosNaming::Name領域の獲得

// サーバアプリケーションのオブジェクトリファレンスを獲得
obj = NamingContext_obj-> resolve( *name, *env );

// InterfaceDefオブジェクトリファレンス取得
CORBA::InterfaceDef_ptr intf = obj->_get_interface( *env );

(2) OperationDefオブジェクトリファレンスの取得

  サーバアプリケーションのメソッド名をパラメタとして、CORBA::InterfaceDef::lookup_name()メソッドを使用することにより、インタフェースリポジトリから指定されたメソッドを検索します。結果として、指定したメソッド情報が格納されたOperationDefオブジェクトのオブジェクトリファレンスが通知されます。

// メソッドのOperationDefオブジェクトリファレンス取得
CORBA::ContainedSeq_ptr intf_opr = intf->lookup_name(
        "calculate",                  // メソッド名
        -1,
        CORBA::dk_Operation,          // Operation情報の取得
        CORBA_FALSE,
        *env );

// OperationDefクラスへの変換
CORBA::OperationDef_ptr OperationDef_obj = CORBA::OperationDef::_narrow((*intf_opr)[0]);

(3) パラメタ情報の取得

  OperationDefオブジェクトリファレンスをパラメタとして、CORBA::OperationDef::describe()メソッドにより、サーバアプリケーションがもっているメソッドのパラメタの情報(パラメタの名前、個数、パラメタの型など)をインタフェースリポジトリから検索します。

// 指定されたメソッドのパラメタ情報を検索
CORBA::Contained::Description   *description = OperationDef_obj->describe( *env );

トランザクションの開始

  トランザクションを開始するために、Currentインタフェースのオブジェクトリファレンスを取得し、CosTransactions::Current::beginメソッドを呼び出します。
  処理の記述例を以下に示します。


CosTransactions::Current_ptr Current;  /* トランザクション開始オブジェクトリファレンス */

/* トランザクション開始インタフェースのオブジェクトリファレンスを獲得 */
obj = orb->resolve_initial_refarences(
           CORBA_ORB_ObjectId_TransactionCurrent,
           *env);
Current = CosTransactions::Current::_narrow(obj);

/* トランザクション開始メソッドの呼出し */
Current->begin(*env);

パラメタの組み立て


(1) パラメタリストの生成

  サーバアプリケーションに渡すパラメタを格納するための領域を保持するリストオブジェクトを生成するために、CORBA::ORB::create_list()メソッドに、何個のパラメタを格納するかを指定します。これにより、NVListオブジェクトリファレンスが通知されます。処理の記述例を以下に示します。

// Contained_Description構造体からパラメタ情報構造体の抽出
CORBA::Any tmp_any =  *description->value; 
CORBA::OperationDescription *opr_description =
        (CORBA::OperationDescription *)tmp_any.value();

// パラメタ情報の抽出
CORBA::ParDescriptionSeq  *params = opr_description->parameters;

CORBA::NVList             *arg_list;                   // NVList

orb->create_list( params->length(), arg_list, *env );  // リストオブジェクトの生成

(2) パラメタリストの設定

  CORBA_NVListオブジェクトリファレンス、サーバアプリケーションのパラメタの名前、型、値、および長さをパラメタとしてCORBA::NVList::add_value()メソッドにより、サーバアプリケーションに渡すパラメタをリストオブジェクトに設定します。
  処理の記述例を以下に示します。

CORBA::Any      p1, p2;
CORBA::Long     x = 10, y = 20;
p1 <<= x;
p2 <<= y;

// パラメタの設定
arg_list->add_value(
    ((*params)[0])->name,        // パラメタ名
    p1,                          // パラメタの型および値
    CORBA::ARG_IN,               // パラメタのタイプ(in,out, inout)
    *env );

// パラメタの設定
arg_list->add_value(
    ((*params)[1])->name,        // パラメタ名
    p2,                          // パラメタの型および値
    CORBA::ARG_IN,               // パラメタのタイプ(in,out, inout)
    *env );

リクエストの作成

  CORBA::Object::create_request()メソッドにより、リクエストオブジェクトを作成します。リクエストとは、メソッド名にパラメタを加えたものです。リクエストオブジェクトに対して、サーバオブジェクトのオブジェクトリファレンス、NVListオブジェクトリファレンス、後述するNamedValueと呼ぶサーバの処理結果を格納する領域を指定することによりリクエストオブジェクトのオブジェクトリファレンスが通知されます。
  処理の記述例を以下に示します。


CORBA::NVList_ptr arg_tmp;

// 復帰パラメタ用リストオブジェクトの生成
orb->create_list(1, arg_tmp, *env);

ODdemo::calculator::result *res = NULL;

CORBA::Any any_tmp( _tc_ODdemo_calculator_result, res, CORBA_FALSE );

// 結果用受取り用変数(CORBA::NamedValue型変数)
CORBA::NamedValue_ptr
result = arg_tmp->add_value(
        NULL,           // resultの設定
        any_tmp,
        (CORBA::Flags)0,
        *env);

CORBA::Request_ptr      request;

// リクエストオブジェクトの生成
obj->_create_request(
    CORBA_OBJECT_NIL,        // context
    "calculate",             // メソッド名
    arg_list,                // 入力パラメタ
    result,                  // 復帰値
    request,                 // 出力パラメタの格納域
    CORBA::OUT_LIST_MEMORY,
    *env );

  NamedValueは、サーバの処理結果を格納するための領域です。
  システムで定義する定義例を以下に示します。


IDLファイルの定義例
module CORBA
{
    struct NamedValue
    {
        identifier      name;         // パラメタの名前
        any              argument;    // パラメタの値
        long             len;         // パラメタの長さ
        Flags          arg_modes;     // パラメタの引き渡し方法(in,out,inout)
    };
};

C++言語での定義例
class CORBA 
{
    class NamedValue
    { 
        public: 
        const char *name(CORBA::Environment &) const;  // パラメタの名前
        Any *value(CORBA::Environment &) const;        // パラメタの値
        Flags flags(CORBA::Environment &) const;       // パラメタの引き渡し方法(in,out,inout)
    };
};

リクエストの送信

  サーバアプリケーションに対してリクエストを送信します。リクエストの方法として、以下の方法があります。

  それぞれについて、以下に示します。


同期送信

  リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::Request::invoke()メソッドにより、サーバアプリケーションを呼び出します。処理の記述例を以下に示します。

request->invoke( *env );

非同期送信

  リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::Request::send_deferred()メソッドにより、サーバアプリケーションを呼び出します。サーバアプリケーションの処理結果は、CORBA::Request:get_response()メソッドにより受け取ります。
  処理の記述例を以下に示します。

request->send_deferred( *env );      // 処理の要求
request->get_response( *env );       // 処理結果の受取り

  CORBA::Request::get_response()サーバアプリケーションからリクエストが完了していないことが判明した場合、再度CORBA::Request::get_response()メソッドを呼び出します。


リクエストの削除

  リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::release()関数により、リクエストオブジェクトを削除します。また、同様にNVListオブジェクトのオブジェクトリファレンスをパラメタとしてCORBA::release()関数により、NVListオブジェクト削除をします。
  処理の記述例を以下に示します。


CORBA::release( request );      // リクエストオブジェクトの削除
CORBA::release( arg_list);      // NVListオブジェクトの削除

トランザクションの完了

  サーバアプリケーションのメソッド呼出しの結果を復帰状態から判断し、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドを呼び出し、トランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドを呼び出し、トランザクションをロールバックします。
  処理の記述例を以下に示します。


/* サーバアプリケーションのメソッド呼出しの復帰状態を確認 */
if(env->exception())
    Current->rollback(*env);
else
    Current->commit(CORBA_TRUE, *env);