1. CORBA アプリケーション

1.1. チュートリアル

この節では、Object Brokerを使ったCORBAアプリケーションの作成手順を、サンプルアプリケーションを例にして説明します。

1.1.1. C++でCORBAアプリケーションを作成する

C++でCORBAアプリケーションを作成する手順は以下のとおりです。
  1. オブジェクトが提供するインタフェースを決める。
  2. インタフェース定義言語(Interface Definition Language : IDL)を用いてインタフェースを定義する。
  3. IDL定義をIDLコンパイラにかける。
  4. 定義したインタフェースについて、サーバの実装コードを記述する。
  5. Calcオブジェクトを呼び出すクライアントアプリケーションのコードを記述する。
  6. C++コンパイラでクライアントとサーバのアプリケーションをビルドする。
  7. アプリケーションを実行する。
IDLによるインタフェースの記述
サーバが提供するインタフェースをIDL言語で記述します。本書では開発環境のcalcサンプルをとりあげます。 calc.idl
interface Calc {
  readonly attribute double memory;

  double add(in double a, in double b);
  double sub(in double a, in double b);
  double mul(in double a, in double b);
  double div(in double a, in double b);
  void mc();
  double mr();
  void ms(in double a);
  void mp(in double a);
};
interfaceは、C++のclass定義に相当します。readonly attributeは読み出し専用の属性であることを示します。各オペレーションの引数の前にある"in"はオペレーションに渡すための引数であり、オペレーションによって値が設定されることはないことを示します。引数を持たないときはかっこ内には何も書きません。 calcは簡易電卓オブジェクトのインタフェースです。1つの属性(アトリビュート)定義と8つのオペレーション定義からなります。
IDLソースファイルのコンパイル
記述したインタフェース定義をIDLコンパイラにかけてC++言語のソースコードに変換します。変換したファイルをライブラリと共にリンクすることにより、同一プロセス内のC++オブジェクトと同じようにリモートのオブジェクトを呼び出すことができるようになります。 次のコマンド行によりコンパイルを行います。
IDLコンパイラの実行
> i2cc calc.idl

Caution i2ccへのパスが正しく設定されている必要があります。

Windows版ではi2ccがVisual C++の機能を利用します。したがって、Visual C++をインストールしておく必要があります。また、Visual C++のbinディレクトリがパスに設定されている必要があります。
この結果、次の3つのソースファイルが生成されます。
calc.h ヘッダーファイル
クライアントおよびサーバアプリケーションでインクルードします。
calccmn.cpp (UNIXでは.C) 共通ファイル
クライアントおよびサーバアプリケーションにリンクします。
calcimp.cpp (UNIXでは.C) サーバアプリケーション用ファイル
サーバアプリケーションにリンクします。

Caution これらのファイルの内容をアプリケーション開発者は意識する必要はありません。また、生成されたソースコードは決して変更しないでください。変更した場合の動作は保証できません。

ファイル名は、ソースファイルの拡張子を除いたファイル名を元にして、それぞれ「.h」、「cmn.cpp」、「imp.cpp」をつけ加えて決定しています。

Caution アプリケーション開発者はこの名前のファイルを作成しないようにしてください。同じ名前のファイルが存在する場合でも、IDLコンパイラは警告なしに上書きします。

オブジェクトリファレンスの取得
オブジェクトの取得については、[1.2.2. Object Broker > オブジェクトリファレンスの取得] を参照してください。
サーバプログラム
サーバプログラムでは、IDLで定義したインタフェースの実装コードおよびmain関数を記述します。配布サンプルではそれぞれcalc_i.cpp、server.cppに対応します。
オペレーションの実装
サーバ側では1つのCORBAオブジェクトに対応して、1つのC++オブジェクトを作成します。このクラスはサーバプログラマが規定します。このクラスを本書では実装クラスと呼びます。実装クラスは、スケルトンクラスを継承して記述します。 スケルトンクラスのクラス名はIDL定義によって変化します。
// IDL
interface Foo{...};

// C++
class POA_Foo{...};
// IDL
module M{
  interface Foo{...};
};

// C++
class POA_M::Foo{...};

サンプルではPOA_Calcクラスになります。 サンプルでは実装クラスはCalc_iです。上記のとおり、POA_Calcクラスを継承しています。

calc_i.h
class Calc_i : public virtual POA_Calc {
       CORBA::Double mem;
      
       public:
       Calc_i();
       virtual ~Calc_i();
      
       virtual CORBA::Double add(
                CORBA::Double a,
                CORBA::Double b,
                CORBA::Environment& env = Ob_default_environment()
       );
 
       virtual CORBA::Double sub(
                CORBA::Double a,
                CORBA::Double b,
                CORBA::Environment& env = Ob_default_environment()
       );
 
       virtual CORBA::Double mul(
                CORBA::Double a,
                CORBA::Double b,
                CORBA::Environment& env = Ob_default_environment()
       );
 
       virtual CORBA::Double div(
                CORBA::Double a,
                CORBA::Double b,
                CORBA::Environment& env = Ob_default_environment()
       );
 
       virtual void mc(
                CORBA::Environment& env = Ob_default_environment()
       );
      
       virtual CORBA::Double mr(
                CORBA::Environment& env = Ob_default_environment()
       );
      
       virtual void ms(
                CORBA::Double a,
                CORBA::Environment& env = Ob_default_environment()
       );
 
       virtual void mp(
                CORBA::Double a,
                CORBA::Environment& env = Ob_default_environment()
       );
};
各実装メンバ関数は仮想関数です。 IDLのデータ型とC++でのデータ型とのマッピングに関しては、[1.2.2. Object Broker > C++マッピング] の説明を参照してください。 calc_i.cppの一部を示します。
#include <iostream.h>
#include "orb.h"
#include "calc.h"
#include "calc_i.h"

Calc_i::Calc_i()
{
    mem = 0;
}

Calc_i::~Calc_i()
{
}

CORBA::Double Calc_i::add(CORBA::Double a, CORBA::Double b, CORBA::Environment&)
{
    return (a + b);
}
Calc_iクラスのオペレーションを表す各メンバ関数内にサーバアプリケーションロジックを記述します。
main関数の実装
サーバのmain関数は次のながれにしたがって記述します。サンプルではmain関数はserver.cppにあります。
  1. ORBの初期化
  2. POAの作成
  3. サーバント(実装オブジェクト)を活性化
  4. POAの活性化通知
  5. リクエスト待ちおよび実行
ORBの初期化
ORBの初期化は [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB_init] により行います。この関数にはmainの引数argc, argvを渡します。
// ORBの初期化 : サーバ/クライアントに関わらず必須
CORBA::ORB_var orbobj = CORBA::ORB_init(argc, argv, "ObjectSpinner");
POAの作成
POAは、いくつかの方針(ポリシ)を持っていてサーバの動作を決定づけています。calcサンプルでは使用しませんが、ルートPOAとは異なるポリシをもつPOAが必要ならば、既存のPOAの [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > create_POA] メソッドにより子POAを作成します。 はじめてPOAを作成する場合は、ルートPOAの子POAとして作成します。ルートPOAは、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::resolve_initial_references] で取得できます。 詳しくは、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > PortableServer::POAクラス] を参照してください。
// ルートPOAの取得
CORBA::Object_var tmpobj = orbobj->resolve_initial_references("RootPOA");
PortableServer::POA_ptr poa = PortableServer::POA::_narrow(tmpobj);

// ポリシリストの作成
CORBA::PolicyList plist(7);
plist.length(7);
plist[0] = poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
...

// 子POAの作成
PortableServer::POA_ptr child_poa =
    poa->create_POA("POA名", PortableServer::POAManager::_nil(), plist);
...
サーバント(実装オブジェクト)の活性化
サーバントをPOAに対応付けます。calcサンプルでは、作成したサーバントの_this()メソッドを呼ぶことで暗黙的に活性化しています。 サーバントの活性化については、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > PortableServer::POAクラス] を参照してください。
// サーバントを作成
Calc_i* calcsvt = new Calc_i;

// サーバントを活性化
Calc_var calcobj = calcsvt->_this();
calcサンプルでは、作成したオブジェクトリファレンスを文字列に変換してファイルに書き出します。クライアント側ではこのファイルを読み込んでオブジェクト呼び出しに利用します。 オブジェクトの取得については、[1.2.2. Object Broker > オブジェクトリファレンスの取得] を参照してください。
ofstream strm("Calc.ref");
CORBA::String_var str = orb->object_to_string(calcobj);
strm << str << endl;
POAの活性化通知
クライアントから呼び出されるきっかけとなるオブジェクトを活性化したならば、そのオブジェクトを管理しているPOAがオブジェクトへの要求受け入れ準備ができたことを、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > activate] メソッドを呼び出してORBに通知します。
PortableServer::POAManager_var poamgr = poa->the_POAManager();
poamgr->activate();
リクエスト待ちおよび実行
main関数では上記処理終了後、リクエスト待ちおよび実行をする [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::run] 関数を呼び出します。
orbobj->run();
また、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::work_pending] と [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::perform_work] を組み合わせて独自のリクエスト処理ループを作成することができます。
for(;;) {
    if (orbobj->work_pending()) {
        ...
        orbobj->perform_work();
        ...
    }
}
CORBA::ORB::work_pending()はクライアントからの要求を調べます。 CORBA::ORB::work_pendingの動作はサーバのスレッド処理方針により異なります。

Caution [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::shutdown] オペレーションが呼ばれた後のCORBA::ORB::work_pending()は、常に0を返すようになります。

CORBA::ORB::perform_work()は要求を処理します。このメンバの中から実装クラスのオペレーション実装メンバ関数が呼ばれます。 終了前には、CORBA::ORB::shutdownを呼び出してクライアントからの受付を終了します。つぎに、POAの終了処理として、PortableServer::POA::create_POAなどで生成したPOAを解放します 解放は、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > PortableServer::POA::destroy] を使って行います。PortableServer::POA::destroyは、呼び出したPOAの子POAに対して再帰的にdestroyを呼び出します。最後に、ORBの終了処理として、CORBA::ORB_initで得たORBオブジェクトを解放します。解放は、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::release] を用いて明示的に(CORBA::ORB_ptr型を使っているとき)、またはCORBA::ORB_var型を使って暗黙的に行います。
// POAの解放
poa->destroy(1, 0);
サーバプログラムのコンパイル
IDLコンパイラが生成したファイルを含めてソースファイルをコンパイルリンクします。リンクするときにはWebOTX Object Brokerのライブラリもリンクします。
HP-UX(IPF)の場合:
% aCC -o calcsrv +DD64 -I$(OrbRoot)/namespace/include -AA -D_REENTRANT -DOB_HPUX_KT server.C calcimp.C calccmn.C calc_i.C -Wl,+s -Wl,+b,/usr/lib/hpux64:/lib -L$(OrbRoot)/namespace/lib -lnsospi -lpthread
HP-UX(PA-RISC)の場合:
% aCC -o calcsrv -I$(OrbRoot)/namespace/include -D_REENTRANT -DOB_HPUX_KT -D_THREAD_SAFE -DRWSTD_MULTI_THREAD +DAportable server.C calcimp.C calccmn.C calc_i.C -Wl,+s -Wl,+b,/usr/lib:/lib -L$(OrbRoot)/namespace/lib -lnsospi -lpthread
Solarisの場合:
% CC -o calcsrv -I$(OrbRoot)/namespace/include -mt server.C calcimp.C calccmn.C calc_i.C -L$(OrbRoot)/namespace/lib -lnsospi -lsocket -lnsl -lthread -ldl
Linuxの場合:
% g++ -o calcsrv -I$(OrbRoot)/namespace/include -D_REENTRANT -D_GNU_SOURCE server.C calcimp.C calccmn.C calc_i.C -L$(OrbRoot)/namespace/lib -lnsospi -ldl -lpthread
Windows(x86)の場合:
Windows(x86)でアプリケーションを作成するときは、ビルドする前にいくつかの設定を行う必要があります。
  1. devenv.exeを立ち上げ、プロジェクトファイルを開きます。
  2. プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。
  3. [C/C++] フォルダをクリックします。
  4. [コード生成] プロパティ ページをクリックします。
  5. [ランタイム ライブラリ] プロパティが、Release版であれば「マルチスレッドDLL」に、Debug版であれば「マルチスレッド デバッグDLL」になっていることを確認します。もし、ほかの設定になっている場合は正しい設定に変更してください。
  6. [C/C++]フォルダの[全般] プロパティ ページをクリックします。
  7. [追加のインクルード ディレクトリ] プロパティにWebOTX Object Brokerのインクルードファイルのパスが正しく設定されているか確認します。ファイルのパスが設定されていない場合は、正しいパスを設定してください。
  8. [プロパティ ページ] ダイアログ ボックスの[リンク] フォルダをクリックします。
  9. [全般] プロパティ ページをクリックします。
  10. WebOTX Object Brokerのライブラリをリンクするライブラリの先頭に追加します。
  11. WebOTX Object Brokerのライブラリは、以下のとおりです。 [VC++ .NET2003の場合] Release版はnosp906.lib、Debug版はnosp906d.lib [VC++ 2005の場合] Release版はnosp908.lib、Debug版はnosp908d.lib [VC++ 2008の場合] Release版はnosp909.lib、Debug版はnosp909d.lib
  12. [OK]ボタンを押して[プロパティ ページ] ダイアログ ボックスを閉じます。
samples内のサンプルではWebOTX Object Brokerのライブラリはすでに追加されています。 インクルードパスとして$(OrbRoot)/namespace/includeを、ライブラリパスとして$(OrbRoot)/namespace/libを設定してください。
Windows(IA64)の場合:
Windows(IA64)でのアプリケーションを作成は、Microsoft Platform SDKを利用して行います。ビルド時には以下の指定を行う必要があります。
  • インクルードファイルパスに「<WebOTX>\ObjectBroker\namespace\include」を追加してください。
  • ライブラリファイルパスに「<WebOTX>\ObjectBroker\namespace\lib」を追加してください。
  • コンパイルオプションに「/MD(デバッグ版なら/MDd)」および「/As64」を指定してください。
  • リンクするライブラリに以下のライブラリを追加してください。 Release版はnosp905.lib、Debug版はnosp905d.lib
  • リンクオプションに「/MACHINE:IA64」を指定してください。
以下に、Makefileのサンプルを示します。
OUTDIR=.\Release
INTDIR=.\Release

ALL : "$(OUTDIR)\calcsrv.exe"

CLEAN :
     -@erase
"$(INTDIR)\calc_i.obj"
     -@erase
"$(INTDIR)\calccmn.obj"
     -@erase
"$(INTDIR)\calcimp.obj"
     -@erase
"$(INTDIR)\server.obj"
     -@erase
"$(INTDIR)\vc60.idb"
     -@erase
"$(OUTDIR)\calcsrv.exe"

"$(OUTDIR)" :
  if not exist "$(OUTDIR)/$(NULL)"
mkdir "$(OUTDIR)"

CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D
"NDEBUG" /D "_CONSOLE" /Fp"$(INTDIR)\calcsrv.pch" /YX
/Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /As64 /c

.cpp{$(INTDIR)}.obj::
 $(CPP) @<<
 $(CPP_PROJ) $<
<< 

LINK32=link.exe
LINK32_FLAGS=nosp905.lib kernel32.lib user32.lib
gdi32.lib winspool.lib comdlg32.lib advapi32.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo
/subsystem:console /incremental:no
/out:"$(OUTDIR)\calcsrv.exe" /machine:IA64
LINK32_OBJS= \
    
"$(INTDIR)\calc_i.obj" \
    
"$(INTDIR)\calccmn.obj" \
    
"$(INTDIR)\calcimp.obj" \
    
"$(INTDIR)\server.obj"

