C++共同クライアント/サーバー・アプリケーションの開発
表2-1では、C++共同クライアント/サーバー・アプリケーションの開発プロセスの概略を示します。
 
      
      
        
          表2-1 
C++共同クライアント/サーバー・アプリケーションの開発プロセス
          |  |  | 
        
          |  | Oracle Tuxedoアプリケーションで使用するコールバック・インタフェースおよびCORBAインタフェースのOMG IDLを記述します。  | 
        
          |  | スケルトンおよびクライアント・スタブを生成します。  | 
        
          |  | 各オブジェクトのオペレーションを実装するメソッドを記述します。 | 
        
          |  | 共同クライアント/サーバー・アプリケーションのクライアント部分を記述します。 | 
        
          |  | コールバック・ラッパー・オブジェクトを使用してコールバック・オブジェクトを作成します。 | 
        
          |  | コールバック・オブジェクトのオブジェクト参照を渡すことにより、Oracle Tuxedoオブジェクトのオペレーションを呼び出します。 | 
        
          |  |  | 
        
          |  | 共同クライアント/サーバー・アプリケーションをコンパイルします。 | 
      
      
      共同クライアント/サーバー・アプリケーション内のコールバック・オブジェクトはトランザクションに関与せず、オブジェクト管理機能を持たないため、このオブジェクト用の実装構成ファイル(
filename.icf)を作成する必要はありません。ただし、Oracle Tuxedoアプリケーション内のOracle TuxedoオブジェクトのICFファイルは作成する必要があります。ICFファイルの記述については、
『CORBAサーバー・アプリケーションの作成』を参照してください。
ここでは、Chat Roomサンプル・アプリケーションを使用して開発の手順を説明します。チャット・ルームとは、様々な場所にいる人々が相互に通信できるアプリケーションです。ログインしたクライアント・アプリケーションを追跡し、それらにメッセージを配信する役目を持つモデレータが、チャット・ルームであると考えてください。 
クライアント・アプリケーションは、ユーザー名を指定してモデレータにログインします。キーボードにメッセージが入力されると、クライアント・アプリケーションはモデレータを呼び出してそのメッセージを渡します。次に、モデレータはコールバック・オブジェクトを呼び出して、ほかのすべてのクライアント・アプリケーションにメッセージを配信します。 
Chat Roomサンプル・アプリケーションは、C++共同クライアント/サーバー・アプリケーションおよびOracle Tuxedoサーバー・アプリケーションで構成されています。共同クライアント/サーバー・アプリケーションはキーボード入力を受け取り、モデレータに対して呼出しを行います。また共同クライアント/サーバー・アプリケーションは、モデレータからのメッセージをリスニングする、つまりモデレータからの呼出しを受信するように、コールバック・オブジェクトを設定します。Chat Roomサンプル・アプリケーションのOracle Tuxedoサーバー・アプリケーションでは、モデレータが実装されます。
図2-1では、Chat Roomサンプル・アプリケーションがどのように動作するのかを示します。
 
      
      
      Chat Roomサンプル・アプリケーションは、次のように動作します。
        
          
            | 1.	 | 共同クライアント/サーバー・アプリケーションは、コールバック・オブジェクト(Listenerオブジェクト)のロジックを実装し、Listenerオブジェクトのサーバントを作成し、Listenerオブジェクトをアクティブ化します。  | 
        
       
      
        
          
            | 2.	 | 共同クライアント/サーバー・アプリケーションは、Listenerオブジェクトのオブジェクト参照を作成し、signon オペレーションの一部としてModeratorオブジェクトに渡します。 | 
        
       
      
        
          
            | 3.	 | Chat Roomサンプル・アプリケーションのサーバー・アプリケーションでは、キーボード入力によるメッセージを確認します。 | 
        
       
      
        
          
            | 4.	 | キーボード入力によりメッセージが生成されると、Chat Roomサンプル・アプリケーションはsend オペレーションを介してそのメッセージをModeratorオブジェクトに送信します。 | 
        
       
      
        
          
            | 5.	 | Chat Roomサンプル・アプリケーションは、一時的に制御をORBに渡して、共同クライアント/サーバー・アプリケーションのListenerオブジェクトがModeratorオブジェクトからpost 呼出しを受け取れるようにします。 | 
        
       
      
        
          
            | 6.	 | 共同クライアント/サーバー・アプリケーション内のListenerオブジェクトは、クライアント・アプリケーションからのリクエストがあるまで、ポストされたメッセージを保存します。 | 
        
       
      
      
      使用できるCORBAインタフェースをクライアント・アプリケーションに記述するには、Object Management Group (OMG)インタフェース定義言語(IDL)を使用します。OMG IDLで記述したインタフェース定義を使用すると、完全にCORBAインタフェースを定義し、各オペレーションの引数を指定できます。OMG IDLは、純粋な宣言型言語です。つまり、実装の詳細は含まれていません。OMG IDLの詳細は、
『CORBAクライアント・アプリケーションの作成』を参照してください。Chat Roomサンプル・アプリケーションでは、
表2-2に示したCORBAインタフェースが実装されます。
        
          表2-2 
Chat Roomサンプル・アプリケーションのCORBAインタフェース
          |  |  |  | 
        
          |  |  |  | 
        
          |  | クライアント・アプリケーションからの入力を受信し、コールバック・オブジェクトによりメッセージを転送して共同クライアント/サーバー・アプリケーションに戻します。 |  | 
        
          |  | Moderatorオブジェクトへのオブジェクト参照を作成します。 |  | 
      
      例2-1は、
Listenerインタフェースを定義する
chatclient.idlを示します。
 
      リスト2-1 
ListenerインタフェースのOMG IDL
module ChatClient{
       interface Listener  {
              oneway void post (in string from,
                                in string output_line);
       };
};
      
      例2-2は、Chat Roomサンプル・アプリケーションの
Moderatorおよび
ModeratorFactoryインタフェースを定義する
chatroom.idlを示します。別のOMG IDLファイルのインタフェースに対する参照を解決するには、
#includeを使用します。Chat Roomサンプル・アプリケーションでは、
signonメソッドにはパラメータとしてListenerオブジェクトが必要であり、そのIDLファイルはListenerインタフェースを定義するOMG IDLファイルを
#includeしている必要があります。
 
      リスト2-2 
ModeratorおよびModeratorFactoryインタフェースのOMG IDL
#include "ChatClient.idl"
module ChatRoom {
       interface Moderator {
           exception IdAlreadyUsed{};
           exception NoRoomLeft{};
           exception IdNotKnown{};
           void signon( in string who,
                        in ChatClient::Listener callback_ref )
                            raises( IdAlreadyUsed, NoRoomLeft );
           void send  (in string who, 
                       in string input_line )
                            raises( IdNotKnown );
           void signoff(in string who )
                           raises( IdNotKnown );
       };
       interface ModeratorFactory {
          Moderator get_moderator( in string chatroom_name );
       };
};
      
      ステップ2:スケルトンおよびクライアント・スタブの生成
OMG IDLで定義したインタフェース仕様は、IDLコンパイラによってスケルトンおよびクライアント・スタブの生成に使用されます。共同クライアント/サーバー・アプリケーションは、Oracle Tuxedoオブジェクトにクライアント・スタブを、コールバック・オブジェクトにスケルトンおよびクライアント・スタブを使用することに注意してください。 
たとえばChat Roomサンプル・アプリケーションでは、共同クライアント/サーバー・アプリケーションはListenerオブジェクト(つまりコールバック・オブジェクト)のためのスケルトンおよびクライアント・スタブを使用して、オブジェクトを実装します。また、共同クライアント/サーバー・アプリケーションは
Moderatorおよび
ModeratorFactoryインタフェースのためのクライアント・スタブを使用して、オブジェクトのオペレーションを呼び出します。Oracle Tuxedoサーバー・アプリケーションはModeratorおよびModeratorFactoryオブジェクトのスケルトンを使用してオブジェクトを実装し、Listenerオブジェクトのためのクライアント・スタブを使用してオブジェクトのオペレーションを呼び出します。
開発プロセスでは、
idlコマンドを
-Pおよび
-iの各オプションを指定して使用し、コールバック・オブジェクトを定義するOMG IDLファイルをコンパイルします。たとえばChat Roomサンプル・アプリケーションでは、
chatclient.idlファイルがOMG IDLファイルです。各オプションは、次のように動作します。 
        
          
            | • | -Pオプションを指定すると、PortableServer::ServantBase クラスから直接継承したスケルトン・クラスが作成されます。PortableServer::ServantBase からの継承は、共同クライアント/サーバー・アプリケーションが明示的にコールバック・オブジェクトのサーバントを作成し、そのサーバントの状態を初期化する必要があることを意味しています。activate_object およびdeactivate_object メソッドはPortableServer::ServantBase クラスのメンバーであるため、コールバック・オブジェクトのサーバントでは使用できません。 | 
        
       
      
        
          
            | • | -iオプションを指定すると、実装テンプレート・ファイルが生成されます。このファイルは、ListenerオブジェクトのOMG IDLで定義されたインタフェースを実装するコードのテンプレートです。 | 
        
       
      次に、Oracle Tuxedoサーバー・アプリケーションのインタフェースを定義するOMG IDLファイルをコンパイルする必要があります(たとえば、Chat Roomサンプル・アプリケーションの
chatroom.idlファイル)。このOMG IDLファイルをコンパイルするには、
idlコマンドを
-iオプションのみ指定して使用します。
表2-3に、
idlコマンドによって作成されるファイルの一覧を示します。
 
      
        
          
            | 
                注意: 
               | Chat Roomサンプル・アプリケーションでは、ChatClient.idl およびChatRoom.idl の各ファイル用に生成されたテンプレート・ファイルは、それらによって実装されるオブジェクト(ListenerおよびModerator)を反映するよう名前を変更されています。また、Moderatorオブジェクト用のテンプレート・ファイルには、ModeratorFactoryオブジェクトの実装が含まれています。 | 
        
       
      
      
        
          
        
        
          |  | idlコマンドで作成されるChat Roomサンプル・アプリケーションのファイル |  | 
        
          |  | Listener_c.cppListener_c.h
 Moderator_c.cpp
 Moderator_c.h
 | OMG IDLファイルで指定した各インタフェース用のクライアント・スタブが含まれます。クライアント・スタブは、オブジェクトにリクエストを送信するために使用されます。 | 
        
          |  | Listener_i.cppModerator_i.cpp
 | OMG IDLファイルで指定されたListener 、Moderator およびModeratorFactory インタフェースの操作を実装するメソッドのシグネチャを格納します。Listener_i.h ファイルには、POA_ChatClient::Listener クラスから継承した実装ファイルが含まれています。 | 
        
          |  | Listener_s.cppListener_s.h
 Moderator_s.cpp
 Moderator_s.h
 | OMG IDLファイルで指定した各インタフェース用のスケルトンが含まれます。実行時に、スケルトンではクライアントのリクエストをサーバー・アプリケーションの適切な操作にマッピングします。Listener_s.h ファイルには、POA_skeleton クラス定義(たとえば、POA_ChatClient::Listener )が含まれています。 | 
      
      
      ステップ3:各オブジェクトのオペレーションを実装するメソッドの記述