"$(OUTDIR)\calcsrv.exe" : "$(OUTDIR)" $(DEF_FILE)
$(LINK32_OBJS)
  $(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<< 
Windows(x64)の場合:
Windows(x64)でのアプリケーションを作成は、Microsoft Platform SDKを利用して行います。ビルド時には以下の指定を行う必要があります。
  • インクルードファイルパスに「<WebOTX>\ObjectBroker\namespace\include」を追加してください。
  • ライブラリファイルパスに「<WebOTX>\ObjectBroker\namespace\lib」を追加してください。
  • コンパイルオプションに「/MD(デバッグ版なら/MDd)」を指定してください。
  • リンクするライブラリに以下のライブラリを追加してください。 [Microsoft Platform SDKの場合] Release版はnosp907.lib, bufferoverflowU.lib、Debug版はnosp907d.lib, bufferoverflowU.lib [Visual Studio 2008の場合] Release版はnosp9010.lib、Debug版はnosp9010d.lib
  • リンクオプションに「/MACHINE:AMD64」を指定してください。
以下に、Makefileのサンプルを示します。
OUTDIR=.\Release
INTDIR=.\Release

ALL : "$(OUTDIR)\calcsrv.exe"

CLEAN :
     -@erase
"$(INTDIR)\calc_i.obj"
     -@erase
"$(INTDIR)\calccmn.obj"
     -@erase
"$(INTDIR)\calcimp.obj"
     -@erase
"$(INTDIR)\server.obj"
     -@erase
"$(INTDIR)\vc60.idb"
     -@erase
"$(OUTDIR)\calcsrv.exe"

"$(OUTDIR)" :
  if not exist "$(OUTDIR)/$(NULL)"
mkdir "$(OUTDIR)"

CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D
"NDEBUG" /D "_CONSOLE" /Fp"$(INTDIR)\calcsrv.pch" /YX
/Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c

.cpp{$(INTDIR)}.obj::
 $(CPP) @<<
 $(CPP_PROJ) $<
<< 

LINK32=link.exe
LINK32_FLAGS=nosp907.lib kernel32.lib user32.lib
gdi32.lib winspool.lib comdlg32.lib advapi32.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib
bufferoverflowU.lib /nologo /subsystem:console
/incremental:no /out:"$(OUTDIR)\calcsrv.exe"
/machine:AMD64
LINK32_OBJS= \
    
"$(INTDIR)\calc_i.obj" \
    
"$(INTDIR)\calccmn.obj" \
    
"$(INTDIR)\calcimp.obj" \
    
"$(INTDIR)\server.obj"

"$(OUTDIR)\calcsrv.exe" : "$(OUTDIR)" $(DEF_FILE)
$(LINK32_OBJS)
  $(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<< 
クライアントプログラム
クライアントプログラムでは以下の処理を行います。
  1. ORBの初期化を行う。
  2. オブジェクトリファレンスを取得する。
  3. インタフェース依存のオブジェクトリファレンスに変換する。
  4. オブジェクトのオペレーションを呼び出す。
  5. 不要になったメモリを解放する。
  6. ORBの終了処理を呼び出す。
ORBの初期化
サーバプログラムと同様です。[ORBの初期化] を参照してください。
オブジェクトリファレンスの取得
サーバプログラムのところで説明したとおり、calcではサーバで文字列に変換されファイルに書き出されたオブジェクトリファレンスをクラスオブジェクトに復元します。
ifstream strm("Calc.ref");
strm >> ref;
CORBA::Object_var objPtr = orb->string_to_object(ref, env);
上記以外の取得方法は、[1.2.2. Object Broker > オブジェクトリファレンスの取得] を参照してください。
インタフェース依存オブジェクトリファレンスへの変換
CORBA::Object_ptr型のままでは、スタブによる呼び出しができませんので、インタフェース依存のオブジェクトリファレンスへ変換します。
Calc_var calc = Calc::_narrow(tobj);
Calcクラスの_narrowスタティックメンバにより行います。
オブジェクトオペレーションの呼び出し
calcのメソッドを呼び出します。メソッド内でORBの通信に変換されてサーバに要求が届きます。
CORBA::Double result;
result = calc->add(1024, 2048, env);
クライアントプログラムのコンパイル
IDLが生成したソースファイルとともにクライアントソースファイルをコンパイル、リンクします。このとき、WebOTX Object Brokerのライブラリもリンクします。
HP-UX(IPF)の場合:
% aCC -o calccli +DD64 -I$(OrbRoot)/namespace/include -AA -D_REENTRANT -DOB_HPUX_KT client.C calccmn.C -Wl,+s -Wl,+b,/usr/lib/hpux64:/lib -L$(OrbRoot)/namespace/lib -lnsospi -lpthread
HP-UX(PA-RISC)の場合:
% aCC -o calccli -I$(OrbRoot)/namespace/include -D_REENTRANT -DOB_HPUX_KT -D_THREAD_SAFE -DRWSTD_MULTI_THREAD client.C calccmn.C -Wl,+s -Wl,+b,/usr/lib:/lib -L$(OrbRoot)/namespace/lib -lnsospi -lpthread
Solarisの場合:
% CC -o calccli -I$(OrbRoot)/namespace/include -mt client.C calccmn.C -L$(OrbRoot)/namespace/lib -lnsospi -lsocket -lnsl -lthread -ldl
Linuxの場合:
% g++ -o calccli -I$(OrbRoot)/namespace/include -D_REENTRANT -D_GNU_SOURCE client.C calccmn.C -L$(OrbRoot)/namespace/lib -lnsospi -ldl -lpthread
Windows(x86)の場合:
Windows(x86)でアプリケーションを作成するときは、ビルドする前にいくつかの設定を行う必要があります。
  1. devenv.exeを立ち上げ、プロジェクトファイルを開きます。
  2. プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。
  3. [C/C++] フォルダをクリックします。
  4. [コード生成] プロパティ ページをクリックします。
  5. [ランタイム ライブラリ] プロパティが、Release版であれば「マルチスレッドDLL」に、Debug版であれば「マルチスレッド デバッグDLL」になっていることを確認します。もし、ほかの設定になっている場合は正しい設定に変更してください。
  6. [C/C++]フォルダの[全般] プロパティ ページをクリックします。
  7. [追加のインクルード ディレクトリ] プロパティにWebOTX Object Brokerのインクルードファイルのパスが正しく設定されているか確認します。ファイルのパスが設定されていない場合は、正しいパスを設定してください。
  8. [プロパティ ページ] ダイアログ ボックスの[リンク] フォルダをクリックします。
  9. [全般] プロパティ ページをクリックします。
  10. WebOTX Object Brokerのライブラリをリンクするライブラリの先頭に追加します。
  11. WebOTX Object Brokerのライブラリは、以下のとおりです。 [VC++ .NET2003の場合] Release版はnosp906.lib、Debug版はnosp906d.lib [VC++ 2005の場合] Release版はnosp908.lib、Debug版はnosp908d.lib [VC++ 2008の場合] Release版はnosp909.lib、Debug版はnosp909d.lib
  12. [OK]ボタンを押して[プロパティ ページ] ダイアログ ボックスを閉じます。
samples内のサンプルではWebOTX Object Brokerのライブラリはすでに追加されています。 インクルードパスとして$(OrbRoot)/namespace/includeを、ライブラリパスとして$(OrbRoot)/namespace/libを設定してください。
Windows(IA64)の場合:
Windows(IA64)でのアプリケーションを作成は、Microsoft Platform SDKを利用して行います。ビルド時には以下の指定を行う必要があります。
  • インクルードファイルパスに「<WebOTX>\ObjectBroker\namespace\include」を追加してください。
  • ライブラリファイルパスに「<WebOTX>\ObjectBroker\namespace\lib」を追加してください。
  • コンパイルオプションに「/MD(デバッグ版なら/MDd)」および「/As64」を指定してください。
  • リンクするライブラリに以下のライブラリを追加してください。 Release版はnosp905.lib、Debug版はnosp905d.lib
  • リンクオプションに「/MACHINE:IA64」を指定してください。
以下に、Makefileのサンプルを示します。
OUTDIR=.\Release
INTDIR=.\Release

ALL : "./calcimp.cpp" "./calccmn.cpp" "./calc.h"
"$(OUTDIR)\calccli.exe"

CLEAN :
     -@erase
"$(INTDIR)\calccmn.obj"
     -@erase
"$(INTDIR)\client.obj"
     -@erase
"$(INTDIR)\vc60.idb"
     -@erase
"$(OUTDIR)\calccli.exe"
     -@erase
"./calc.h"
     -@erase
"./calccmn.cpp"
     -@erase
"./calcimp.cpp"

"$(OUTDIR)" :
  if not exist "$(OUTDIR)/$(NULL)"
mkdir "$(OUTDIR)"

CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D
"NDEBUG" /D "_CONSOLE" /Fp"$(INTDIR)\calccli.pch" /YX
/Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /As64 /c

.cpp{$(INTDIR)}.obj::
 $(CPP) @<<
 $(CPP_PROJ) $<
<< 

LINK32=link.exe
LINK32_FLAGS=nosp905.lib kernel32.lib user32.lib
gdi32.lib winspool.lib comdlg32.lib advapi32.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo
/subsystem:console /incremental:no
/out:"$(OUTDIR)\calccli.exe" /machine:IA64
LINK32_OBJS= \
    
"$(INTDIR)\calccmn.obj" \
    
"$(INTDIR)\client.obj"

"$(OUTDIR)\calccli.exe" : "$(OUTDIR)" $(DEF_FILE)
$(LINK32_OBJS)
  $(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<< 
Windows(x64)の場合:
Windows(x64)でのアプリケーションを作成は、Microsoft Platform SDKを利用して行います。ビルド時には以下の指定を行う必要があります。
  • インクルードファイルパスに「<WebOTX>\ObjectBroker\namespace\include」を追加してください。
  • ライブラリファイルパスに「<WebOTX>\ObjectBroker\namespace\lib」を追加してください。
  • コンパイルオプションに「/MD(デバッグ版なら/MDd)」を指定してください。
  • リンクするライブラリに以下のライブラリを追加してください。 [Microsoft Platform SDKの場合] Release版はnosp907.lib, bufferoverflowU.lib、Debug版はnosp907d.lib, bufferoverflowU.lib [Visual Studio 2008の場合] Release版はnosp9010.lib、Debug版はnosp9010d.lib
  • リンクオプションに「/MACHINE:AMD64」を指定してください。
以下に、Makefileのサンプルを示します。
OUTDIR=.\Release
INTDIR=.\Release

ALL : "./calcimp.cpp" "./calccmn.cpp" "./calc.h"
"$(OUTDIR)\calccli.exe"

CLEAN :
     -@erase
"$(INTDIR)\calccmn.obj"
     -@erase
"$(INTDIR)\client.obj"
     -@erase
"$(INTDIR)\vc60.idb"
     -@erase
"$(OUTDIR)\calccli.exe"
     -@erase
"./calc.h"
     -@erase
"./calccmn.cpp"
     -@erase
"./calcimp.cpp"

"$(OUTDIR)" :
  if not exist "$(OUTDIR)/$(NULL)"
mkdir "$(OUTDIR)"

CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D
"NDEBUG" /D "_CONSOLE" /Fp"$(INTDIR)\calccli.pch" /YX
/Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c

.cpp{$(INTDIR)}.obj::
 $(CPP) @<<
 $(CPP_PROJ) $<
<< 
LINK32=link.exe
LINK32_FLAGS=nosp907.lib kernel32.lib user32.lib
gdi32.lib winspool.lib comdlg32.lib advapi32.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib 
bufferoverflowU.lib /nologo /subsystem:console
/incremental:no /out:"$(OUTDIR)\calccli.exe"
/machine:AMD64
LINK32_OBJS= \
    
"$(INTDIR)\calccmn.obj" \
    
"$(INTDIR)\client.obj"

"$(OUTDIR)\calccli.exe" : "$(OUTDIR)" $(DEF_FILE)
$(LINK32_OBJS)
  $(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<< 
作成したプログラムの使用方法
作成したプログラムを実行するには、OrbRootの設定とWebOTX Object Brokerが動作している必要があります。 OrbRootはWebOTX Object Brokerのインストールディレクトリの情報で、WebOTX Object Brokerをインストールすると自動的に設定されます。
設定に関する詳しい説明は [関連製品 > Object Broker Java TM > 運用ガイド > 1. 環境設定について] を参照してください。 WebOTX Object Brokerの動作確認は以下のように行います。
WebOTX Object Brokerが動作していないときは、次のようにして起動します。なお、$(OrbRoot)/binがpathに設定されているものとします。
Solaris, Linuxの場合:
下に示すコマンドを実行します。
% /etc/rc2.d/S75ObjectSpinner start
HP-UXの場合:
下に示すコマンドを実行します。
% /sbin/rc2.d/S750ObjectSpinner start
Windowsの場合:
Administrator権限のあるユーザでログオンします。「管理ツール」の「サービス」を開き、「ObjectSpinner」を選んで[開始]ボタンを押します。もし「ObjectSpinner」サービスがないときは、ORBカスタムを起動して[サービスの登録]ボタンを押します。ORBカスタムを終了して、もう一度サービスの起動を試みてください。
WebOTX Object Brokerが起動したら作成したプログラムを実行することができます。作成したcalccliおよびcalcsrvが同一ディレクトリにあり、同一マシン内での通信を試みる場合は次のように実行します。
HP-UX, Solaris, Linuxの場合:
% ./calcsrv &
% ./calccli
Windowsの場合:
> start .\calcsrv
> .\calccli
calccliとcalcsrvを別々のディレクトリもしくは別々のマシンで起動して通信を試みる場合は次のように実行します。
  1. 同一ディレクトリで同一マシンのときと同様にcalcsrvを起動します。
  2. calcsrvを起動したディレクトリに作成されるCalc.refをcalccliを起動するマシンのcalccliがあるディレクトリにコピーします。
  3. 同一ディレクトリで同一マシンのときと同様にcalccliを起動します。

Caution calcsrvを起動する場所を変更すると、Calc.refの内容も変わります。プログラムを実行する前に、古いCalc.refを削除してください。

自動起動サーバ
WebOTX Object Brokerではクライアントからの要求が発生した時点で自動的にサーバプロセスを立ち上げる機能があります。これを自動起動と呼んでいます。 自動起動のサーバであっても普通のサーバの作成と基本的に違いはありません。下記3項目に注意して作成することにより自動起動サーバとして使うことができます。
  1. mainの引数argcおよびargvをそのままCORBA::ORB_initの引数として渡す。
  2. [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::__server_path_name(const char*)] メソッドまたは設定によりサーバパス名を指定しておく。
  3. 呼び出されるオブジェクトをパーシステントオブジェクトとして作成する。
パーシステントオブジェクトについては、[パーシステントオブジェクトを持つサーバ]を参照してください。 サーバントを活性化するPOAの [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > ServantRetentionPolicy] がPortableServer::RETAINで、かつ、サーバントマネージャもデフォルトサーバントも用いない場合、サーバントの活性化には、自動起動のきっかけとなったオブジェクト(下記参照)のオブジェクトIDを指定する必要があります。 自動起動のときは、「OBARG:」で始まる文字列が自動起動引数としてサーバプロセスのargvに引き渡されます。特に指定した場合を除きargv[1]で引き渡されます。この引数から、自動起動のきっかけとなったオブジェクトのオブジェクトリファレンスを取り出すには[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > Ob_SvrInitialArg]クラスを使います。
Ob_SvrInitialArg arg(argv[1]); // argv[1]は「OBARG:」で始まる文字列
CORBA::Object_var obj = arg.this_object();
上記コードにより自動起動のきっかけとなったオブジェクトのオブジェクトリファレンスがobjに入ります。

Caution Windowsで自動起動サーバのパス名に空白(' ')が含まれている場合で、WinMainではなく、mainでプログラムを記述しているときには、含まれている空白の数だけ引数が増えて渡されます。この場合、「OBARG:」で始まる文字列がargv[1]になるように調整してからCORBA::ORB_initを呼んでください。このとき、自動起動引数の位置を指定している場合は、argv[1]ではなく適切な場所になるようにしてください。

下記コードにより自動起動のきっかけとなったオブジェクトのオブジェクトIDがoidに入ります。
PortableServer::POA_ptr poa = ... // サーバントを活性化するPOA
PortableServer::ObjectId_var oid =
poa->reference_to_id(obj);
サーバの活性化方針
サーバの動作は、サーバの活性化方針により異なります。サーバの活性化方針には以下のものがあります。
共有サーバ (既定値)
複数のオブジェクトがサーバを共有することを許します。もっとも一般的なサーバです。
非共有サーバ
同時には1つのオブジェクトしかサポートしないサーバです。
永続サーバ
自動起動が行われないサーバです。そのほかの性質については共有サーバと同じです。
メソッドごとのサーバ
メソッドが呼び出されるたびに起動されるサーバです。
サーバの活性化方針の設定は、関数で行う方法と設定で行う方法があります。 関数での設定は [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::__server_activation_policy(Obi::ActPolicyType)] で行います。 引数には、以下の値を指定します。
CORBA::ORB_var orbobj = CORBA::ORB_init(...);
...
// 非共有サーバを指定するとき
orbobj->__server_activation_policy(Obi::UnsharedServer);
サーバの活性化処理方針の設定は、CORBA::ORB::resolve_initial_referencesでルートPOAを取得する前に行ってください。 設定で指定するには、"インプリメンテーション名"ActPolicyにcorba_sharedserver(共有サーバ)、corba_unsharedserver(非共有サーバ)、corba_persistentserver(永続サーバ)、または、corba_serverpermethod(メソッドごとのサーバ)を設定します。具体的設定方法については [関連製品 > Object Broker Java TM > 運用ガイド > 1. 環境設定について] を参照してください。
サーバでのマルチスレッド
サーバプロセスでのスレッド処理方針は3通りあります。
  1. スレッドを使わない(既定値)。
  2. 処理ごとにスレッドを作成して処理する(メソッドごとのスレッド方針)。
  3. あらかじめ固定の数のスレッドを作成してラウンドロビンで処理する(プールスレッド方針)。
2, 3の場合ともスレッドのメイン関数はORBライブラリ内で提供されています。また、スレッド処理は、CORBA::ORB::runまたは、CORBA::ORB::work_pendingとCORBA::ORB::perform_workの中で行われますので、アプリケーションサーバプログラムでは、これらのメソッドをメインスレッドで実行するだけですべてのスレッド処理方針に対応することができます([リクエスト待ちおよび実行]参照)。プログラミング上スレッド処理方針による差異はありません。ただし、スレッドを利用することにより、アプリケーションプログラムの各メソッドは同時に実行される可能性があります。アプリケーションのデータの排他はアプリケーションが責任をもって行う必要があります。 スレッド処理方針が"メソッドごとのスレッド方針"のときは、クライアントからの各リクエストに対し、スレッドが作成されてリクエストが処理されます。 スレッド処理方針が"プールスレッド方針"のときは、クライアントからのリクエストを受け取ったときに、プールスレッド間で共有されるリクエストバッファにリクエストを挿入します。プールスレッドはリクエストバッファからリクエストを取り出して処理します。このときリクエストバッファに処理すべきリクエストがない場合はスレッド間同期システムコールにより待ち合わせをします。このとき、CPU利用権は放棄しています。また、必要であれば、[リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::__server_thread_number(CORBA::ULong)] メソッドまたは設定によりプールスレッド数を変更することもできます。 スレッド処理方針の設定は、関数で行う方法と設定で行う方法があります。関数での設定は [リファレンス集 開発編(共通) > 4. CORBA > 4.4. WebOTX ObjectBroker C++ > CORBA::ORB::__server_thread_policy(Ob_ThreadPolicy)] で行います。
CORBA::ORB_var orbobj = CORBA::ORB_init(...);
...
// メソッドごとのスレッド方針を指定するとき
orbobj->__server_thread_policy(Ob_thr_permethod);
...
// プールスレッド方針を指定するとき
orbobj->__server_thread_policy(Ob_thr_pool);
サーバプロセスのスレッド処理方針の設定は、CORBA::ORB::runおよびCORBA::ORB::work_pendingを実行する前に行ってください。 設定で指定するには、"インプリメンテーション名"ThreadPolicyにpermethodあるいはpoolを設定します。"メソッドごとのスレッド方針"に設定する場合はpermethodを設定します。"プールスレッド方針"に設定する場合はpoolを設定します。具体的設定方法については [関連製品 > Object Broker Java TM > 運用ガイド > 1. 環境設定について] を参照してください。
TIEアプローチを使ったサーバプログラム
[オペレーションの実装] および [main関数の実装] ではIDLコンパイラが生成したスケルトンクラスを継承して実装オブジェクトクラスを定義しました。それに対して、スケルトンクラスを継承しない方法もあります。その1つの方法としてTIEアプローチがあります。 TIEアプローチでの実装オブジェクトはIDLで定義したオペレーションのみをもちます。また、スケルトンクラスで行っていた処理はIDLコンパイラが生成するTIEオブジェクトで行います。 次のIDLで定義したインタフェースをもつサーバプログラムをTIEアプローチを使って実装する方法を以下で説明します。
// IDL
interface MyInterface {
       void MyOp(in long arg);
       ...
};
パーシステントオブジェクトを持つサーバ
パーシステントオブジェクトは、LifespanPolicyにPERSISTENTをもつPOAがサーバントを活性化することにより作成されます。ルートPOA、および、create_POA関数でLifespanPolicyを指定しなかったときの方針はTRANSIENTです。以下にC++言語によるパーシステントオブジェクト作成の例を示します。
// IDL
interface MyInterface {
       void MyOp(in long arg);
       ...
};
// C++
// 実装オブジェクトクラス
class MyImpl : POA_MyInterface {
public:
       ...
       void MyOp(CORBA::Long, CORBA::Environment&);
       ...
};
 
main() {
       CORBA::ORB_var orb = CORBA::ORB_init(...);
       ...
      
       PortableServer::POA_ptr rootPOA = ... // ルートPOAの取得
 
       // LifespanPolicyとしてPERSISTENTをもつPOAを作成
       CORBA::PolicyList plist;
       plist.length(1);
       plist[0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);
      
       PortableServer::POA_ptr poa =
           rootPOA->create_POA("MyPOA", PortableServer::POAManager::_nil(), plist);
 
       // サーバントを作成
       MyImpl* svt = new MyImpl;
 
       // サーバントを活性化
       PortableServer::ObjectId_var oid = poa->activate_object(svt);
 
       // オブジェクトIDからオブジェクトリファレンスを取得
       CORBA::Object_var obj = poa->id_to_reference(*oid);
       ...
 
}

1.1.2. Object Broker C++サンプル

Object Broker C++が提供するサンプルプログラムの使用方法について説明します。
サンプルプログラムは、WebOTXマニュアルをインストールすると次の場所に格納されます。
    <サンプルインストールディレクトリ>\corba\obcpp.zip
zip圧縮形式でインストールされていますので、解凍ツールなどを利用して解凍後ご利用ください。 解凍後に生成されるobcppディレクトリに、サンプルプログラムをディレクトリごとに格納しています。
説明中の記述はWindowsの場合を示しています。UNIXの場合は、次のように読み替えてください。
また、以下でのビルド例で指定しているソリューションファイルは、VC++ 2005用のファイルです。VC++ .NET2003でのビルド時は、<project名>2003.slnを指定してください。
サンプルの実行前に、ObjectSpinnerサービスを起動させてください。名前サーバを動作させる設定が必要です。


1.1.2.1. 計算のサンプル (calc)

コマンドプロンプトを開き、ビルトを実行します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc
> devenv calcsrv.sln /build release
> devenv calccli.sln /build release
サーバプログラムを実行します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc\release
> calcsrv
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc\release
> calccli
got Calc Object Reference
1024 + 2048 = 3072
memory store 3072
1024 - 2048 = -1024
3.1415926 * 400 = 1256.64
memory recall = 3072
4096 / 365 = 11.2219
memory + 11.2219
memory recall = 3083.22
memory clear = 0
exiting..

> 
サーバプログラムを終了させるには、クライアントを起動する時の引数に"svstop"を指定します。 もしくは、サーバプロセスを終了させます。

1.1.2.2. 名前サーバを使用する計算のサンプル (calc2)

コマンドプロンプトを開き、ビルドを実行します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc2
> devenv regobj.sln /build release
> devenv calcsrv.sln /build release
> devenv calccli.sln /build release
別のコマンドプロンプトウィンドウを開き、インプリメンテーションの自動登録ツールregobjを用いて、calcsrvを登録します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc2\release
> regobj Calc Calc_i calcsrvのフルパス myobj
別のコマンドプロンプトを開き、クライアントプログラムを実行します。 サーバプログラムは自動起動され、出力として以下のように表示されます。
> cd <サンプルインストールディレクトリ>\corba\obcpp\calc2\release
> calccli myobj
1024 + 2048 = 3072
memory store 3072
1024 - 2048 = -1024
3.1415926 * 400 = 1256.64
memory recall = 3072
4096 / 365 = 11.2219
memory + 11.2219 
memory recall = 3083.22
memory clear = 0
exiting..

> 
サーバプログラムを終了させるには、クライアントを起動する時の引数に"svstop"を追加します。 もしくは、サーバプロセスを終了させます。

1.1.2.3. POAのサンプル (POA1-POA14)

サンプルの概要
サンプルプログラムは、名前と電話番号を管理する簡単なアドレス帳をシミュレーションしたもので、すべてのサンプルに共通なものです。 サーバが管理するアドレス帳に対して、クライアントは次のようなサービスを利用できます。
POAサンプルのクライアントプログラムは共通です。サーバのサンプルプログラム側で、様々なPOAのポリシーを使用した際の動作を確認することができます。 POA1からPOA14の各サンプルの概要は以下のとおりです。
表1.1.2.3-1
1.1.2.4. デフォルトでの使用例 (POA1) 全てデフォルトのPOAポリシーで動作するサンプルです。POAやServantを初期化時に準備します。
1.1.2.5. AdapterActivator使用例 (POA2) POAやServantをオペレーション呼出のタイミングで動的に生成するサンプルです。アダプタアクティベータ(AdapterActivator)機能を利用しています。
1.1.2.6. ServantActivator使用例 (POA3) Servantをオペレーション呼出のタイミングで動的に生成するサンプルです。サーバントマネージャ(ServantManager)機能を利用しています。
1.1.2.7. ServantLocator使用例 (POA4) Servantを動的に毎回生成するサンプルです。サーバントマネージャ(ServantManager)機能とNON_RETAINポリシーを利用しています。
1.1.2.8. USE_DEFAULT_SERVANTポリシー使用例 (POA5) ひとつのServantが複数のオブジェクトリファレンスに対応して動作するサンプルです。デフォルトサーバント(DefaultServant)機能とUSER_ID、MULTIPLE_IDポリシーを利用しています。
1.1.2.9. SINGLE_THREAD_MODELポリシー使用例 (POA6) ユーザが定義するServant、サーバントマネージャ(ServantManager)、アダプタアクティベータ(AdapterActivator)の処理がすべて1つのメインスレッド上で動作するサンプルです。SINGLE_THREAD_MODELポリシーを利用しています。
1.1.2.10. ORB_CTRL_ MODELポリシー使用例 (POA7) ユーザが定義するServant、サーバントマネージャ(ServantManager)、アダプタアクティベータ(AdapterActivator)の処理が、Object Brokerが管理する任意スレッド上で動作するサンプルです。ORB_CTRL_MODELポリシーを利用しています。
1.1.2.11. TRANSIENTポリシー使用例 (POA8) オブジェクトリファレンスの有効期間がPOAのライフサイクルと関係して動作するサンプルです。TRANSIENTポリシーを利用しています。
1.1.2.12. PERSISTENTオブジェクトの手動起動サーバでの実装例 (POA9) オブジェクトリファレンスの有効期間がPOAのライフサイクルとは関係なく動作するサンプルです。PERSISTENTポリシーを利用しています。
1.1.2.13. TRANSIENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA10) Servantの明示的な活性化を行わずに動作するサンプルです。TRANSIENT,IMPLICIT_ACTIVATIONポリシーを利用しています。
1.1.2.14. PERSISTENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA11) POA10と同様、Servantの明示的な活性化を行わずに動作するサンプルです。こちらはPERSISTENT,IMPLICIT_ACTIVATIONポリシーを利用しています。
1.1.2.15. POAManagerのサンプル (POA12) POAの状態に応じて動作するサンプルです。POA マネージャ(POA Manager)という機能を利用しています。
1.1.2.16. TIEアプローチのサンプル (POA13) POA1をPOAのTIEクラスで動作させるサンプルです。
1.1.2.17. 自動起動サーバのサンプル (POA14) POA9を自動起動サーバとして動作させるサンプルです。
各種機能の説明は、製品構成と提供機能の「3.提供機能」-「3.6.7.11. CORBA実行環境」-「3.6.7.11. CORBA実行環境」を参照してください。 このサンプルでは、次のIDL定義を使用します。
module AddressMapping {
   typedef string<43> AM_MAP;
   typedef sequence<AM_MAP,10> AM_MAPS;

   interface AddressMap_1 {
       attribute unsigned long map_num;
       boolean add(in string name, in string phone);
       boolean search(in string name, out AM_MAP map);
       boolean delete(in string name);
       boolean list(out AM_MAPS maps);
   };
};
このようにサンプルの機能自体は同じものですが、サーバを構成するPOAのポリシを変えることによって、その動作がどう異なるかを複数のサンプルによって実現しています。
クライアントプログラム
クライアントプログラムはすべてのサンプルに共通です。クライアントプログラムを起動すると、次のようなメニューを表示します。
Menu) 1.Get numbers of all. 
      2.Add address. 
      3.Delete address. 
      4.Search address. 
      5.List all. 
      6.Display object reference (& save to file:objref.dat).
      7.Obtain object reference again. 
      9.End. 
  Please select number?
1. は、アドレス帳の登録件数を表示します。
  Please select number? 1 
-------------------------- 
--> Get start. 
        Get number of all maps = 5
2. は、アドレス帳への登録を行います。メッセージに応じて、名前と電話番号を入力してください。
  Please select number? 2 
-------------------------- 
--> Add start. 
        name? sample1 
        phone? 111-1111 
      add() calling ..........OK.
3. は、アドレス帳からの削除を行います。メッセージに応じて、名前を入力してください。
  Please select number? 3 
-------------------------- 
--> Delete start. 
        name? sample1 
      delete() calling ..........OK. 
4. は、アドレス帳からの検索を行います。メッセージに応じて、名前を入力してください。
  Please select number? 4 
-------------------------- 
--> Search start. 
        name? sample12_3 
      search() calling ..........OK. 
         name / phone 
        ------------------------------------------- 
        sample12_3 / 333-3333 
5. は、アドレス帳に登録されている情報を一覧表示します。
  Please select number? 5 
-------------------------- 
--> List start. 
      list() calling ..........OK. 
         name / phone 
        ------------------------------------------- 
        Sample1 / 111-1111 
        Sample2 / 222-2222 
        Sample3 / 333-3333 
6. は、現在保持しているオブジェクトリファレンスを文字列に変換したものを表示します。また、カレントディレクトリに "objref.dat" という名前のファイルを出力します。
  Please select number? 6 
-------------------------- 
--> Display start.(local) 
Object reference: IOR:000000000000002249444c3a416464726573734d617070696e672f4164
64726573734d61703a312e300000000000000100000000000000a000010000000000087072696d65
72610004fc000000000088004e4f7262040100000000000000002249444c3a416464726573734d61
7070696e672f416464726573734d61703a312e30000000000000010000000000000000000000d083
84d0880000003c00504f4101000000000000072f6d79504f41000000000024004e504f4101000000
0000072f6d79504f41000000000000000000d08384d08800000000
7. は、新たにオブジェクトリファレンスを再取得します。
  Please select number? 7 
-------------------------- 
--> Obtain start.(local) 
サーバプログラムにおける注意点
PERSISTENTポリシを選択している場合、サーバ再起動後も同じアドレス帳にアクセスできるようになっています。このために、サーバが動作しているカレントディレクトリ配下に"address.dat"という名前のファイルに情報を常に保存しています。 再起動時にこのファイルをロードすることによって永続性を保っています。なお、初期状態に戻す場合は、サーバ起動前にファイルを削除してください。 また、複数クライアントからの見え方を確認するために、登録・削除5回毎に15秒間処理遅延が発生するようになっていますので注意してください。サンプル12に限っては、さらにPOA Managerの状態をHolding状態に遷移しています。
各サンプルのポリシー設定
各サンプルでは、異なるポリシーを設定しています。下表に示します。
表1.1.2.3-2
POAポリシー POAサンプル番号
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Thread Policy
ORB_CTRL_MODEL (既定値)
SINGLE_THREAD_MODEL
Lifespan Policy
TRANSIENT (既定値)
PERSISTENT
Object Id Uniqueness Policy
UNIQUE_ID ( 既定値)
MULTIPLE_ID
Id Assignment Policy
SYSTEM_ID (既定値)
USER_ID
Servant Retention Policy
RETAIN (既定値)
NON_RETAIN
Request Processing Policy
USE_ACTIVE_OBJECT_MAP_ONLY (既定値)
USE_SERVANT_MANAGER
USE_DEFAULT_SERVANT
Implicit Activation Policy
NO_IMPLICIT_ACTIVATION (既定値)
IMPLICIT_ACTIVATION

1.1.2.4. デフォルトでの使用例 (POA1)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_1.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース
特徴
サンプル1は、ActiveObjectMap のみを利用した形態です。 すべてデフォルトのポリシをもつPOA とServant を初期化時にあらかじめ生成し、Servant を活性化します。 一度活性化されたServant は、RETAIN ポリシによりActiveObjectMap に登録されますので、クライアントからのリクエスト時の動的な生成は起こりません。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA1のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA1
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: TRANSIENT
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時にServantが生成され、クライアントからのリクエスト時には動的に生成されていないことが分かります。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
===== AMapServant created.
          type: TRANSIENT
If you want to stop ServerAP, key quit!
===== AMapServant/add() start. [Thread name = 3]
        name = sample1, phone = 111-1111
===== AMapServant/add() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
quit.
goodbye...
===== AMapServer end.

1.1.2.5. AdapterActivator使用例 (POA2)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_2.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapAdapterActivator_2.cpp … AdapterAcrivatorクラスC++ソース
特徴
サンプル2は、AdapterActivator を利用した形態です。 サンプル1では初期化時にPOA、Servant をあらかじめ生成しておいたのに対して、サンプル2では初期化時には何も生成せず、rootPOA に対してAdapterActivator の登録のみ行っています。POA、Servant はクライアントからの最初のリクエスト時にAdapterActivator のunknown_adapter()で動的に生成され、活性化されます。 一度活性化されたServant は、RETAIN ポリシによりActiveObjectMap に登録されますので、以降のリクエスト時にはこのような動的な生成は起こりません。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA2のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA2
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されず、クライアントからの最初のリクエスト時に AdapterActivatorのunknown_adapter()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されることがないことも分かります。
>  server
===== AMapServer start. [Thread name = 3]
If you want to stop ServerAP, key quit!
===== AMapAdapterActivator/unknown_adapter() start. [Thread name = 3]
===== myPOA created.
===== AMapServant created.
          type: PERSISTENT
                sleeped 15sec per 5actions.
===== Loading start.
===== Loading end.
===== AMapAdapterActivator/unknown_adapter() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample2, phone = 222-2222
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
quit
goodbye...
===== AMapServer end.

1.1.2.6. ServantActivator使用例 (POA3)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_3.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスのC++ソース
特徴
サンプル3は、ServantManagerを利用した形態です。 サンプル1では初期化時にPOA、Servantをあらかじめ生成しておいたのに対して、サンプル3では初期化時にServantManager(ServantActivator)を登録したPOAのみを生成します。Servantはクライアントからの最初のリクエスト時にServantManager(ServantAcrivator)のincarnate()で動的に生成され、活性化されます。 一度活性化されたServantは、RETAINポリシによりActiveObjectMapに登録されますので、以降のリクエスト時にはこのような動的な生成は起こりません。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA3のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA3
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されておらず、クライアントからの最初のリクエスト時にServantActivatorのincarnate()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されることがないことも分かります。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
If you want to stop ServerAP, key quit!
===== AMapServantActivator/incarnate() start. [Thread name = 3]
===== AMapServant created.
          type: TRANSIENT
===== AMapServantActivator/incarnate() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample3, phone = 333-3333
===== AMapServant/add() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
quit
goodbye...
===== AMapServer end.

1.1.2.7. ServantLocator使用例 (POA4)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_4.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapServantLocator.cpp … ServantLocatorクラスのC++ソース
特徴
サンプル4は、NON_RETAINポリシでのServantManagerを利用した形態です。 初期化時にはServantManager(ServantLocator)を登録したPOAのみを生成します。 サンプル3では、Servantはクライアントからの最初のリクエスト時に動的に1回だけ生成され、活性化されたのに対して、サンプル4では毎回ServantManager(ServantLocator)のpreinvoke()で動的に生成され、活性化されます。 なぜなら、一度活性化されたServantも、NON_RETAINポリシによりActiveObjectMapに登録されないまま、ServantManager(ServantLocator)のpostinvoke()により消滅されるためです。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA4のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA4
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されておらず、クライアントからの最初のリクエスト時にServantLocatorのpreinvoke()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されていることも分かります。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
If you want to stop ServerAP, key quit!
===== AMapServantLocator/preinvoke() start. [Thread name = 3]
        For add operation.
===== AMapServant created.
          type: TRANSIENT
===== AMapServantLocator/preinvoke() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample4, phone = 444-4444
===== AMapServant/add() end.
===== AMapServantLocator/postinvoke() start. [Thread name = 3]
        For add operation.
===== AMapServantLocator/postinvoke() end.
===== AMapServantLocator/preinvoke() start. [Thread name = 3]
        For list operation.
===== AMapServant created.
          type: TRANSIENT
===== AMapServantLocator/preinvoke() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
===== AMapServantLocator/postinvoke() start. [Thread name = 3]
        For list operation.
===== AMapServantLocator/postinvoke() end.
quit
goodbye...
===== AMapServer end.

1.1.2.8. USE_DEFAULT_SERVANTポリシー使用例 (POA5)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_5.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース
特徴
サンプル5は、MULTIPLE_ID,USER_IDポリシでのDefaultServantを利用した形態です。 初期化時にはPOA、Servantを生成し、それをDefaultServantとして登録します。 クライアントからのリクエスト時にはそのDefaultServantが毎回対応することになります。また、ユーザ定義のObjectIdにより作成された複数のオブジェクトリファレンスにおけるリクエストも、同じDefaultServantが対応することになります。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA5のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA5
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。このサンプルでは、MULTIPLE_IDポリシーにより、1つのServantに対して2つのオブジェクトリファレンスを生成しています。 以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: TRANSIENT
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. (C) もう1つのクライアントプログラムを起動します。"-name AMapObj2"を付加して起動してください。これにより、異なるオブジェクトリファレンスを得られます。以下のメニューが出力されます。
    > server
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: TRANSIENT
    If you want to stop ServerAP, key quit!
    ===== AMapServant/add() start. [Thread name = 3]
            name = sample5, phone = 555-5555
    ===== AMapServant/add() end.
    Connect request accepted
    ===== AMapServant/list() start. [Thread name = 4]
    ===== AMapServant/list() end.
    quit
    goodbye...
    ===== AMapServer end.
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
  Please select number? 2
--------------------------
--> Add start.
        name? sample5
        phone? 555-5555
      add() calling ..........OK.
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
  Please select number? 5
--------------------------
--> List start.
      list() calling ..........OK.
         name / phone
        -------------------------------------------
        sample5 / 555-5555

1.1.2.9. SINGLE_THREAD_MODELポリシー使用例 (POA6)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_6.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapAdapterActivator_6.cpp … AdapterActivatorクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスC++ソース
特徴
サンプル6は、SINGLE_THREAD_MODELポリシにより,ユーザが定義するServant、ServantManager、AdapterActivatorがすべてメインスレッド上だけで実行される形態です。 初期化時には、parentPOAにAdapterActivatorを登録しておきます。クライアントからの最初のリクエスト時にAdapterActivatorのunknown_adapter()でmyPOAが生成され、myPOAにServantManagerが登録されます。つぎにmyPOAに登録したServantManagerのincarnate()でServantが生成され、そのServantは活性化されます。 また、このサンプルでは、サーバのメインスレッドでは、ORB.run()ではなく、ORB.work_pending()とORB.perform_work()を使用しています。これは、イベントループ処理の1つとしてORBの処理を実行させたいプログラマが使う関数です。そうでないプログラマは他のサンプル同様にORB.run()を使うのが便利です。 SINGLE_THREAD_POLICYの利点は、ユーザ定義コードがすべてメインスレッドで実行されるため、マルチスレッドを考慮しなくていいというところにあります。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA6のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA6
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。

1.1.2.10. ORB_CTRL_ MODELポリシー使用例 (POA7)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_7.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapAdapterActivator_7.cpp … AdapterActivatorクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスC++ソース
特徴
サンプル7は、ORB_CTRL_MODELポリシにより、ユーザが定義するServant,ServantManager,AdapterActivatorがWebOTX Object Broker C++が管理するスレッド上で実行される形態です。 初期化時には、rootPOAにAdapterActivatorを登録しておきます。クライアントからの最初のリクエスト時にAdapterActivatorのunknown_adapter()でPOAが生成され、そしてServantManagerが登録されます。これにより、Servantが生成され、活性化されます。 サーバのメインスレッドでは、ORB.run()を使用しています。これにより、ユーザ定義のコードはWebOTX Object Broker C++が管理するスレッドで実行されることになります。 従って、マルチスレッドを考慮したコーディングが必要であるといえます。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA7のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA7
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
  Please select number? 2
--------------------------
--> Add start.
        name? sample7
        phone? 777-7777
      add() calling ..........OK.
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5
  Please select number? 5
--------------------------
--> List start.
      list() calling ..........OK.
         name / phone
        -------------------------------------------
        sample7 / 777-7777
サーバのメッセージから、ユーザが定義したAdapterActivator、ServantActivater、Servantがすべてメインスレッド以外で実行されていることが分かります。また、別のクライアントからの要求が異なるスレッドで実行されていることが分かります。
> server
===== AMapServer start. [Thread name = 3]
If you want to stop ServerAP, key quit!
===== AMapAdapterActivator/unknown_adapter() start. [Thread name = 3]
===== myPOA created.
===== AMapAdapterActivator/unknown_adapter() end.
===== AMapServantActivator/incarnate() start. [Thread name = 3]
===== AMapServant created.
          type: PERSISTENT
                sleeped 15sec per 5actions.
===== Loading start.
===== Loading end.
===== AMapServantActivator/incarnate() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample7, phone = 777-7777
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServantActivator/incarnate() start. [Thread name = 4]
===== AMapServant created.
          type: PERSISTENT
                sleeped 15sec per 5actions.
===== Loading start.
===== Loading end.
===== AMapServantActivator/incarnate() end.
===== AMapServant/list() start. [Thread name = 4]
===== AMapServant/list() end.
quit
goodbye...
===== AMapServer end.

1.1.2.11. TRANSIENTポリシー使用例 (POA8)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_8.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスのC++ソース
特徴
サンプル8は、TRANSIENTポリシで動作する形態です。 TRANSIENTポリシとは、POAのライフタイムとオブジェクトリファレンスのライフタイムが同じであることを意味しています。よって、POAがdestroy()されると古いオブジェクトリファレンスではオブジェクトにアクセスできません。再度アクセスするには、新しいオブジェトリファレンスを取得しなければなりません。 また、このサンプルではServantActivatorも使っています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA8のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA8
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    If you want to stop ServerAP, key quit or refresh!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。サーバ(A)でPOAを作り直すには、"refresh"と入力します。クライアント(B)で新しいオブジェクトリファレンスを取得するには、7を入力します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)でオブジェクトリファレンスを表示します。
  Please select number? 6