各OMG IDLファイルをコンパイルしたら、各オブジェクトのオペレーションを実装するメソッドを記述する必要があります。共同クライアント/サーバー・アプリケーションでは、コールバック・オブジェクト(つまりListenerオブジェクト)の実装ファイルを記述します。コールバック・オブジェクトの実装は、ほかのCORBAオブジェクトの実装と同じように記述しますが、TPフレームワークのかわりにPOAを使用する点が異なります。また、Oracle Tuxedoサーバー・アプリケーションのOracle Tuxedoオブジェクト(ModeratorおよびModeratorFactoryオブジェクト)の実装ファイルも記述します。
        
          
            | • | OMG IDLファイルで指定された各オペレーションのメソッド宣言 | 
        
       
      
      
        
          
            | • | 各インタフェースの実装のコンストラクタ(実装は任意) | 
        
       
      
        
          
            | • | オプションとして、Oracle Tuxedoオブジェクト用のcom.beasys.Tobj_Servant.activate_object メソッドおよびcom.beasys.Tobj_Servant.deactivate_object メソッド | 
        
       
      activate_objectメソッドおよび
deactivate_objectメソッド内では、オブジェクトのアクティブ化または非アクティブ化に関連する特定の手順を実行するコードを記述します。 
 
      リスト2-3はListenerオブジェクトの実装ファイルを、
リスト2-4はModeratorおよびModeratorFactoryオブジェクトの実装ファイルを示します。 
 
      
        
          
            | 
                注意: 
               | ModeratorおよびModeratorFactoryオブジェクトの実装ファイルには、メソッドとデータがさらに追加されています。実装ファイルのテンプレートは、idl -i コマンドによって作成されています。 | 
        
       
      リスト2-3 
Listenerオブジェクトの実装ファイル
// This module contains the definition of the implementation class
// Listener_i
#ifndef _Listener_i_h
#define _Listener_i_h
#include "ChatClient_s.h"
class Listener_i : public POA_ChatClient::Listener {
       public:
              Listener_i ();
              virtual ~Listener_i();
              void post (
                     const char * from,
                     const char * output_line); 
...
};
#endif
      
      リスト2-4 
ModeratorおよびModeratorFactoryオブジェクトの実装ファイル
// This module contains the definitions of the implementation class
// Moderator and ModeratorFactory
#ifndef _Moderator_i_h
#define _Moderator_i_h
#include "ChatRoom_s.h"
const int CHATTER_LIMIT = 5;
// the most chatters allowed
class Moderator_i : public POA_ChatRoom::Moderator {
       public:
       //Define the operations
       void signon ( const char*      who,
                     ChatClient::Listener_ptr   	callback_ref); 
       void send ( const char *       who,
                   const char *       input_line); 
       void signoff ( const char * who); 
       //Define the Framework functions
       virtual void activate_object  ( const char* stroid );
       virtual void deactivate_object( const char* stroid,
                                   TobjS::DeactivateReasonValue 
                                   reason);
       private:
       // Define function to find name on list
       int find( const char * handle ); 
       // Define name of the chat room overseen by the Moderator
       char* m_chatroom_name;
       // Data for maintaining list
       // Chatter[n] id
       CORBA::String              chatters[CHATTER_LIMIT];  
       // Chatter[n] callback ref
       ChatClient::Listener_var callbacks[CHATTER_LIMIT]; 
};
class ModeratorFactory_i : public POA_ChatRoom::ModeratorFactory { 
       public:
        ChatRoom::Moderator_ptr get_moderator ( const char* 
                                                 chatroom_name ); 
};
#endif
      
      ステップ4:共同クライアント/サーバー・アプリケーションのクライアント部分の記述
共同クライアント/サーバー・アプリケーションの開発では、そのクライアント部分をOracle Tuxedoクライアント・アプリケーションと同じように記述します。クライアント・アプリケーションには、次の処理を行うコードを含める必要があります。 
        
          
            | 1.	 | ORBを初期化します。Oracle Tuxedoシステムは、適正なプロトコルを使用してORBをアクティブ化します。この場合、該当するプロトコルはIIOPです。 | 
        
       
      
        
          
            | 2.	 | Bootstrapオブジェクトを使用して、Oracle Tuxedoのドメインとの通信を確立します。 | 
        
       
      
        
          
            | 3.	 | FactoryFinderオブジェクトへの初期参照を解決します。 | 
        
       
      
        
          
            | 4.	 | ファクトリを使用して、目的のOracle Tuxedo オブジェクト(つまりModeratorオブジェクト)のオブジェクト参照を取得します。 | 
        
       
      
        
          
            | 
                注意: 
               | Oracle Tuxedo製品のうち、CORBA環境のリリース8.0には、Oracle WebLogic Enterpriseの旧リリースで提供されていたOracleクライアント環境オブジェクトが引き続き含まれており、Oracle Tuxedo 8.0 CORBAクライアントでも使用できます。Oracle Tuxedo 8.0クライアントは、これらの環境オブジェクトを使用して、ブートストラップ処理、セキュリティ、およびトランザクション・オブジェクトへの初期参照を解決する必要があります。このリリースでは、OMG Interoperable Naming Service (INS)を使用してブートストラップ処理、セキュリティ、およびトランザクション・オブジェクトへの初期参照を解決するためのサポートが追加されています。INSの詳細は、『CORBAプログラミング・リファレンス』 の「CORBAブートストラップ処理のプログラミング・リファレンス」を参照してください。 | 
        
       
      クライアントの開発手順は、
リスト2-5で説明します。これには、Chat Roomサンプル・アプリケーションのコードが含まれます。Chat Roomサンプル・アプリケーションでは、共同クライアント/サーバー・アプリケーションのクライアント部分がファクトリを使用してModeratorオブジェクトへのオブジェクト・リファレンスを取得し、次にModeratorオブジェクトの
signon、
sendおよび
signoffメソッドを呼び出します。
リスト2-5 
Chat Room共同クライアント/サーバー・アプリケーションのクライアント部分
...
// Initialize the ORB
orb_ptr = CORBA::ORB_init(argc, argv, "BEA_IIOP");
// Create a Bootstrap object to establish communication with the
// domain
bootstrap = new Tobj_Bootstrap(orb_ptr,"");
// Get a FactoryFinder object, use it to find a Moderator factory,
// and get a Moderator.
// Use the Bootstrap object to find the FactoryFinder object
CORBA::Object_var var_factory_finder_oref =
          bootstrap->resolve_initial_references("FactoryFinder");