--------------------------
--> Display start.(local)
Object reference: IOR:000000000000002249444c3a416464726573734d617070696e672f4164
64726573734d61703a312e300000000000000100000000000000a000010000000000087072696d65
7261000488000000000088004e4f7262040100000000000000002249444c3a416464726573734d61
7070696e672f416464726573734d61703a312e30000000000000010000000000000000000000d082
a60d300000003c00504f4101000000000000072f6d79504f41000000000024004e504f4101000000
0000072f6d79504f41000000000000000000d082a60d3000000000
サーバを再起動し、クライアント(B)でオブジェクトリファレンスを取得し、再度表示します。
  Please select number? 6
--------------------------
--> Display start.(local)
Object reference: IOR:000000000000002249444c3a416464726573734d617070696e672f4164
64726573734d61703a312e300000000000000100000000000000a000010000000000087072696d65
7261000491000000000088004e4f7262040100000000000000002249444c3a416464726573734d61
7070696e672f416464726573734d61703a312e30000000000000010000000000000000000000d082
a703480000003c00504f4101000000000000072f6d79504f41000000000024004e504f4101000000
0000072f6d79504f41000000000000000000d082a7034800000000
サーバを再起動する前と、再起動後に再取得したオブジェクトリファレンスが異なることが分かります。再取得前に古いオブジェクトリファレンスのままリクエストすると、以下のように例外が発生します。
  Please select number? 5
--------------------------
--> List start.
      list() calling .....error!!!
CORBA::NO_RESPONSE exception occurred. minor = 1186, completed = CORBA::COMPLETE
D_NO

1.1.2.12. PERSISTENTオブジェクトの手動起動サーバでの実装例 (POA9)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_9.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスのC++ソース
特徴
サンプル9は、PERSISTENTポリシで動作する形態です。 内容については、サンプル8と同様です。 PERSISTENTポリシとは、POAやサーバが終了してもオブジェクトリファレンスは有効であることを意味しています。よって、POAが一度削除され再び生成されても、クライアントは古いオブジェクトリファレンスをそのまま使用してオブジェクトにアクセスできます。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA9のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA9
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。xxxxにはサーバのポート番号を指定してください。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    If you want to stop ServerAP, key quit or refresh!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。サーバ(A)でPOAを作り直すには、"refresh"と入力します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。

1.1.2.13. TRANSIENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA10)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_10.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース
特徴
サンプル10は、TRANSIENTポリシとIMPLICIT_ACTIVATIONポリシをもつ形態です。 この場合、Servantの明示的な活性(activate_object()により活性化する)を行わなくとも、servant_to_reference()を使用するだけで暗黙のうちに活性化が行われますので、クライアントからのリクエスト時に意図するServantに対応づけられることになります。 また、TRANSIENTの場合には、UNIQUE_IDでもMULTIPLE_IDでも指定できます。このサンプルではMULTIPLE_IDを指定していますので、同じServantに2個のオブジェクトリファレンスを対応づけています。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA10のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA10
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: TRANSIENT
    ===== AMapServant's object reference created by servant_to_reference().
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. (C) もう1つのクライアントプログラムを起動します。"-name AMapObj2"を付加して起動してください。これにより、異なるオブジェクトリファレンスを得られます。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj2
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
  Please select number? 2
--------------------------
--> Add start.
        name? sample10
        phone? 101-0101
      add() calling ..........OK.
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
  Please select number? 5
--------------------------
--> List start.
      list() calling ..........OK.
         name / phone
        -------------------------------------------
        sample10 / 101-0101
サーバのメッセージから、初期化時にservant_to_reference()を使用するだけで暗黙のうちにServantは活性化されており、クライアントからのリクエスト時には明示的な活性の場合と同様に処理されることが分かります。また、異なるオブジェクトリファレンスによるリクエストでも同じServantが対応しますので、2つのクライアントが同じアドレス帳を参照・更新していることが分かります。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
===== AMapServant created.
          type: TRANSIENT
===== AMapServant's object reference created by servant_to_reference().
If you want to stop ServerAP, key quit!
===== AMapServant/add() start. [Thread name = 3]
        name = sample10, phone = 101-0101
===== AMapServant/add() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
quit
goodbye...
===== AMapServer end.

1.1.2.14. PERSISTENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA11)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_11.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース
特徴
サンプル11は、PERSISTENTポリシとIMPLICIT_ACTIVATIONポリシをもつ形態です。 この場合も、サンプル10と同様に暗黙のうちに活性化が行われます。 また、PERSISTENTの場合には、MULTIPLE_IDは指定できませんので、このサンプルではUNIQUE_IDを指定しています。 また、サンプル9同様に、手動起動サーバでPERSISTENTポリシのオブジェクトを実装します。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA11のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA11
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。xxxxにはサーバのポート番号を指定してください。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: PERSISTENT
                    sleeped 15sec per 5actions.
    ===== Loading start.
    ===== Loading end.
    ===== AMapServant's object reference created by servant_to_reference().
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
初期化時にservant_to_reference()を使用するだけで暗黙のうちにServantは活性化されており、クライアントからのリクエスト時には明示的な活性化の場合と同様に処理されることが分かります。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
===== AMapServant created.
          type: PERSISTENT
                sleeped 15sec per 5actions.
===== Loading start.
===== Loading end.
===== AMapServant's object reference created by servant_to_reference().
If you want to stop ServerAP, key quit!
===== AMapServant/add() start. [Thread name = 3]
        name = sample11, phone = 111-1111
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/list() start. [Thread name = 3]
===== AMapServant/list() end.
quit
goodbye...
===== AMapServer end.

1.1.2.15. POAManagerのサンプル (POA12)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_12.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース
特徴
サンプル12は、POA Managerを利用した形態です。 POA Managerの状態をHolding状態にすることで、クライアントからのリクエストがキューイングされます。再度、Activeにすることでリクエストの処理が再開します。 サンプルで提供しているServantは、登録あるいは削除のオペレーション5回毎にPOA Managerを15秒間Holding状態にします。これにより、擬似的に処理遅延(sleep)が起こり、この間に別なクライアントからリクエストが届いても、リクエストが保留されます。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA12のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA12
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: PERSISTENT
                    sleeped 15sec per 5actions.
    ===== Loading start.
    ===== Loading end.
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
サーバは、次のように動作します。
> server
===== AMapServer start. [Thread name = 3]
===== myPOA created.
===== AMapServant created.
          type: PERSISTENT
                sleeped 15sec per 5actions.