// Narrow the FactoryFinder object
Tobj::FactoryFinder_var var_factory_finder =
       Tobj::FactoryFinder::_narrow(var_factory_finder_oref.in());
// Use the FactoryFinder object to find a factory for the Moderator
CORBA::Object_var var_moderator_factory_oref =
       var_factory_finder->find_one_factory_by_id( 
       "ModeratorFactory" );
// Narrow the Moderator Factory
ChatRoom::ModeratorFactory_var var_moderator_factory =
       ChatRoom::ModeratorFactory::_narrow( 
       var_moderator_factory_oref.in() );
// Get a Moderator
// The chatroom name is passed as a command line parameter
var_moderator_oref =
            var_moderator_factory->get_moderator
            (var_chat_room_name.in() );   
...
      
      ステップ5:コールバック・ラッパー・オブジェクトを使用したコールバック・オブジェクトの作成
コールバック・オブジェクトの基本的な作成手順は常に同じであるため、Oracle Tuxedo製品ではコールバック・オブジェクトの開発を簡略化するコールバック・ラッパー・オブジェクトを提供しています。 
コールバック・ラッパー・オブジェクトは、次のことを行います。
        
          
            | • | コールバック・オブジェクトのオブジェクト・ポリシーを定義します。次のオブジェクト・ポリシーがサポートされています。 | 
        
       
      
      
        
          
            | • | 永続/システムID (_persistent/systemid) | 
        
       
      
        
          
            | • | 永続/ユーザーID (_persistent/userid) | 
        
       
      
      
        
          
            | • | コールバック・オブジェクトのサーバントを作成します。 | 
        
       
      
        
          
            | • | ORBおよびPOAを、コールバック・オブジェクトに対するリクエストを受け付ける状態に設定します。 | 
        
       
      
        
          
            | • | アクティブ化されたコールバック・オブジェクトのオブジェクト参照を返します。オブジェクトIDはシステムで生成することも、ユーザーが指定することもできます。 | 
        
       
      
        
          
            | • | 単一のサーバントまたはすべてのアクティブなサーバントに対するリクエストの受け付けを停止するようORBに指示します。 | 
        
       
      コールバック・ラッパー・オブジェクトおよびそのメソッドの完全な説明については、
『CORBAプログラミング・リファレンス』を参照してください。
リスト2-6では、Chat Roomサンプル・アプリケーションでのコールバック・ラッパー・オブジェクトの使用方法を示します。
 
      リスト2-6 
Chat Roomサンプル・アプリケーションでのコールバック・ラッパー・オブジェクトの使用方法
...
// Use the Callbacks object to create a servant for the 
// Listener object, activate the Listener object, and create an 
// object reference for the Listener object.
BEAWrapper::Callbacks* callbacks = 
                       new BEAWrapper::Callbacks( orb_ptr );
Listener_i * listener_callback_servant = new Listener_i();
CORBA::Object_var v_listener_oref=callbacks->start_transient(
                                listener_callback_servant,
                                ChatClient::_tc_Listener->id());
ChatClient::Listener_var v_listener_callback_oref =
                                ChatClient::Listener::_narrow(
                                var_listener_oref.in());
...
      
      ステップ6:コールバック・オブジェクトの参照を渡すことによるオブジェクトのオペレーションの呼出し
コールバック・オブジェクトのオブジェクト参照を取得したら、そのコールバック・オブジェクト参照をOracle Tuxedoオブジェクトのメソッドにパラメータとして渡すことができます。Chat Roomサンプル・アプリケーションでは、Moderatorオブジェクトは
signonメソッドへのパラメータとして、Listenerオブジェクトのオブジェクト参照を使用します。
リスト2-7では、この手順を示します。
// Sign on to the Chat room using a user-defined handle and a
// reference to the Listener object (the callback object) to receive
// input from other client applications logged into the Chat room.
var_moderator_reference->signon(handle,
                                 var_listener_callback_oref.in() );
      
      
      IIOPを使用するリモート共同クライアント/サーバー・アプリケーションを実行する場合は、次のようにコールバック・オブジェクトのオブジェクト参照にホストおよびポート番号が含まれている必要があります。 
        
          
            | • | 一時コールバック・オブジェクトの場合、任意の有効なポート番号(TCP/IPで定義)を使用できまります。この番号は、ORBによって動的に取得できます。  | 
        
       
      
        
          
            | • | 永続コールバック・オブジェクトの場合、コールバック・オブジェクトのオブジェクト参照が作成されたのと同じポートでコールバック・オブジェクトへのリクエストを受け付けるように、ORBを設定する必要があります。  | 
        
       
      ポート番号の指定は、動的範囲ではなくユーザー範囲から行ってください。ユーザー範囲からポート番号を割り当てることで、共同クライアント/サーバー・アプリケーションで使用するポートの不整合を回避できます。使用する共同クライアント/サーバー・アプリケーション用に特定のポートを指定するには、共同クライアント/サーバー・アプリケーションのためのプロセスを開始するコマンド行に、次を含めます。