===== Loading start.
===== Loading end.
If you want to stop ServerAP, key quit!
===== AMapServant/add() start. [Thread name = 3]
        name = sample12_1, phone = 111-1111
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample12_2, phone = 222-2222
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample12_3, phone = 333-3333
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample12_4, phone = 444-4444
===== Saving start.
===== Saving end.
===== AMapServant/add() end.
===== AMapServant/add() start. [Thread name = 3]
        name = sample12_5, phone = 555-5555
===== Saving start.
        Holding(15sec.).....end.
        +-------------------------------------------------------------
        |※この間に受け付けたクライアント(C)からの要求は15秒間、
        |  待たされます。
        +-------------------------------------------------------------
===== AMapServant/list() start. [Thread name = 4]
===== AMapServant/list() end.
===== Saving end.
===== AMapServant/add() end.
quit
goodbye...
===== AMapServer end.

1.1.2.16. TIEアプローチのサンプル (POA13)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_1_tie.cpp … サーバプログラムC++ソース AMapServant_tie.cpp … DelegateクラスC++ソース
特徴
サンプル13は、サンプル1をPOAのTIEクラスを使用して作成したものです。 サーバ側のオブジェクトの作成および登録の方法が若干異なる以外は、動作はサンプル1と同じとなります。 AMapServant_tie.cppは、各メソッドの処理はAMapServant.cppと同じですが、AddressMapOperationsを実装している点が異なっています。 また、AMapServer_1_tie.cppは、POA_AddressMap_tieクラス作成し、これをPOAに登録しています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA13のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA13
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    ===== AMapServer start. [Thread name = 3]
    ===== myPOA created.
    ===== AMapServant created.
              type: TRANSIENT
    If you want to stop ServerAP, key quit!
    
以降は、POA1と同じです。

1.1.2.17. 自動起動サーバのサンプル (POA14)

提供されるもの
AddressMap.idl … インタフェース定義IDLソース AMapClient.cpp … クライアントプログラムC++ソース AMapServer_14.cpp … サーバプログラムC++ソース AMapServant.cpp … ServantクラスC++ソース AMapServantActivator.cpp … ServantActivatorクラスのC++ソース regobj.cpp … インプリメンテーション登録ツールのソース
特徴
サンプル14は、サンプル9を自動起動サーバとして改造したものです。 自動起動サーバのオブジェクトリファレンスを生成するには、インプリメンテーション名を指定する必要があります。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA14のディレクトリに移動します。
    > cd <サンプルインストールディレクトリ>\corba\obcpp\POA14
    
  3. (A) ビルドを実行します。
    > devenv server2005.sln /build release
    > devenv client2005.sln /build release
    > devenv regobj2005.sln /build release
    
  4. インプリメンテーションを登録します。
    > regobj AddressMapping/AddressMap AMapServant serverのフルパス AMapObj
    

    Caution serverのフルパスで指定したディレクトリにサンプル14のserverのデータファイルaddress.dat)が出力されます。このディレクトリには、oadを起動したユーザの書き込み許可が必要です。

  5. クライアントプログラムを起動します。以下のメニューが出力されます。
    ===== AMapClient started. =====
            target = AMapObj
    --------------------------
    Menu) 1.Get numbers of all.
          2.Add address.
          3.Delete address.
          4.Search address.
          5.List all.
          6.Display object reference (& save to file:objref.dat).
          7.Obtain object reference again.
          9.End.
      Please select number?
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. メニューで9を入力し、クライアントプログラムを終了します。これにより自動的にサーバも終了します。

1.1.2.18. valuetypeのサンプル (value1-value4)

実行方法は、value1-value4の各サンプルで共通です。ここでは、value1の実行方法を説明します。 コマンドプロンプトを開き、ビルドを実行します。
> cd <サンプルインストールディレクトリ>\corba\obcpp\value1
> devenv val1server2005.sln /build release
> devenv val1client2005.sln /build release
サーバプログラムを実行します。
> Val1Server
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> Val1Client
valuetypeの使用例(value1)


図1.1.2.18-1

valuetypeの使用例(value2)


図1.1.2.18-2

valueboxの使用例(value3)
あるデータ型(long,struct等)をvalueboxとして定義することにより、valueがもつnullや共有の概念を取り込むことができます。 このサンプルは、共有の概念を持たないstruct型をvalueboxとして定義することによる復元の差異を確認できます。


図1.1.2.18-3


図1.1.2.18-4

abstract interfaceの使用例 (value4)
abstract interfaceを定義し、その型をオペレーションのパラメタに指定すると、そのabstract interfaceを継承するinterfaceかvalueかを動的に切り換えて指定できるようになります。 このサンプルは、クライアントがサーバから取得したabstract interface型のオブジェクトに対してオペレーションを実行し、その差異を確認できます。

1.1.3. JavaでCORBAアプリケーションを作成する

JavaでCORBAアプリケーションを作成する手順は以下のとおりです。
  1. オブジェクトが提供するインタフェースを決める。
  2. インタフェース定義言語(Interface Definition Language : IDL)を用いてインタフェースを定義する。
  3. IDL定義をIDLコンパイラにかける。
  4. 定義したインタフェースについて、サーバの実装コードを記述する。
  5. Calcオブジェクトを呼び出すクライアントアプリケーションのコードを記述する。
  6. Javaコンパイラでクライアントとサーバのアプリケーションをビルドする。
  7. アプリケーションを実行する。
インタフェース定義
はじめにIDLを用いてインタフェースの定義を行います。ここでは例としてCalcという演算オブジェクト(単純にするために足し算のみをサポートしたオブジェクト)を定義します。このアプリケーションはクライアントから2つのlong型の値を受け取り、受け取った2つの値の和をクライアントに対してlong型で返します。Calcのインタフェース定義は以下のようになります。
calc.idl
module Calculator {
    interface Calc {
        long add(in long arg1, in long arg2);
    };
};
Calcインタフェースに定義されたaddメソッドをみてください。"in long arg1", "in long arg2"という2つの引数が定義されています。"in"という宣言は、これらの引数がオブジェクトに渡されることを意味しています。addメソッドの戻り値の型はlong型です。IDL定義にはインタフェースだけを定義し、実装コードは記述しません。IDLの表記方法はC++に似ていますので、IDLを習得するのは容易です。
IDL定義のコンパイル
WebOTX Object Broker Java TM IDLコンパイラであるi2jはIDL定義をもとにJavaソースコードを生成します。i2jを使うにはコマンド行で、以下のように入力してください。
> i2j calc.idl
コマンドを実行すると下記のファイルが作成されます。
生成されたJavaソースファイル
i2jが生成したいくつかのファイルは、IDL定義のモジュール名と同じCalculatorというサブディレクトリに格納されます。IDLのモジュール定義は、Javaのパッケージにマッピングされ、インタフェース/クラスはすべてCalculatorパッケージ内に置かれます。
Calc.java
Calcインタフェースが生成されます。このインタフェースは以下のCalcOperationsを継承しています。
CalcHelper.java
CalcHelperクラスが生成されます。HelperクラスはAny型への挿入と取り出し、ストリームからの読み込みと書き出しに使われます。
CalcHolder.java
CalcHolderクラスが生成されます。Holderクラスはout/inout引数のときに使われます。
CalcOperations.java
IDLで定義したインタフェースがCalcOperationsとして生成されます。
CalcPOA.java
CalcPOAクラスが生成されます。このクラスはサーバアプリケーションの実装に使われます。
_CalcStub.java
_CalcStubが生成されます。Stubクラスはクライアントの実装に使われます。このクラスをアプリケーションから直接使うことはできません。
サーバアプリケーション
サーバアプリケーションコードCalcServerを示します。このプログラムは次の手順で処理されます。
ORBの初期化
ORBの初期化とORBオブジェクトの獲得をORBクラスのinitメソッドによって行います。initメソッドはいくつかのオーバーロードされた形式を持っています。init(String[], Property)ではプログラムに渡されたargs引数を指定します。
POAオブジェクトの取得
サーバの実装には、POAオブジェクトのインタフェースを使用します。POAオブジェクトの取得は、ORBオブジェクトに対して、resolve_initial_references("RootPOA")を発行することによって行います。
オブジェクトの作成
クライアントからの要求を処理するJavaオブジェクトを作成します。オブジェクトの作成は単にnewを使用して行うだけです。作成するオブジェクトのクラスはリスト2で示したようにCalcPOAクラスを継承します。
作成したオブジェクトとORBの関連付け
JavaオブジェクトをORBインスタンスと関連付けます。
名前サーバのオブジェクトリファレンスの獲得
resolve_initial_referencesに"NameService"を渡すと名前サービスのルートコンテキストが返ります。
作成したオブジェクトと名前を関連付けるNameComponentの生成
名前サービスを用いてオブジェクトの名前を指定するにはNameComponent型のシーケンスを使用します。このサンプルでは、"CalcObj"という名前で、ルートの名前コンテキストにオブジェクトを登録します。
名前サーバへの登録
この例ではrebindという名前コンテキストのメソッドを使います。rebindは、名前コンテキスト内に登録しようとする名前と同じ名前のものが登録されていたときにも登録に成功します。bindメソッドは同一名が存在したときには例外を返します。
POAManagerオブジェクトの活性化
クライアントからの要求を受け付けられるように,POAManagerオブジェクトをactivateします。これを実行しないと、クライアントからの要求は受け付けられません。
クライアントからの要求処理ループの実行
クライアントからの要求は、run()メソッドを実行することにより処理されます。
CalcObjクラスは、Calcインタフェースを実装しているクラスです。このクラス宣言は通常のJavaのクラス宣言となんら変わりません。唯一の規則はスケルトンクラス(このソースコード例ではCalcPOA)を継承することです。

Caution メソッドのシグネチャはスケルトンクラスで定義されているメソッドと同じものにしてください。スケルトンのメソッドはabstractと宣言されているので、メソッドの実装を忘れたり、違うシグネチャで実装してしまうとコンパイルエラーになります。

CalcServer.java
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import Calculator.*;
 
// Calcインタフェースの実装
class CalcObj extends CalcPOA {
  public int add(int arg1, int arg2) {
    System.out.println("add called!");
    System.out.println("arg1="+arg1+",arg2="+arg2);
    return arg1 + arg2;
  }
}

public class CalcServer {
  public static void main(String args[]) {
    // Object Broker Java を使用するためのシステムプロパティ設定
       
    System.setProperty("org.omg.CORBA.ORBClass", "jp.co.nec.orb.OSPORB");
       
    System.setProperty("org.omg.CORBA.ORBSingletonClass", "jp.co.nec.orb.OSPORBSingleton");
 
    try {
      // ORBの初期化
      ORB orb = ORB.init(args, null);
 
      // POAオブジェクトの取得
      POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));

      // Calcインタフェースの実装オブジェクトの生成
      CalcObj target = new CalcObj();
 
      // 実装オブジェクトとORBを関連付け、オブジェクトリファレンスを取得
      org.omg.CORBA.Object target_ref = poa.servant_to_reference(target);
 
      // 名前サービスのオブジェクトリファレンスを獲得
      org.omg.CORBA.Object o = orb.resolve_initial_references("NameService");
      NamingContext ns = NamingContextHelper.narrow(o);
 
           
      // 作成したオブジェクトと名前を関連付けるNameComponentの生成
      NameComponent ncseq[] = {
        new NameComponent("CalcObj", "")
      };
 
      // 名前サーバへの登録
      ns.rebind(ncseq, target_ref);
 
      // POAManagerオブジェクトの活性化
      POAManager poamgr = poa.the_POAManager();
      poamgr.activate();

      // クライアントからの要求処理ループの実行
      orb.run();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
クライアントアプリケーション
クライアントアプリケーションCalcClientのソースコードを示します。このプログラムは次の手順で処理されます。
ORBの初期化
ORBの初期化とORBオブジェクトの獲得をORBクラスのinitメソッドによって行います。initメソッドはいくつかのオーバーロードされた形式を持っています。init(String[], Property)ではプログラムに渡されたargs引数が使われます。これはサーバアプリケーションと同じです。
名前サービスのルートコンテキストのオブジェクトリファレンスの獲得
resolve_initial_referencesに"NameService"を渡すと名前サービスのルートコンテキストのオブジェクトリファレンスが返ります。
Calcオブジェクトと名前を関連付けるNameComponentの生成
名前サービスを用いてオブジェクトの名前を指定するにはNameComponent型のシーケンスを使用します。このサンプルでは、サーバオブジェクトは"CalcObj"という名前で登録されています。
名前の検索とCalcオブジェクトのオブジェクトリファレンスの獲得
名前コンテキストのresolveメソッドは名前を検索して名前と関連付けられているオブジェクトリファレンスを獲得します。このサンプルでは、サーバアプリケーションによって関連付けられたCalcオブジェクトのオブジェクトリファレンスを得ることができます。
Calcインタフェース型への変換
resolveが返すオブジェクトリファレンスはorg.omg.CORBA.Objectという全てのCORBAオブジェクトに共通な基底クラスになっています。したがって、Calcインタフェースのオペレーションを実行する前に、オブジェクトリファレンスの型を共通な基底クラスからCalcに変換しなければなりません。これを行うには、IDLコンパイラによって自動生成されたCalcHelperクラスのnarrowメソッドを用います。
addメソッドの実行
一度特定の型にnarrowによって変換されたオブジェクトリファレンスは、あたかも通常のJavaメソッドであるかのようにメソッドを実行することができます。narrowによって変換して得られたオブジェクトは、実際には_CalcStub型です。クライアント側にあるスタブオブジェクトはサーバアプリケーション内にある実オブジェクトのプロキシ(Proxy : 代理の意)です。スタブはメソッドの引数をマーシャル(ある規則にしたがったバイト列に変換すること)してバッファにたくわえ、そのバッファの内容をサーバに転送します。また、サーバから戻り値やout/inout引数を受信するとアンマーシャル(バイト列をもとの型に戻すこと)を行い、呼び出し側に結果を返します。つまり、_CalcStubはCalcインタフェースと同じメソッドをもち、Calc型と同等に扱えるのです。なお、_CalcStubクラスをプログラム中で直接使用してはいけません。直接使用すると、プログラムの移植性が失われます。
CalcClient.java
import org.omg.CORBA.*; 
import org.omg.CosNaming.*; 
import Calculator.*; 
  
public class CalcClient { 
  public static void main(String args[]) { 
    // Object Broker Java を使用するためのシステムプロパティ設定 
    System.setProperty("org.omg.CORBA.ORBClass", "jp.co.nec.orb.OSPORB"); 
    System.setProperty("org.omg.CORBA.ORBSingletonClass", "jp.co.nec.orb.OSPORBSingleton"); 
  
    try { 
      // ORBの初期化 
      ORB orb = ORB.init(args, null); 
  
      // 名前サービスのオブジェクトリファレンスを獲得 
      org.omg.CORBA.Object o = orb.resolve_initial_references("NameService"); 
      NamingContext ns = NamingContextHelper.narrow(o); 
  
      // Calcオブジェクトと名前を関連付けるNameComponentの生成 
      NameComponent nc = new NameComponent("CalcObj", ""); 
      NameComponent ncseq[] = {nc}; 
  
      // 名前の検索とCalcオブジェクトのオブジェクトリファレンスの獲得 
      // Calcインタフェース型への変換 
      Calc calcobj = CalcHelper.narrow(ns.resolve(ncseq)); 

      // addメソッドの実行 
      int ret = calcobj.add(1, 1); 
      System.out.println("1+1=" + ret); 
    }  catch (Exception e) { 
      System.out.println("ERROR : " + e) ; 
      e.printStackTrace(System.out); 
    } 
  } 
} 
プログラムのビルド
クライアントとサーバのプログラムを書き終えたら、次のコマンドによって、アプリケーションをビルドします。calc.idlが置かれているディレクトリに移動していると仮定します。
> javac CalcServer.java CalcClient.java Calculator\*.java
このコマンドは、クライアントとサーバの両方のアプリケーションをビルドします。

Caution コンパイルを行う前に、CLASSPATH環境変数にWebOTX Object Broker Javaのクラスライブラリが含まれているかを確認してください。

サーバアプリケーションの実行
次のコマンドでサーバアプリケーションを実行します。
> java CalcServer
作成したサーバやクライアントを実行する前に、WebOTX Object Brokerを起動しなければなりません。もし、起動されていなければエラーになります。上記のコマンドはWebOTX Object Brokerがデフォルトの設定で動作している場合を示しています。もし、WebOTX Object Brokerの設定をデフォルトから変更して動作させている場合は、特別な引数が必要になります。 このプログラムは自動的には終了しません。終了させるときはCTRL-Cをタイプして終了させてください。
クライアントアプリケーションの実行
次のコマンドでクライアントアプリケーションを実行します。
> java CalcClient
1+1=2
クライアントプログラムはサーバオブジェクトのaddメソッドの2つのパラメータにそれぞれ「1」を渡します。サーバはリクエストを受け取り、「2」を返します。クライアントは結果を表示します。 サーバはaddメソッドが呼ばれるたびにサーバが動作しているウィンドウ上に下記のメッセージを表示します。
Add called!
arg1=1,arg2=1
TIEサーバアプリケーション
ここまでは、スケルトンクラス(CalcPOA)を継承してサーバアプリケーションを作成する方法について述べました。実際のアプリケーション開発では、サーバオブジェクトに別のクラスを継承させたい場合もあります。しかし、Java言語は多重継承を許していないため、スケルトンクラスと別のクラスを同時に継承させることができません。このような場合のために、サーバオブジェクトにスケルトンクラスを継承させない方法を用意しています。次に、そのリストを示します。 スケルトンクラスを継承する方法とは、次の点が異なります。
TIEオブジェクトは、CalcPOAを継承する方法での実装オブジェクトのかわりに使用することが可能です。TIEクラスを生成するにはIDLコンパイル時に-tieオプションを指定してください。以下にTIEサーバアプリケーションの例を示します。
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import Calculator.*;
 
// Calcインタフェースの実装
class CalcObj extends CalcPOA {
  public int add(int arg1, int arg2) {
       
    System.out.println("add called!");
       
    System.out.println("arg1="+arg1+",arg2="+arg2);
    return arg1 + arg2;
  }
}
 
public class CalcServer {
  public static void main(String args[]) {
    // Object Broker Java を使用するためのシステムプロパティ設定
    System.setProperty("org.omg.CORBA.ORBClass", "jp.co.nec.orb.OSPORB");
    System.setProperty("org.omg.CORBA.ORBSingletonClass", "jp.co.nec.orb.OSPORBSingleton");
 
    try {
      // ORBの初期化
      ORB orb = ORB.init(args, null);

      // POAオブジェクトの取得
      POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));

      // Calcインタフェースの実装オブジェクトの生成
      CalcObj obj = new CalcObj();
      
      // TIEオブジェクトの生成
      CalcPOATie target  = new CalcPOATie(obj);
 
      // 実装オブジェクトとORBを関連付け、オブジェクトリファレンスを取得
      org.omg.CORBA.Object target_ref = poa.servant_to_reference(target);
 
      // 名前サービスのオブジェクトリファレンスを獲得
      org.omg.CORBA.Object o = orb.resolve_initial_references("NameService");
      NamingContext ns = NamingContextHelper.narrow(o);
 
      // 作成したオブジェクトと名前を関連付けるNameComponentの生成
      NameComponent ncseq[] = {
        new NameComponent("CalcObj", "")
      };
 
      // 名前サーバへの登録
      ns.rebind(ncseq, target_ref);
 
      // POAManagerオブジェクトの活性化
      POAManager poamgr = poa.the_POAManager();
      poamgr.activate();
 
      // クライアントからの要求処理ループの実行
      orb.run();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
自動起動サーバアプリケーション
ここまでで説明したサーバアプリケーション生成されるオブジェクトは、トランジェント(非永続)オブジェクトといわれるものです。トランジェントオブジェクトとは、サーバプロセスが起動している間だけ有効であるオブジェクトです。サーバプロセスが終了してしまうと、再起動したとしても、新たなサーバプロセスでクライアントからの要求が処理されることはありません。これは、サーバプロセスが終了した時に、オブジェクトも消滅しているためです。トランジェントオブジェクトのオブジェクトリファレンスは、サーバが起動している間だけ有効であり、サーバが終了してしまうと、そのオブジェクトリファレンスを使用して呼び出しを行うことはできません。 これに対して、サーバプロセスが終了してもオブジェクトが消滅しないようにする必要がある場合も多くあります。このようなオブジェクトはパーシステント(永続)オブジェクトと呼びます。サーバプロセスが終了しても、クライアントからパーシステントオブジェクトを使用して呼び出しを実行することにより、サーバプロセスを自動的に起動させることができます。パーシステントオブジェクトを利用したサーバプログラムを示します。
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import Calculator.*;
 
// Calcインタフェースの実装
class CalcObj extends CalcPOA {
  public int add(int arg1, int arg2) {
       
    System.out.println("add called!");
       
    System.out.println("arg1="+arg1+",arg2="+arg2);
        return arg1 + arg2;
    }
}
 
public class CalcServer {
  public static void main(String args[]) {
    // Object Broker Java を使用するためのシステムプロパティ設定
    System.setProperty("org.omg.CORBA.ORBClass", "jp.co.nec.orb.OSPORB");
       
    System.setProperty("org.omg.CORBA.ORBSingletonClass", "jp.co.nec.orb.OSPORBSingleton");
 
    try {
      // ORBの初期化
      ORB orb = ORB.init(args, null);
 
      // POAオブジェクトの取得
      POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
           
      // POAポリシーの作成。
      // パーシステント、かつオブジェクトIDをプログラマが指定。
           
      Policy plist[] = {
        poa.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),
        poa.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID)
      };
 
      POAManager pmgr = poa.the_POAManager();
 
           
      // ポリシーに基づいて新たなPOAを作成
      poa = poa.create_POA("mypoa", pmgr, plist);
 
      // Calcインタフェースの実装オブジェクトの生成
      CalcObj target = new CalcObj();
 
      // オブジェクトIDの生成
      byte[] oid = "MyCalcObj".getBytes("8859_1");
 