ここで、
nnnは共同クライアント/サーバー・アプリケーション内のコールバック・オブジェクトに対する呼出しを生成およびリスニングする際にORBによって使用されるポートの数です。 
このコマンドは、共同クライアント/サーバー・アプリケーション内のコールバック・オブジェクトのオブジェクト参照を永続的なものにする場合、および共同クライアント/サーバー・アプリケーションを停止して再起動する場合に使用します。このコマンドを使用しない場合、ORBではランダムなポートが使用されます。共同クライアント/サーバー・アプリケーションを停止してから再起動すると、その共同クライアント/サーバー・アプリケーション内のコールバック・オブジェクトへの呼出しは失敗します。
ポート番号は、
CORBA::orb_initメンバー関数の
argv引数への入力の一部です。
argv引数が渡されると、ORBがその情報を読み取り、そのプロセス中に作成されるすべてのオブジェクト参照用のポートを確立します。また、同じ目的にブートストラップ・オブジェクトの
register_callback_portオペレーションを使用することもできます。
共同クライアント/サーバー・アプリケーションが同じドメイン内のOracle Tuxedoオブジェクトと通信するには、サーバー・アプリケーションの構成ファイルが必要です。この構成ファイルは、サーバー・アプリケーション開発の一環として記述します。構成ファイルのバイナリ・バージョンであるTUXCONFIGファイルは、共同クライアント/サーバー・アプリケーションを起動する前に存在している必要があります。
TUXCONFIGファイルは、
tmloadcfコマンドを使用して作成されます。
TUXCONFIGファイルの作成については、
『Oracle Tuxedo CORBAアプリケーション・スタート・ガイド』および
『Oracle Tuxedoアプリケーションの設定』を参照してください。
 
      使用する共同クライアント/サーバー・アプリケーションでIIOPバージョン1.0または1.1が使用されている場合、管理者はIIOPサーバー・ハンドラ(ISH)に接続されていないコールバック・オブジェクトをアウトバウンドIIOPが呼び出すことを可能にする起動パラメータを指定して、IIOPサーバー・リスナー(ISL)をブートする必要があります。ISLコマンドの-Oオプションを指定すると、アウトバウンドIIOPが有効になります。パラメータを追加すると、管理者はOracle Tuxedoアプリケーションに最適な構成を得ることができます。ISLコマンドの詳細は、
『Oracle Tuxedoコマンド・リファレンス』を参照してください
 
      ステップ8:共同クライアント/サーバー・アプリケーションのコンパイル
共同クライアント/サーバー・アプリケーション開発の最終手順は、実行可能プログラムの生成です。これを行うには、スケルトンおよびクライアント・スタブに対してコードおよびリンクをコンパイルする必要があります。
buildobjclientコマンドを
-Pオプションを指定して使用し、共同クライアント/サーバー・アプリケーションの実行可能プログラムを生成します。実行可能プログラムをビルドするには、コマンドによりOracle Tuxedoオブジェクトのクライアント・スタブ、コールバック・オブジェクトのクライアント・スタブ、コールバック・オブジェクトのスケルトン、およびコールバック・オブジェクトの実装を、適切なPOAライブラリと組み合せます。
 
      
        
          
            | 
                注意: 
               | buildobjclientコマンドの-P オプションを使用するには、コールバック・オブジェクトのスケルトンとクライアント・スタブを作成したときにidl コマンドの-P オプションを使用しておく必要があります。 | 
        
       
      POAの使用によるコールバック・オブジェクトの作成
POAを直接使用してコールバック・オブジェクトを作成できます。POAを直接使用するのは、コールバック・ラッパー・オブジェクトからでは利用できないPOA機能およびオブジェクト・ポリシーを使用する場合です。たとえば、POAの最適化機能を使う場合は、POAを直接使用する必要があります。次のトピックでは、POAを使用して、サポートされているオブジェクト・ポリシーを備えたコールバック・オブジェクトを作成する方法を説明します。
        
          
            | 
                注意: 
               | Oracle Tuxedo製品のこのバージョンでサポートされているのは、POAインタフェースのサブセットのみです。サポートされているインタフェースのリストについては、『CORBAプログラミング・リファレンス』 を参照してください。 | 
        
       
      一時オブジェクト・ポリシーを備えたコールバック・オブジェクトの作成
POAを使用して一時オブジェクト・ポリシーを備えたコールバック・オブジェクトを作成するには、次のことを行うコードを記述する必要があります。
子POAを作成する必要があるのは、ルートPOAでは双方向IIOPを使用できないためです。子POAでは
LifespanPolicy (TRANSIENT)および
IDAssignmentPolicy (
SYSTEM)のデフォルト値を使用できます。
BOTHの
BiDirPolicyポリシーを指定する必要があります。
IIOPバージョン1.2は、入力されるリクエストと出力されるリクエストの双方についてTCP/IP接続の再利用をサポートします。TCP/IP接続の再利用の許可を選択するのは、ORBです。再利用を許可するには、TCP/IP接続の再利用を許可するORBポリシー・オブジェクトを作成し、ポリシー・リスト内のポリシー・オブジェクトをORB初期化時に使用します。ポリシー・オブジェクトは、
CORBA::ORB::create_policyオペレーションを使用して作成します。
CORBA::ORB::create_policyオペレーションの詳細は、
『CORBAプログラミング・リファレンス』を参照してください。
        
          
            | 3.	 | コールバック・オブジェクトのサーバントを作成します。 | 
        
       
      
        
          
            | 4.	 | サーバントでコールバック・オブジェクトに対するリクエストを受け付ける準備ができていることをPOAに通知します。  | 
        
       
      この手順では、共同クライアント/サーバー・アプリケーションが、オブジェクトIDを使用してPOAのコールバック・オブジェクトをアクティブ化します。
        
          
            | 6.	 | コールバック・オブジェクトのオブジェクト参照を作成します。 | 
        
       
      
        
          
            | 7.	 | コールバック・オブジェクトのオブジェクト参照を、Oracle Tuxedoオブジェクトの1つのメソッドへのパラメータとして使用し、Oracle Tuxedoオブジェクトに対して呼出しを行います。 | 
        
       
      リスト2-8では、POAを使用してListenerオブジェクトを作成するChat Roomサンプル・アプリケーションの一部を示します。
 
      リスト2-8 