      if (args.length == 1 && args[0].equals("create")) {
        // プログラムの引数に"create"と指定されたら
        // オブジェクトリファレンスを作成し、名前サーバに登録して終了する。
        org.omg.CORBA.Object calcref = 
          poa.create_reference_with_id(oid, "IDL:Calculator/Calc:1.0");
 
        // 名前サービスのオブジェクトリファレンスを獲得
        org.omg.CORBA.Object o = orb.resolve_initial_references("NameService");
        NamingContext ns = NamingContextHelper.narrow(o);
 
        // 作成したオブジェクトと名前を関連付けるNameComponentの生成
        NameComponent ncseq[] = {
          new NameComponent("CalcObj", "")
        };
 
        // 名前サーバへの登録
        ns.rebind(ncseq, calcref);
      } else {
        // 上記以外は、オブジェクトを活性化する。
        // オブジェクトIDを指定してオブジェクトを活性化
        poa.activate_object_with_id(oid, target);
 
        // POAManagerオブジェクトの活性化
        pmgr.activate();
 
        // クライアントからの要求処理ループの実行
        orb.run();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
このプログラムでは、実行時の引数に"create"を指定して起動した時にオブジェクトリファレンスを作成し、名前サービスに登録しています。オブジェクトリファレンスの生成には、create_reference_with_idを使用します。create_reference_with_idには、オブジェクトIDとリポジトリIDを渡します。実行時の引数に何も指定せずに起動した時には、作成する時と同じオブジェクトIDを使用して、オブジェクトを活性化しています。オブジェクトの活性化はactivate_object_with_idを使用します。活性化した後で、要求処理ループを実行しています。
クライアントアプレット
最後にクライアントをアプレットで実装する場合のJavaソースコードを示します。基本的にはクライアントアプリケーションと同じ手順ですが、次の点が異なります。
ORBの初期化
ORBの初期化とORBオブジェクトの獲得をORBクラスのinitメソッドによって行います。initメソッドはいくつかのオーバーロードされた形式を持っています。init(Applet, Property)ではアプレット自身が第1パラメータに使われます。
プログラムのビルドも、クライアントアプリケーションと同じ手順です。
CalcApplet.java
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import java.awt.Gaphics;
import Calculator.*;
 
public class CalcApplet extends java.applet.Applet {
  String message = "";
 
  public void init() {
    try {
      // ORBの初期化
      ORB orb = ORB.init(this, null);
 
      // 名前サービスのオブジェクトリファレンスを獲得
      org.omg.CORBA.Object o =
        orb.resolve_initial_references("NameService");
           
      NamingContext ns = NamingContextHelper.narrow(o);
 
      // Calcオブジェクトと名前を関連付けるNameComponentの生成
      NameComponent nc = new NameComponent("CalcObj", "");
      NameComponent ncseq[] = {nc};
 
      // 名前の検索とCalcオブジェクトのオブジェクトリファレンスの獲得
      // Calcインタフェース型への変換
      Calc calcobj = CalcHelper.narrow(ns.resolve(ncseq));
 
      // addメソッドの実行
      int ret = calcobj.add(1, 1);
 
      message = "1+1=" + ret;
    } catch (Exception e) {
      message = "ERROR : " + e.toString();
      e.printStackTrace(System.out);
    }
  }
  public void paint(Graphics g) {
    g.drawString(message, 25, 50);
  }
}
アプレットを実行するためにはHTMLファイルが必要です。
CalcApplet.htm
<html>
 
<head>
<title>Calc Applet</title>
</head>
 
<body>
<applet codebase='.' code='CalcApplet.class' width=400 height=400 archive=ospiorb50.jar,ospiname50.jar>
 
// 次のパラメタは環境に合わせて変更してください。
<param name=org.omg.CORBA.ORBInitialHost value=webserverhostname>
 
// 次のパラメタはこのまま指定します。
<param name=org.omg.CORBA.ORBClass value=jp.co.nec.orb.OSPORB>
<param name=org.omg.CORBA.ORBSingletonClass value=jp.co.nec.orb.OSPORBSingleton>
 
</applet>
</body>
 
</html>
この例では、リストの<applet>タグに含まれているarchiveに、WebOTX Object Broker Javaのクラスライブラリを指定しています。上記の例は、Object Broker Javaのクラスライブラリが、アプレットのクラスファイルと同じ場所にある場合の設定ですので、実際の環境に合わせて変更してください。ORBInitialHostはWebサーバのホスト名です。このホストで、WebOTX Object Brokerが動作している必要があります。 appletviewerを使用する場合、次のコマンドで起動します。
> appletviewer http://webserverhostname/?/CalcApplet.htm


図1.1.3-1

1.1.4. Object Broker JavaTM サンプル

ObjectBroker Java TM が提供するサンプルプログラムの使用方法について説明します。
サンプルプログラムは、WebOTXマニュアルをインストールすると次の場所に格納されます。
    <サンプルインストールディレクトリ>\corba\objava.zip
zip圧縮形式でインストールされていますので、解凍ツールなどを利用して解凍後ご利用ください。 解凍後に生成されるobjavaディレクトリに、サンプルプログラムをディレクトリごとに格納しています。
説明中のディレクトリ記述はWindowsの場合を示しています。UNIXの場合は、次のように読み替えて下さい。
サンプルの実行前に、ObjectSpinnerサービスを起動させてください。名前サーバを動作させる設定が必要です。
以降ではサンプルインストール先に "C:\Program Files\NEC\WebOTX\samples" を指定した場合について説明します。

1.1.4.1. 足し算のサンプル (calc1)

コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\calc1
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc1Server
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\calc1
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc1Client
0+0=0
1+1=2
2+2=4
3+3=6
4+4=8
5+5=10
6+6=12
7+7=14
8+8=16
9+9=18
サーバプログラムは自動的には終了しませんので、Ctrl+C などで終了させてください。

1.1.4.2. 名前サーバを使用する足し算のサンプル (calc2)

コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\calc2
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc2Server
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\calc2
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc2Client
1+1=2
サーバプログラムは自動的には終了しませんので、Ctrl+C などで終了させてください。

1.1.4.3. 構造体などの複雑な型を使用するサンプル (example)

コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\example
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB CplxServer
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\example
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB CplxClient
ret.l=2
ret.s=HelloWorld
a2.l=2
a2.s=HelloWorld
a3.l=2
a3.s=HelloWorld
サーバプログラムは自動的には終了しませんので、Ctrl+C などで終了させてください。

1.1.4.4. アプレットのサンプル (applet)

C:\Program Files\NEC\WebOTX\samples\corba\objava\applet\CalcApplet.htmのcodebase、archive、ポート設定などを適切に変更し、Webサーバに登録します。 コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\applet
> make
Calc2で使用したサーバプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\calc2
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc2Server
AppletViewerでURLを指定して実行します。
> appletviewer http://・・・/CalcApplet.htm

1.1.4.5. サーバプログラムのサンプル (serversamp)

コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\serversamp
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc3Server
Calc3Serverは名前サーバにオブジェクトを登録し、クライアントからの要求を待ちます。 別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\serversamp
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Calc3Client
1+1=2
サーバプログラムは自動的には終了しませんので、Ctrl+C などで終了させてください。

1.1.4.6. POAのサンプル (POA1-POA14)

サンプルの概要
POAのサンプルは、名前と電話番号を管理する簡単なアドレス帳をシミュレーションしたものです。 サーバが管理するアドレス帳に対して、クライアントは次のようなサービスを利用できます。
POAサンプルのクライアントプログラムは共通です。サーバのサンプルプログラム側で、様々なPOAのポリシーを使用した際の動作を確認することができます。 POA1からPOA14の各サンプルの概要は以下のとおりです。
表1.1.4.6-1
1.1.4.7. デフォルトでの使用例 (POA1) 全てデフォルトのPOAポリシーで動作するサンプルです。POAやServantを初期化時に準備します。
1.1.4.8. AdapterActivator使用例 (POA2) POAやServantをオペレーション呼出のタイミングで動的に生成するサンプルです。アダプタアクティベータ(AdapterActivator)機能を利用しています。
1.1.4.9. ServantActivator使用例 (POA3) Servantをオペレーション呼出のタイミングで動的に生成するサンプルです。サーバントマネージャ(ServantManager)機能を利用しています。
1.1.4.10. ServantLocator使用例 (POA4) Servantを動的に毎回生成するサンプルです。サーバントマネージャ(ServantManager)機能とNON_RETAINポリシーを利用しています。
1.1.4.11. USE_DEFAULT_SERVANTポリシー使用例 (POA5) ひとつのServantが複数のオブジェクトリファレンスに対応して動作するサンプルです。デフォルトサーバント(DefaultServant)機能とUSER_ID、MULTIPLE_IDポリシーを利用しています。
1.1.4.12. SINGLE_THREAD_MODELポリシー使用例 (POA6) ユーザが定義するServant、サーバントマネージャ(ServantManager)、アダプタアクティベータ(AdapterActivator)の処理がすべて1つのメインスレッド上で動作するサンプルです。SINGLE_THREAD_MODELポリシーを利用しています。
1.1.4.13. ORB_CTRL_ MODELポリシー使用例 (POA7) ユーザが定義するServant、サーバントマネージャ(ServantManager)、アダプタアクティベータ(AdapterActivator)の処理が、ObjectBrokerが管理する任意スレッド上で動作するサンプルです。ORB_CTRL_MODELポリシーを利用しています。
1.1.4.14. TRANSIENTポリシー使用例 (POA8) オブジェクトリファレンスの有効期間がPOAのライフサイクルと関係して動作するサンプルです。TRANSIENTポリシーを利用しています。
1.1.4.15. PERSISTENTオブジェクトの手動起動サーバでの実装例 (POA9) オブジェクトリファレンスの有効期間がPOAのライフサイクルとは関係なく動作するサンプルです。PERSISTENTポリシーを利用しています。
1.1.4.16. TRANSIENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA10) Servantの明示的な活性化を行わずに動作するサンプルです。TRANSIENT,IMPLICIT_ACTIVATIONポリシーを利用しています。
1.1.4.17. PERSISTENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA11) POA10と同様、Servantの明示的な活性化を行わずに動作するサンプルです。こちらはPERSISTENT,IMPLICIT_ACTIVATIONポリシーを利用しています。
1.1.4.18. POAManagerのサンプル (POA12) POAの状態に応じて動作するサンプルです。POA マネージャ(POA Manager)という機能を利用しています。
1.1.4.19. TIEアプローチのサンプル (POA13) POA1をPOAのTIEクラスで動作させるサンプルです。
1.1.4.20. 自動起動サーバのサンプル (POA14) POA9を自動起動サーバとして動作させるサンプルです。
各種機能の説明は、製品構成と提供機能の「3.提供機能」-「3.6.7.11. CORBA実行環境」-「3.6.7.11. CORBA実行環境」を参照してください。
各サンプルのポリシー設定
各サンプルでは、異なるポリシーを設定しています。下表に示します。
表1.1.4.6-2
POAポリシー POAサンプル番号
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Thread Policy
ORB_CTRL_MODEL (既定値)
SINGLE_THREAD_MODEL
Lifespan Policy
TRANSIENT (既定値)
PERSISTENT
Object Id Uniqueness Policy
UNIQUE_ID (既定値)
MULTIPLE_ID
Id Assignment Policy
SYSTEM_ID (既定値)
USER_ID
Servant Retention Policy
RETAIN (既定値)
NON_RETAIN
Request Processing Policy
USE_ACTIVE_OBJECT_MAP_ONLY (既定値)
USE_SERVANT_MANAGER
USE_DEFAULT_SERVANT
Implicit Activation Policy
NO_IMPLICIT_ACTIVATION (既定値)
IMPLICIT_ACTIVATION
このサンプルでは、次のIDL定義を使用します。
module AddressMapping { 
   typedef string<43>          AM_MAP; 
   typedef sequence<AM_MAP,10> AM_MAPS; 
   interface AddressMap_1 { 
       attribute unsigned long map_num; 
       boolean add(in string name, in string phone); 
       boolean search(in string name, out AM_MAP map); 
       boolean delete(in string name); 
       boolean list(out AM_MAPS maps); 
   }; 
};
クライアントプログラム
クライアントプログラムはすべてのサンプルに共通です。クライアントプログラムを起動すると、次のようなメニューを表示します。
Menu) 1.Get numbers of all. 
2.Add address. 
3.Delete address. 
4.Search address. 
5.List all. 
6.Display object reference (& save to file:objref.dat).
7.Obtain object reference again. 
9.End. 
Please select number?
1. は、アドレス帳の登録件数を表示します。
Please select number? 1 
-------------------------- 
--> Get start. 
Get number of all maps = 5
2. は、アドレス帳への登録を行います。メッセージに応じて、名前と電話番号を入力してください。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample1 
phone? 111-1111 
add() calling ..........OK.
3. は、アドレス帳からの削除を行います。メッセージに応じて、名前を入力してください。
Please select number? 3 
-------------------------- 
--> Delete start. 
name? sample1 
delete() calling ..........OK. 
4. は、アドレス帳からの検索を行います。メッセージに応じて、名前を入力してください。
Please select number? 4 
-------------------------- 
--> Search start. 
name? sample12_3 
search() calling ..........OK. 
name / phone 
------------------------------------------- 
sample12_3 / 333-3333 
5. は、アドレス帳に登録されている情報を一覧表示します。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
Sample1 / 111-1111 
Sample2 / 222-2222 
Sample3 / 333-3333 
6. は、現在保持しているオブジェクトリファレンスを文字列に変換したものを表示します。また、カレントディレクトリに "objref.dat" という名前のファイルを出力します。
Please select number? 6 
-------------------------- 
--> Display start.(local) 
Object reference: IOR:000000000000002249444c3a416464726573734d61707069
6e672f416464726573734d61703a312e300000000000000100000000000000a0000100
00000000087072696d6572610004fc000000000088004e4f7262040100000000000000
002249444c3a416464726573734d617070696e672f416464726573734d61703a312e30
000000000000010000000000000000000000d08384d0880000003c00504f4101000000
000000072f6d79504f41000000000024004e504f41010000000000072f6d79504f4100
0000000000000000d08384d08800000000 
7. は、新たにオブジェクトリファレンスを再取得します。
Please select number? 7 
-------------------------- 
--> Obtain start.(local) 
サーバプログラムにおける注意点

1.1.4.7. デフォルトでの使用例 (POA1)

POA1はActiveObjectMapのみを利用した形態です。 すべてデフォルトのポリシーをもつPOAとServantを初期化時にあらかじめ生成し、Servantを活性化します。一度活性化されたServantは、RETAINポリシーによりActiveObjectMapに登録されますので、クライアントからのリクエスト時の動的な生成は起こりません。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA1のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA1
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_1
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: TRANSIENT 
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時にServantが生成され、クライアントからのリクエスト時には動的に生成されていないことが分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
===== AMapServant created. 
type: TRANSIENT 
If you want to stop ServerAP, key quit!
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample1, phone = 111-1111 
===== AMapServant/add() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
quit. 
goodbye... 
===== AMapServer end.

1.1.4.8. AdapterActivator使用例 (POA2)

POA2はAdapterActivatorを利用した形態です。 POA1では初期化時にPOAとServantをあらかじめ生成しておいたのに対して、POA2では初期化時には何も生成せず、rootPOAに対してAdapterActivatorの登録のみ行っています。POAとServantはクライアントからの最初のリクエスト時にAdapterActivatorのunknown_adapter()で動的に生成され、活性化されます。一度活性化されたServantは、RETAINポリシーによりActiveObjectMapに登録されますので、以降のリクエスト時にはこのような動的な生成は起こりません。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA2のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA2
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_2
    ===== AMapServer start. [Thread name = main] 
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されず、クライアントからの最初のリクエスト時に AdapterActivatorのunknown_adapter()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されることがないことも分かります。
===== AMapServer start. [Thread name = main] 
If you want to stop ServerAP, key quit! 
===== AMapAdapterActivator/unknown_adapter() start. [Thread name = Thr
ead-3] 
===== myPOA created. 
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapAdapterActivator/unknown_adapter() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample2, phone = 222-2222 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.9. ServantActivator使用例 (POA3)

POA3は、ServantManagerを利用した形態です。 POA1では初期化時にPOAとServantをあらかじめ生成しておいたのに対して、POA3では初期化時にServantManager(ServantActivator)を登録したPOAのみを生成します。Servantはクライアントからの最初のリクエスト時にServantManager(ServantAcrivator)のincarnate()で動的に生成され、活性化されます。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA3のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA3
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_3
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されておらず、クライアントからの最初のリクエスト時にServantActivatorのincarnate()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されることがないことも分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
If you want to stop ServerAP, key quit! 
===== AMapServantActivator/incarnate() start. [Thread name = Thread-3]
===== AMapServant created. 
type: TRANSIENT 
===== AMapServantActivator/incarnate() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample3, phone = 333-3333
===== AMapServant/add() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.10. ServantLocator使用例 (POA4)

POA4は、NON_RETAINポリシーでのServantManagerを利用した形態です。 初期化時にはServantManager(ServantLocator)を登録したPOAのみを生成します。POA3では、Servantはクライアントからの最初のリクエスト時に動的に1回だけ生成され活性化されたのに対して、POA4では毎回ServantManager(ServantLocator)のpreinvoke()で動的に生成され活性化されます。活性化されたServantは、NON_RETAINポリシーによりActiveObjectMapに登録されないまま、ServantManager(ServantLocator)のpostinvoke()により消滅されます。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA4のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA4
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_4
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    If you want to stop ServerAP, key quit!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバのメッセージから、初期化時には何も生成されておらず、クライアントからの最初のリクエスト時にServantLocatorのpreinvoke()においてServantが生成されていることが分かります。また、以降のリクエスト時に動的に生成されていることも分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
If you want to stop ServerAP, key quit! 
===== AMapServantLocator/preinvoke() start. [Thread name = Thread-3] 
For add operation. 
===== AMapServant created. 
type: TRANSIENT 
===== AMapServantLocator/preinvoke() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample4, phone = 444-4444 
===== AMapServant/add() end. 
===== AMapServantLocator/postinvoke() start. [Thread name = Thread-3]
For add operation. 
===== AMapServantLocator/postinvoke() end. 
===== AMapServantLocator/preinvoke() start. [Thread name = Thread-3] 
For list operation. 
===== AMapServant created. 
type: TRANSIENT 
===== AMapServantLocator/preinvoke() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
===== AMapServantLocator/postinvoke() start. [Thread name = Thread-3] 
For list operation. 
===== AMapServantLocator/postinvoke() end. 
quit 
goodbye... 
===== AMapServer end.

1.1.4.11. USE_DEFAULT_SERVANTポリシー使用例 (POA5)

POA5は、MULTIPLE_ID、USER_IDポリシーでのDefaultServantを利用した形態です。 初期化時にはPOAとServantを生成し、それをDefaultServantとして登録します。クライアントからのリクエスト時には、そのDefaultServantが毎回対応することになります。また、オブジェクトIDをユーザが定義することにより、作成された複数のオブジェクトリファレンスにおけるリクエストも、同じDefaultServantが対応することになります。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA5のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA5
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。このサンプルでは、MULTIPLE_IDポリシーにより、1つのServantに対して2つのオブジェクトリファレンスを生成しています。 以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_5
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: TRANSIENT 
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. (C) もう1つのクライアントプログラムを起動します。"-name AMapObj2"を付加して起動してください。これにより、異なるオブジェクトリファレンスを得られます。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient -name AMapObj2
    ===== AMapClient started. ===== 
    target = AMapObj2 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample5 
phone? 555-5555 
add() calling ..........OK.
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
sample5 / 555-5555 
サーバのメッセージから、初期化時にServant(DefaultServant)が生成され、クライアントからのリクエスト時にはそのServantが毎回対応していることが分かります。また、異なるオブジェクトリファレンスによるリクエストでも同じServantが対応しますので、2つのクライアントが同じアドレス帳を参照・更新していることが分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
===== AMapServant created. 
type: TRANSIENT 
If you want to stop ServerAP, key quit! 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample5, phone = 555-5555 
===== AMapServant/add() end. 
Connect request accepted 
===== AMapServant/list() start. [Thread name = Thread-4] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.12. SINGLE_THREAD_MODELポリシー使用例 (POA6)

POA6は、SINGLE_THREAD_MODELポリシーにより,ユーザが定義するServant、ServantManager、AdapterActivatorがすべてメインスレッド上だけで実行される形態です。 初期化時には、parentPOAにAdapterActivatorを登録しておきます。クライアントからの最初のリクエスト時にAdapterActivatorのunknown_adapter()でmyPOAが生成され、myPOAにServantManagerが登録されます。つぎにmyPOAに登録したServantManagerのincarnate()でServantが生成され、そのServantは活性化されます。また、このサンプルでは、サーバのメインスレッドでは、ORB.run()ではなく、ORB.work_pending()とORB.perform_work()を使用しています。これは、イベントループ処理の1つとしてORBの処理を実行させたいプログラマが使う関数です。そうでないプログラマは他のサンプル同様にORB.run()を使うのが便利です。SINGLE_THREAD_POLICYの利点は、ユーザ定義コードがすべてメインスレッドで実行されるため、マルチスレッドを考慮しなくていいというところにあります。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA6のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA6
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_6
    ===== AMapServer start. [Thread name = main] 
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample6 
phone? 666-6666 
add() calling ..........OK.
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
sample6 / 666-6666 
サーバのメッセージから、ユーザが定義したAdapterActivator、ServantActivater、Servantがすべてperform_work()の延長、すなわちメインスレッドで実行されていることが分かります。また、別のクライアントからの要求も同じスレッドで実行されていることが分かります。
===== AMapServer start. [Thread name = main] 
If you want to stop ServerAP, key quit! 
===== AMapAdapterActivator/unknown_adapter() start. [Thread name = main]
===== myPOA created. 
===== AMapAdapterActivator/unknown_adapter() end. 
===== perform_work() start. 
===== AMapServantActivator/incarnate() start. [Thread name = main] 
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapServantActivator/incarnate() end. 
===== perform_work() end. 
===== perform_work() start. 
===== AMapServant/add() start. [Thread name = main] 
name = sample6, phone = 666-6666 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== perform_work() end. 
===== perform_work() start. 
===== AMapServantActivator/incarnate() start. [Thread name = main] 
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapServantActivator/incarnate() end. 
===== perform_work() end. 
===== perform_work() start. 
===== AMapServant/list() start. [Thread name = main] 
===== AMapServant/list() end. 
===== perform_work() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.13. ORB_CTRL_ MODELポリシー使用例 (POA7)

POA7は、ORB_CTRL_MODELポリシにより、ユーザが定義するServant、ServantManager、AdapterActivatorがObject Brokerが管理するスレッド上で実行される形態です。 初期化時には、rootPOAにAdapterActivatorを登録しておきます。クライアントからの最初のリクエスト時にAdapterActivatorのunknown_adapter()でPOAが生成され、ServantManagerが登録されます。これにより、Servantが生成され、活性化されます。サーバのメインスレッドでは、ORB.run()を使用しています。ユーザ定義のコードはObject Brokerが管理するスレッドで実行されることになります。したがって、マルチスレッドを考慮したコーディングが必要であるといえます。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA7のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA7
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_7
    ===== AMapServer start. [Thread name = main] 
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample7 
phone? 777-7777 
add() calling ..........OK. 
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
sample7 / 777-7777 
サーバのメッセージから、ユーザが定義したAdapterActivator、ServantActivater、Servantがすべてメインスレッド以外で実行されていることが分かります。また、別のクライアントからの要求が異なるスレッドで実行されていることが分かります。
===== AMapServer start. [Thread name = main] 
If you want to stop ServerAP, key quit! 
===== AMapAdapterActivator/unknown_adapter() start. [Thread name = Thread-3] 
===== myPOA created. 
===== AMapAdapterActivator/unknown_adapter() end. 
===== AMapServantActivator/incarnate() start. [Thread name = Thread-3]
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapServantActivator/incarnate() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample7, phone = 777-7777 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServantActivator/incarnate() start. [Thread name = Thread-4]
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapServantActivator/incarnate() end. 
===== AMapServant/list() start. [Thread name = Thread-4] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.14. TRANSIENTポリシー使用例 (POA8)

POA8は、TRANSIENTポリシーで動作する形態です。 TRANSIENTポリシーとは、POAのライフタイムとオブジェクトリファレンスのライフタイムが同じであることを意味しています。よって、POAがdestroy()によって破棄されると、古いオブジェクトリファレンスではオブジェクトにアクセスすることができません。再度アクセスするには、新しいオブジェクトリファレンスを取得しなければなりません。また、このサンプルではServantActivatorも使用しています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA8のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA8
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_8
    ===== AMapServer start. [Thread name = main] 
    If you want to stop ServerAP, key quit or refresh!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。サーバ(A)でPOAを作り直すには、"refresh"と入力します。クライアント(B)で新しいオブジェクトリファレンスを取得するには、7を入力します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)でオブジェクトリファレンスを表示します。
Please select number? 6 
-------------------------- 
--> Display start.(local) 
Object reference: IOR:000000000000002249444c3a416464726573734d61707069
6e672f416464726573734d61703a312e300000000000000100000000000000a0000100
00000000087072696d657261000488000000000088004e4f7262040100000000000000
002249444c3a416464726573734d617070696e672f416464726573734d61703a312e30
000000000000010000000000000000000000d082a60d300000003c00504f4101000000
000000072f6d79504f41000000000024004e504f41010000000000072f6d79504f4100
0000000000000000d082a60d3000000000 
サーバを再起動し、クライアント(B)でオブジェクトリファレンスを取得し、再度表示します。
Please select number? 7 
-------------------------- 
--> Obtain start.(local) 
Please select number? 6 
-------------------------- 
--> Display start.(local) 
Object reference: IOR:000000000000002249444c3a416464726573734d61707069
6e672f416464726573734d61703a312e300000000000000100000000000000a0000100
00000000087072696d657261000491000000000088004e4f7262040100000000000000
002249444c3a416464726573734d617070696e672f416464726573734d61703a312e30
000000000000010000000000000000000000d082a703480000003c00504f4101000000
000000072f6d79504f41000000000024004e504f41010000000000072f6d79504f4100
0000000000000000d082a7034800000000 
サーバを再起動する前と、再起動後に再取得したオブジェクトリファレンスが異なることが分かります。再取得前に古いオブジェクトリファレンスのままリクエストすると、以下のように例外が発生します。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling .....ERROR : org.omg.CORBA.OBJECT_NOT_EXIST[minor
=5112, completed=MAYBE, reason=The object is not active] 
org.omg.CORBA.OBJECT_NOT_EXIST[minor=5112, completed=MAYBE, reason=The
object is not active 

1.1.4.15. PERSISTENTオブジェクトの手動起動サーバでの実装例 (POA9)

POA9は、PERSISTENTポリシーで動作する形態です。 内容については、POA8と同様です。PERSISTENTポリシーとは、POAやサーバが終了してもオブジェクトリファレンスは有効であることを意味しています。よって、POAが一度削除され再生成されても、クライアントは古いオブジェクトリファレンスをそのまま使用してオブジェクトにアクセスすることができます。 このサンプルのサーバは手動起動(PersistentServer)のサーバです。手動起動サーバでPERSISTENTポリシーのオブジェクトを実装するには、サーバのポート番号を指定する必要があります。サーバのポート番号を指定する方法は、起動時の引数で指定する方法とプログラム中で指定する方法があります。このサンプルは、起動時の引数で指定する方法を用いています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA9のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA9
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。xxxxにはサーバのポート番号を指定してください。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB -DServerPort=xxxx AMapServer_9
    ===== AMapServer start. [Thread name = main] 
    If you want to stop ServerAP, key quit or refresh!
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。サーバ(A)でPOAを作り直すには、"refresh"と入力します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
サーバを再起動後も、古いオブジェクトリファレンスのままリクエストできることがわかります。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
sample7 / 777-7777 

1.1.4.16. TRANSIENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA10)