POAの使用によるListenerオブジェクトの作成
// Establish communication with the POA
orb_ptr = CORBA::ORB_init(argc, argv, "BEA_IIOP");
CORBA::PolicyList policy_list(1);
CORBA::Any val;
CORBA::Object_ptr o_init_poa;
o_init_poa = orb_ptr->resolve_initial_references("RootPOA");
// Narrow to get the Root POA
root_poa_ptr = PortableServer::POA::_narrow(o_init_poa);
CORBA::release(o_init_poa);
// Specify an IIOP Policy of Bidirectional for the POA
val <<= BiDirPolicy::BOTH;
CORBA::Policy_ptr bidir_pol_ptr = 	orb_ptr->create_policy(
                       BiDirPolicy::BIDIRECTIONAL_POLICY_TYPE, val);
policy_list.length ( 1 );
policy_list[0] = bidir_pol_ptr;
// Create the BiDirectional POA
bidir_poa_ptr = root_poa_ptr->create_POA("BiDirPOA", 
                                          root_poa_ptr->
                                          the_POAManager(),
                                          policy_list);
// Activate the POA
root_poa_ptr->the_POAManager()->activate();
// Create the Listener object
ChatClient::Listener_var v_listener_callback_ref;
// Create a servant for Listener object and activate it
listener_callback_servant = new Listener_i();
  CORBA::Object_var           v_listener_oref;
  PortableServer::ObjectId_var temp_OId =
     bidir_poa_ptr ->activate_object(listener_callback_servant );
// Create object reference for the Listener object with a 
      // system generated Object Id
v_listener_oref = bidir_poa_ptr->create_reference_with_id
                                 (temp_OId, 		   
                                 ChatClient::_tc_Listener->id() );
v_listener_callback_ref = ChatClient::Listener::_narrow
                                 ( v_listener_oref.in() );
      
      永続/ユーザーIDオブジェクト・ポリシーを備えたコールバック・オブジェクトの作成
POAを使用して永続/ユーザーIDオブジェクト・ポリシーを備えたコールバック・オブジェクトを作成するには、次のことを行うコードを記述する必要があります。
        
          
            | 1.	 | ユーザーIDを格納する文字列を使用し、それをオブジェクトIDに変換します。 | 
        
       
      
        
          
            | 2.	 | LifespanPolicyがPERSISTENT に設定され、IDAssignmentPolicy がUSERID に設定された子POAを作成します。 | 
        
       
      
        
          
            | 3.	 | Listenerオブジェクトのサーバントを作成します。 | 
        
       
      
        
          
            | 4.	 | Listenerオブジェクトの文字列化されたオブジェクトIDとリポジトリIDを使用して、Listenerオブジェクトのオブジェクト参照を作成します。 | 
        
       
      
        
          
            | 5.	 | Listenerオブジェクトをアクティブ化します。 | 
        
       
      
        
          
            | 
                注意: 
               | 永続/ユーザーIDオブジェクト・ポリシーは、リモート共同クライアント/サーバー・アプリケーション、つまりOracle Tuxedoドメイン内には存在しない共同クライアント/サーバー・アプリケーションでのみ使用されます。 | 
        
       
      
      
        
          
            | 
                注意: 
               | このサンプル・コードでは、双方向IIOPを使用しません。 | 
        
       
      リスト2-9 
永続/ユーザーIDオブジェクト・ポリシーを備えたListenerオブジェクトのサンプル・コード
// Declare a string and convert it to an object Id.
const char* oid_string = "783";
PortableServer::ObjectID_var oid=
              PortableServer::string_to_ObjectId(oid_string);
// Find the root POA
CORBA::Object_var oref =
              orb_ptr->resolve_initial_references("RootPOA");
PortableServer::POA_var root_poa =
              PortableServer::POA::_narrow(oref);
// Create and activate a Persistent/UserID POA
CORBA::PolicyList policies(2);
policies.length(2);
policies[0] = root_poa->create_lifespan_policy(
              PortableServer::PERSISTENT);
policies[1] = root_poa->create_id_assignment_policy(
              PortableServer::USER_ID );
PortableServer::POA_var poa_ref =
              root_poa->create_POA("poa_ref", 	
              root_poa->the_POAManager(),policies);
root_poa->the_POAManager()->activate();
// Create object reference for the Listener object.
oref = poa_ref->create_reference_with_id(oid,
              ChatClient::_tc_Listener->id());
ChatClient::Listener_ptr Listener_oref =
              ChatClient::Listener::_narrow( oref );
// Create Listener_i servant and activate the Listener object
Listener_i* my_Listener_i = new Listener_i();
poa_ref->activate_object_with_id( oid, my_Listener_i);
// Make call passing the reference to the Listener object
v_moderator_ref->signon( handle, Listener_oref);
      
      永続/システムIDオブジェクト・ポリシーを備えたコールバック・オブジェクトの作成
POAを使用して永続/システムIDオブジェクト・ポリシーを備えたコールバック・オブジェクトを作成するには、次のことを行うコードを記述する必要があります。
        
          
            | 1.	 | LifespanPolicyがPERSISTENT に設定され、IDAssignmentPolicy がデフォルトに設定された子POAを作成します。 | 
        
       
      
        
          
            | 2.	 | Listenerオブジェクトのサーバントを作成します。 | 
        
       
      
        
          
            | 3.	 | システム生成のオブジェクトID (ListenerオブジェクトのリポジトリID)を使用して、Listenerオブジェクトのオブジェクト参照を作成します。 | 
        
       
      
        
          
            | 4.	 | Listenerオブジェクトをアクティブ化します。 | 
        
       
      
        
          
            | 
                注意: 
               | 永続/システムIDオブジェクト・ポリシーは、リモート共同クライアント/サーバー・アプリケーション、つまりOracle Tuxedoドメイン内には存在しない共同クライアント/サーバー・アプリケーションでのみ使用されます。 | 
        
       
      
      リスト2-10 
永続/システムIDオブジェクト・ポリシーを備えたListenerオブジェクトのサンプル・コード
// Find the root POA
CORBA::Object_var oref=
       orb_ptr->resolve_initial_references("RootPOA")
PortableServer::POA_var root_poa =
       PortableServer::POA::_narrow(oref);
// Create and activate a Persistent/System ID POA
CORBA::PolicyList policies(1);
policies.length(1);
policies[0] = root_poa->create_lifespan_policy(
       PortableServer::PERSISTENT);
//
IDAssignmentPolicy is the default so you do not need to specify it
PortableServer::POA_var poa_ref = root_poa->create_POA(
       "poa_ref", root_poa->the_POAManager(), policies);
root_poa->the_POAManager()->activate();
// Create Listener_i servant and activate the Listener object
Listener_i* my_Listener_i = new Listener_i();
PortableServer::ObjectId_var temp_OId =
       poa_ref->activate_object ( my_Listener_i );
// Create object reference for Listener object with returned
// system object Id
oref = poa_ref->create_reference_with_id(
       temp_OId, ChatClient::_tc_Listener->id() );
ChatClient::Listener_var Listener_oref =
       ChatClient::Listener::_narrow(oref);
// Make the call passing the reference to the Listener object
v_moderator_ref->signon( handle, Listener_oref );
      
      C++共同クライアント/サーバー・アプリケーションのスレッドに関する留意事項
共同クライアント/サーバー・アプリケーションは、まずクライアント・アプリケーションとして機能し、次にサーバー・アプリケーションとして機能するように切り替わることができます。そのために、共同クライアント/サーバー・アプリケーションでは、次の呼出しを行うことにより、スレッドの完全な制御をORBに提供します。 
共同クライアント/サーバー・アプリケーションのサーバー部分のメソッドが
ORB::shutdown()を呼び出すと、サーバーのアクティビティはすべて停止し、共同クライアント/サーバー・アプリケーションのサーバー部分で
ORB::run()が呼び出されると、制御はステートメントに返されます。制御が共同クライアント/サーバー・アプリケーションのクライアント機能に返されるのは、この条件においてのみです。
クライアント・アプリケーションにはスレッドが1つしかないため、共同クライアント/サーバー・アプリケーションのクライアント機能とサーバー機能で、中央演算処理装置(CPU)を共有する必要があります。この共有は、ORBをときどき確認して、共同クライアント/サーバー・アプリケーションに、実行すべきサーバー・アプリケーション作業があるかどうかを調べることによって行われます。ORBの確認を実行するには、次のコードを使用します。
if ( orb->work_pending() ) orb->perform_work(); 
      ORBはサーバー・アプリケーションの作業を完了すると、共同クライアント/サーバー・アプリケーションに戻ります。共同クライアント/サーバー・アプリケーションはその後、クライアント・アプリケーション機能を実行します。共同クライアント/サーバー・アプリケーションでは、ORBの不定期な確認を、確実に行う必要があります。行われない場合、共同クライアント/サーバー・アプリケーションは呼出しをまったく処理しません。
共同クライアント/サーバー・アプリケーションがリクエストをブロックしている間は、ORBがコールバックを扱うことはできません。共同クライアント/サーバー・アプリケーションが別のOracle Tuxedoサーバー・アプリケーションのオブジェクトを呼び出した場合、ORBはレスポンス待機中にブロックします。ブロック中のORBはコールバックを扱うことができないため、リクエストが完了するまでコールバックはキュー入れられます。
Chat Roomサンプル・アプリケーションのビルドと実行
Chat Roomサンプル・アプリケーションをビルドして実行するには、次の手順に従います。
        
          
            | 1.	 | Chat Roomサンプル・アプリケーションのファイルを作業ディレクトリにコピーします。 | 
        
       
      
        
          
            | 2.	 | Chat Roomサンプル・アプリケーションのファイルの保護属性を変更します。 | 
        
       
      
      
      
      Chat Roomサンプル・アプリケーション用ファイルの作業ディレクトリへのコピー
Chat Roomサンプル・アプリケーションのファイルを、ローカル・マシンの作業ディレクトリにコピーする必要があります。Chat Roomサンプル・アプリケーションのファイルは、次のディレクトリに格納されています。
drive:\TUXDIR\samples\corba\chatroom 
      
      /usr/local/TUXDIR/samples/corba/chatroom 
      Chat Roomサンプル・アプリケーションをビルドして実行するには、
表2-4に示すファイルを使用します。
        
          表2-4 
Chat Roomサンプル・アプリケーションに含まれるファイル
          |  |  | 
        
          |  | ModeratorおよびModeratorFactory インタフェースを宣言する、OMG IDLコード。 | 
        
          |  | Listenerインタフェースを宣言するOMG IDLコード。 | 
        
          | Listener_i.hListener_i.cpp
 | 共同クライアント/サーバー・アプリケーションのListenerオブジェクトのメソッド実装用C++ソース・コード。 | 
        
          | Moderator_i.hModerator_i.cpp
 | Oracle Tuxedoサーバー・アプリケーションのModeratorおよびModeratorFactoryオブジェクトのメソッド実装用C++ソース・コード。 | 
        
          |  | 共同クライアント/サーバー・アプリケーションのC++ソース・コード。 | 
        
          |  | Oracle Tuxedoサーバー・アプリケーションのC++ソース・コード。 | 
        
          | KeyboardManager.hKeyboardManager.cpp
 | Chat Roomサンプル・アプリケーションでキーボードからの入力を処理するC++ソース・コード。このコードは、ChatClientMain.cpp によって使用されます。 | 
        
          |  | Chat Roomサンプル・アプリケーションにおけるOracle Tuxedoサーバー・アプリケーションのModeratorおよびModeratorFactoryオブジェクトの実装構成ファイル(ICF)。 | 
        
          |  | UNIXシステムで、環境変数を設定してChat Roomサンプル・アプリケーションをビルドするスクリプト。 | 
        
          |  | Windowsシステムで、環境変数を設定してChat Roomサンプル・アプリケーションをビルドするコマンド・プロシージャ。 | 
        
          |  | Chat Roomサンプル・アプリケーション用の、UNIXオペレーティング・システムのmakefile 。 | 
        
          |  | Chat Roomサンプル・アプリケーション用の、Windowsオペレーティング・システムのmakefile 。 | 
        
          |  | Chat Roomサンプル・アプリケーションのビルドと実行に関する最新情報を示したファイル。 | 
      
      Chat Roomサンプル・アプリケーションのファイルに対する保護属性の変更