POA10は、TRANSIENTポリシーとIMPLICIT_ACTIVATIONポリシーをもつ形態です。 Servantのactivate_object()により明示的に活性化を行わなくても、servant_to_reference()を使用するだけで暗黙のうちに活性化が行われますので、クライアントからのリクエスト時に意図するServantに対応づけられることになります。また、TRANSIENTの場合には、UNIQUE_IDでもMULTIPLE_IDでも指定できます。このサンプルではMULTIPLE_IDを指定していますので、同じServantに2個のオブジェクトリファレンスを対応づけています。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA10のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA10
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_10
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: TRANSIENT 
    ===== AMapServant's object reference created by servant_to_reference().
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. (C) もう1つのクライアントプログラムを起動します。"-name AMapObj2"を付加して起動してください。これにより、異なるオブジェクトリファレンスを得られます。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient -name AMapObj2
    ===== AMapClient started. ===== 
    target = AMapObj2 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample10 
phone? 101-0101 
add() calling ..........OK. 
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling ..........OK. 
name / phone 
------------------------------------------- 
sample10 / 101-0101 
サーバのメッセージから、初期化時にservant_to_reference()を使用するだけで暗黙のうちにServantは活性化されており、クライアントからのリクエスト時には明示的な活性の場合と同様に処理されることが分かります。また、異なるオブジェクトリファレンスによるリクエストでも同じServantが対応しますので、2つのクライアントが同じアドレス帳を参照・更新していることが分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
===== AMapServant created. 
type: TRANSIENT 
===== AMapServant's object reference created by servant_to_reference().
If you want to stop ServerAP, key quit! 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample10, phone = 101-0101 
===== AMapServant/add() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.17. PERSISTENTポリシーかつIMPLICIT_ACTIVATIONポリシーの例 (POA11)

POA11は、PERSISTENTポリシとIMPLICIT_ACTIVATIONポリシをもつ形態です。 POA10と同様に暗黙のうちに活性化が行われます。PERSISTENTの場合には、MULTIPLE_IDは指定できませんので、このサンプルではUNIQUE_IDを指定しています。また、POA9と同様に、手動起動サーバでPERSISTENTポリシのオブジェクトを実装しますので、サーバのポート番号を指定する必要があります。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA11のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA11
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。xxxxにはサーバのポート番号を指定してください。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB -DServerPort=xxxx AMapServer_11
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: PERSISTENT 
    sleeped 15sec per 5actions. 
    ===== Loading start. 
    ===== Loading end. 
    ===== AMapServant's object reference created by servant_to_reference().
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  7. (B) メニューで9を入力し、クライアントプログラムを終了します。
  8. (A) "quit"と入力し、サーバプログラムを終了します。
初期化時にservant_to_reference()を使用するだけで暗黙のうちにServantは活性化されており、クライアントからのリクエスト時には明示的な活性化の場合と同様に処理されることが分かります。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
===== AMapServant's object reference created by servant_to_reference().
If you want to stop ServerAP, key quit! 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample11, phone = 111-1111 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/list() start. [Thread name = Thread-3] 
===== AMapServant/list() end. 
quit 
goodbye... 
===== AMapServer end.

1.1.4.18. POAManagerのサンプル (POA12)

POA12は、POA Managerを利用した形態です。 POA Managerの状態をHolding状態にすることで、クライアントからのリクエストがキューイングされます。再度、Activeにすることでリクエストの処理が再開します。サンプルで提供しているServantは、登録あるいは削除のオペレーション5回毎にPOA Managerを15秒間Holding状態にします。これにより、擬似的に処理遅延(sleep)が起こり、この間に別のクライアントからリクエストが届いても、リクエストが保留されます。
  1. 3つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをA、B、Cとします。
  2. (A、B、Cとも) POA12のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA12
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_12
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: PERSISTENT 
    sleeped 15sec per 5actions. 
    ===== Loading start. 
    ===== Loading end. 
    If you want to stop ServerAP, key quit! 
    
  5. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  6. (C) もう1つのクライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B, C) メニューで9を入力し、クライアントプログラムを終了します。
  9. (A) "quit"と入力し、サーバプログラムを終了します。
クライアント(B)から登録を実行します。
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample12_1 
phone? 111-1111 
add() calling ..........OK. 
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample12_2 
phone? 222-2222
add() calling ..........OK. 
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample12_3 
phone? 333-3333 
add() calling ..........OK. 
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample12_4 
phone? 444-4444 
add() calling ..........OK. 
Please select number? 2 
-------------------------- 
--> Add start. 
name? sample12_5 
phone? 555-5555 
add() calling .......... 
+-------------------------------------------------------------
|※このリクエストにより擬似的な処理遅延で応答が15秒間、 
|  遅れます。 
+-------------------------------------------------------------
OK. 
クライアント(C)から検索すると、(B)から登録した結果が表示されます。
Please select number? 5 
-------------------------- 
--> List start. 
list() calling .......... 
+-------------------------------------------------------------
|※Holding状態により、このリクエストはキューイングされ、 
|  15秒間応答が遅れます。 
+-------------------------------------------------------------
OK. 
name / phone 
-------------------------------------------  
sample12_1 / 111-1111 
sample12_2 / 222-2222 
sample12_3 / 333-3333 
sample12_4 / 444-4444 
sample12_5 / 555-5555 
サーバは、次のように動作します。
===== AMapServer start. [Thread name = main] 
===== myPOA created. 
===== AMapServant created. 
type: PERSISTENT 
sleeped 15sec per 5actions. 
===== Loading start. 
===== Loading end. 
If you want to stop ServerAP, key quit! 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample12_1, phone = 111-1111 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample12_2, phone = 222-2222 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample12_3, phone = 333-3333 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample12_4, phone = 444-4444 
===== Saving start. 
===== Saving end. 
===== AMapServant/add() end. 
===== AMapServant/add() start. [Thread name = Thread-3] 
name = sample12_5, phone = 555-5555 
===== Saving start. 
Holding(15sec.).....end. 
+-------------------------------------------------------------
|※この間に受け付けたクライアント(C)からの要求は15秒間、 
|  待たされます。 
+-------------------------------------------------------------
===== AMapServant/list() start. [Thread name = Thread-4] 
===== AMapServant/list() end. 
===== Saving end. 
===== AMapServant/add() end. 
quit 
goodbye... 
===== AMapServer end. 

1.1.4.19. TIEアプローチのサンプル (POA13)

POA13は、POA1をPOAのTIEクラスを使用して作成したものです。サーバ側のオブジェクトの作成および登録の方法が異なる以外は、POA1と同じです。 AMapServant_tie.javaは、各メソッドの処理はAMapServant.javaと同じですが、AddressMapOperationsを実装している点が異なっています。また、AMapServer_1_tie.javaは、POA_AddressMap_tieクラスを作成し、これをPOAに登録しています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA13のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA13
    
  3. (A) makeを実行します。
    > make
    
  4. (A) サーバプログラムを起動します。以下のメッセージが出力されると、起動完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_1_tie
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created. 
    ===== AMapServant created. 
    type: TRANSIENT 
    If you want to stop ServerAP, key quit! 
    
以降は、POA1と同じです。

1.1.4.20. 自動起動サーバのサンプル (POA14)

POA14は、POA9を自動起動サーバとして改造したものです。 自動起動サーバのオブジェクトリファレンスを生成するには、インプリメンテーション名を指定する必要があります。インプリメンテーション名を指定する方法は、起動時の引数で指定する方法とプログラム中で指定する方法があります。このサンプルは、起動時の引数で指定する方法を用いています。
  1. 2つのコマンドプロンプトウィンドウを開きます。それぞれのウィンドウをAとBとします。
  2. (A、Bとも) POA14のディレクトリに移動します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\POA14
    
  3. (A) makeを実行します。
    > make
    
  4. (A) インプリメンテーションを登録します。AMapServer_14を実行するために必要なクラスパスを設定してください。クラスパスおよびjavaコマンドはフルパスで指定してください。
    > instimpl myImpl "C:\j2sdk1.4.2_10\bin\java -classpath C:\Progra~1\NEC\WebOTX\samples\corba\objava\POA14;C:\Progra~1\NEC\WebOTX\ObjectBroker\lib\ospiorb50.jar;C:\Progra~1\NEC\WebOTX\ObjectBroker\lib\ospiname50.jar;C:\Progra~1\NEC\WebOTX\ObjectBroker\lib\jsocks.jar -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapServer_14" SharedServer
    

    Caution インプリメンテーションを登録するときにクラスパスを直接設定する場合には、ブランク文字を含まない形式でクラスパスを記述して下さい。ブランク文字を含むクラスパスを記述した場合、ブランクまでをクラスパスと判断し、自動起動サーバが正常に起動しない場合があります。

  5. (A) オブジェクトリファレンスを生成します。4で登録したインプリメンテーションの名前を指定します。以下のメッセージが出力されると、生成完了です。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB -DImplementationName=myImpl AMapServer_14 -create
    ===== AMapServer start. [Thread name = main] 
    ===== myPOA created.
    
  6. (B) クライアントプログラムを起動します。以下のメニューが出力されます。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB AMapClient
    ===== AMapClient started. ===== 
    target = AMapObj 
    -------------------------- 
    Menu) 1.Get numbers of all. 
    2.Add address. 
    3.Delete address. 
    4.Search address. 
    5.List all. 
    6.Display object reference (& save to file:objref.dat). 
    7.Obtain object reference again. 
    9.End. 
    Please select number? 
    
  7. クライアント側メニューを選択することによって動作します。動作に応じて両ウィンドウにメッセージが出力されますので、どのように動作しているかを確認してください。
  8. (B) メニューで9を入力し、クライアントプログラムを終了します。これにより自動的にサーバも終了します。

1.1.4.21. フックのサンプル (hook)

このサンプルは、オペレーションop1を実行してオペレーションstopで停止する、簡単なサーバ/クライアントプログラムに各種フックが登録されています。
  1. コマンドプロンプトを開き、makeを実行します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\hook
    > make
    
  2. サーバプログラムを実行します。
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB HookServer
    HookServer start.
    ORB init
    get NameService reference
    [SrvHook]Hook created.
    
  3. 別のコマンドプロンプトを開き、クライアントプログラムを実行します。
    > cd C:\Program Files\NEC\WebOTX\samples\corba\objava\hook
    > java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB HookClient
    
サーバ側のウィンドウは、次のように表示されます。
HookServer start.
ORB init
get NameService reference
[SrvHook]Hook created.
[SrvHook]ServerAfterReceive() for message called.
47 49 4F 50 01 00 00 00 00 00 00 B0 00 00 00 01
G  I  O  P  .  .  .  .  .  .  .  .  .  .  .  .
00 00 00 01 00 00 00 0C 00 00 00 00 00 01 00 01
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
[SrvHook]ServerAfterReceive() for parameter called.
[SrvHook]  operation: op1
[SrvHook]  arg1's value = 1
op1() called.
[SrvHook]ServerBeforeSend() for parameter called.
[SrvHook]  operation: op1
[SrvHook]ServerBeforeSend() for message called.
47 49 4F 50 01 00 00 01 00 00 00 20 00 00 00 01
G  I  O  P  .  .  .  .  .  .  .     .  .  .  .
00 00 00 01 00 00 00 0C 00 00 00 00 00 01 00 01
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
[SrvHook]ServerAfterReceive() for message called.
47 49 4F 50 01 00 00 00 00 00 00 B0 00 00 00 01
G  I  O  P  .  .  .  .  .  .  .  .  .  .  .  .
00 00 00 01 00 00 00 0C 00 00 00 00 00 01 00 01
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
[SrvHook]ServerAfterReceive() for parameter called.
[SrvHook]  operation: stop
stop() called.
HookServer end.
クライアント側のウィンドウは、次のように表示されます。
HookClient start.
ORB init
get NameService reference
[CltHook]Hook created.
op1() call
[CltHook]ClientBeforeSend() for parameter called.
[CltHook]  operation: op1
[CltHook]  arg1's value = 1
[CltHook]ClientBeforeSend() for message called.
47 49 4F 50 01 00 00 00 00 00 00 B0 00 00 00 01
G  I  O  P  .  .  .  .  .  .  .  .  .  .  .  .
00 00 00 01 00 00 00 0C 00 00 00 00 00 01 00 01
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
[CltHook]ClientAfterReceive() for message called.
47 49 4F 50 01 00 00 01 00 00 00 20 00 00 00 01
G  I  O  P  .  .  .  .  .  .  .     .  .  .  .
00 00 00 01 00 00 00 0C 00 00 00 00 00 01 00 01
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
[CltHook]ClientAfterReceive() for parameter called.
[CltHook]  operation: op1
done.
stop() call
done.
HookClient end.

1.1.4.22. アプレットプロキシ使用のサンプル (appletsv)

このサンプルではアプレットプロキシを使用してアプレット上でサーバオブジェクトを運用することによって、簡易チャットシステムを実現しています。 この簡易チャットシステムは、各チャットクライアント(アプレット)を登録してクライアントから届いたメッセージを全クライアントに配送するチャットサーバと、サーバに自分を登録してメッセージをサーバに送信しサーバから届いたメッセージを表示するクライアントとからなっています。サーバは chat::MessageSender インタフェースを、クライアントはchat::MessageRecever インタフェースをそれぞれ実装しています。 このサンプルの実行のためには、Object Brokerの名前サーバ、アプレットプロキシおよびWebサーバが必要です。サーバマシン(たとえばsamplesv)上でObject BrokerとWebサーバを動作させ、Webサーバからサンプルディレクトリをアクセス可能にします(URLをhttp://samplsv/appletsv/とします)。同時にObject Brokerのjarファイルをそのディレクトリにコピーします。また、サンプルディレクトリにあるdefault.htmのORBInitialHostにサーバマシン名を指定します。 コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\appletsv
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB ChatServer
サーバマシンにアクセス可能なマシン上でApplet ViewerもしくはWebブラウザを起動し、サンプルページのdefault.htmにアクセスします。
> appletviewer http://samplesv/appletsv/default.htm
起動したブラウザの「User」フィールドに自分の名前を、「Message」フィールドに適当なメッセージを入力すると、チャットサーバにメッセージが送信され、各クライアントに配送されてチャットウィンドウ上に表示されます。各フィールドに入力されたメッセージはリターンキーを押すことで確定されます。

1.1.4.23. valuetypeのサンプル (value1-value4)

実行方法は、value1-value4の各サンプルで共通です。ここでは、value1の実行方法を説明します。 コマンドプロンプトを開き、makeを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\value1
> make
サーバプログラムを実行します。
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Val1Server
別のコマンドプロンプトを開き、クライアントプログラムを実行します。
> cd C:\Program Files\NEC\WebOTX\samples\corba\objava\value1
> java -Dorg.omg.CORBA.ORBClass=jp.co.nec.orb.OSPORB Val1Client
valuetypeの使用例(value1)


図1.1.4.23-1

valuetypeの使用例(value2)


図1.1.4.23-2

valueboxの使用例(value3)
あるデータ型(long、structなど)をvalueboxとして定義することにより、valuetypeがもつnullや共有の概念を取り込むことができます。このサンプルは、共有の概念を持たないstruct型をvalueboxとして定義することによる復元の差異を確認できます。


図1.1.4.23-3


図1.1.4.23-4

abstract interfaceの使用例 (value4)
abstract interfaceを定義し、その型をオペレーションのパラメタに指定すると、そのabstract interfaceを継承するinterfaceかvaluetypeかを動的に切り換えて指定できるようになります。このサンプルは、クライアントがサーバから取得したabstract interface型のオブジェクトに対してオペレーションを実行し、その差異を確認できます。 interfaceのオブジェクトリファレンスの場合、オペレーションの実行結果は、サーバ側で表示されます。 valueの場合、オペレーションの実行結果は、クライアント側で表示されます。