Oracle Tuxedoソフトウェアのインストール時には、サンプル・アプリケーションは読取り専用に設定されています。Chat Roomサンプル・アプリケーションのファイルを編集またはビルドするには、作業ディレクトリにコピーしたファイルの保護属性を次のように変更しておく必要があります。
prompt> attrib /S -r drive:\workdirectory\*.* 
      
      
      ksh prompt> chmod u+w /workdirectory/*.* 
      UNIXオペレーティング・システムのプラットフォームでは、次のように
ChatRoom.kshのパーミッションも変更して、ファイルの実行許可を付与する必要があります。
ksh prompt> chmod +x ChatRoom.ksh 
      
      Chat Roomサンプル・アプリケーションをビルドして実行する前に、システムで
TUXDIR環境変数が設定されていることを確認する必要があります。ほとんどの場合、この環境変数はインストール手順の一環として設定済です。
TUXDIR環境変数は、Oracle Tuxedoソフトウェアをインストールしたディレクトリ・パスを定義します。例:
インストール中に定義された環境変数の情報が正しいことを確認するには、次の手順に従います。
        
          
            | 1.	 |  「スタート」メニューの、「設定」をポイントします。 | 
        
       
      
        
          
            | 2.	 |  「設定」メニューから、「コントロール・パネル」をクリックします。 | 
        
       
      
      
      「システムのプロパティ」ウィンドウが表示されます。
ksh prompt>printenv TUXDIR 
      
      
      
        
          
            | 1.	 |  [システムのプロパティ]ウィンドウの[環境]ページで、TUXDIR 環境変数をクリックします。 | 
        
       
      
      
      
      ksh prompt>export TUXDIR=directorypath 
      
       ChatSetupコマンドを使用すると、次の手順を自動化できます。
 
      
      
      
        
          
            | 3.	 | クライアント・アプリケーションのコードをコンパイルします。 | 
        
       
      
        
          
            | 4.	 | サーバー・アプリケーションのコードをコンパイルします。 | 
        
       
      ChatSetupコマンドを実行する前に、次のことを確認する必要があります。
 
      
        
          
            | • | アプリケーションのビルドおよび実行を行う適切な管理者権限があること。 | 
        
       
      
        
          
            | • | 使用しているマシンのパスにnmake が存在すること。 | 
        
       
      
        
          
            | • | UNIXの場合は、PATH 変数にmake 実行可能プログラムが含まれていること。 | 
        
       
      サンプル・アプリケーションをビルドして実行するには、次のように
ChatSetupコマンドを入力します。
ksh prompt> cd workdirectory 
      ksh prompt> ./ChatSetup.ksh 
      
      次のコマンドを入力して、Chat Roomサンプル・アプリケーションにおけるサーバー・アプリケーションとシステム・サーバーのプロセスを開始します。
このコマンドを入力すると、次のサーバー・プロセスが開始されます。
システムのEventBrokerです。このサーバー・プロセスを使用するのは、Oracle Tuxedoシステムのみです。
次の3つの
TMFFNAMEサーバー・プロセスが開始されます。
        
          
            | • | -Nおよび-M オプションを指定して開始されたTMFFNAME サーバー・プロセスは、マスターNameManagerサービス。NameManagerサービスは、アプリケーションによって指定された名前のオブジェクト参照へのマッピングを維持します。このサーバー・プロセスを使用するのは、Oracle Tuxedoシステムのみです。 | 
        
       
      
        
          
            | • | -Nオプションのみを指定して開始されたTMFFNAME サーバー・プロセスは、スレーブNameManagerサービス。 | 
        
       
      
        
          
            | • | -Fオプションを指定して開始されたTMFFNAME サーバー・プロセスには、FactoryFinderオブジェクトが含まれます。 | 
        
       
      
      Chat Roomサンプル・アプリケーションのためのサーバー・アプリケーション・プロセスです。
次のコマンドを入力して、Chat Roomサンプル・アプリケーションのクライアント・アプリケーションを起動します。
prompt> ChatClient chatroom_name -ORBport nnn 
      ここで、
chatroom_nameは接続するチャット・ルームの名前です。任意の値を入力できます。自分自身を識別するためのハンドルを入力するよう求められます。任意の値を入力できます。選択したハンドルが使用中の場合は、別のハンドルの入力を求められます。
Chat Roomサンプル・アプリケーションを使いやすいように最適化するには、同じチャット・ルーム名を使用する第2のクライアント・アプリケーションを実行します。
クライアント・アプリケーションを終了するには、
「\」と入力します。
Chat Roomサンプル・アプリケーションの停止
別のサンプル・アプリケーションを使用する前に、次のコマンドを入力してChat Roomサンプル・アプリケーションを停止し、作業ディレクトリから不要なファイルを削除します。
prompt> nmake -f ChatRoom.nt superclean 
      prompt> nmake -f ChatRoom.nt adminclean 
      
      ksh prompt> tmshutdown -y 
      ksh prompt> . ./Admin/setenv.ksh 
      ksh prompt> make -f ChatRoom.mk superclean 
      ksh prompt> make -f ChatRoom.nt adminclean