19.3.2 サンプル:client_server

<この項の構成>
(1) サンプルの目的
(2) コードの説明
(3) コンパイルの手順
(4) クライアントおよびサーバアプリケーションの実行または配置

(1) サンプルの目的

このサンプルでは,コードを変更しないで,既存のCORBAアプリケーションにポータブルインタセプタを追加する簡単な方法を実際に説明します。ポータブルインタセプタはクライアント側およびサーバ側の両方のどのアプリケーションにも追加できます。これは,ランタイム時に設定する指定のオプションやプロパティで,関連するアプリケーションを再実行することによって行えます。

使用するクライアントおよびサーバアプリケーションは,$VBROKERDIR/examples/vbe/basic/bank_agent(UNIX)または%VBROKERDIR%¥examples¥vbe¥basic¥bank_agent(Windows)にあるアプリケーションと類似しています。サンプル全体は抜粋であり,ポータブルインタセプタはランタイム構成時に追加されています。その理由は,VisiBrokerのインタセプタを熟知している開発者にVisiBrokerのインタセプタとOMG固有ポータブルインタセプタ間のコーディングを早く行える方法を提供するためです。

(2) コードの説明

(a) 必須パッケージのインポート

ポータブルインタセプタインタフェースを使用するには,関連パッケージまたはヘッダファイルが組み込まれている必要があります。Java ORBで,DuplicateNameやInvalidNameのようなポータブルインタセプタの例外を使用している場合,org.omg.PortableInterceptor.ORBInitInfoPackageはオプションであることに注意してください。

コードサンプル19-25 ポータブルインタセプタを使用する際の必須ヘッダファイル(C++)

#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"

コードサンプル19-26 ポータブルインタセプタを使用する際の必須パッケージ(Java)

import org.omg.PortableInterceptor.*;
import org.omg.PortableInterceptor.ORBInitInfoPackage.*;

まずクライアント側で,リクエストインタセプタの各部分の書き方について詳細に説明します。クライアント側のリクエストインタセプタをロードするには,インタフェースをインプリメントするクラスであるORBInitializerをインプリメントする必要があります。また,これは初期化を考慮するとサーバ側のリクエストインタセプタにも該当します。

次にこれをインプリメントするコードを示します。

コードサンプル19-27 クライアントリクエストインタセプタをロードするためのORBInitializerの正しい継承
C++の場合

class SampleClientLoader :
  public PortableInterceptor::ORBInitializer

Javaの場合

public class SampleClientLoader extends
  org.omg.CORBA.LocalObject implements ORBInitializer

コードサンプル19-28 サーバリクエストインタセプタをロードするためのORBInitializerの正しい継承
C++の場合

class SampleServerLoader :
  public PortableInterceptor::ORBInitializer

Javaの場合

public class SampleServerLoader extends
  org.omg.CORBA.LocalObject implements ORBInitializer

インタフェースをインプリメントするオブジェクトであるORBInitializerそれぞれもLocalObjectオブジェクトから継承される必要があることに注意してください。これが必要である理由は,ORBInitializerのIDL定義がキーワードであるlocalを使用するためです。IDLキーワードlocalの詳細については,「25. valuetypeの使用」を参照してください。

ORBの初期化時に,各リクエストインタセプタはpre_init()インタフェースのインプリメンテーションによって追加されています。このインタフェース内では,クライアントリクエストインタセプタは,add_client_request_interceptor()メソッドによって追加されています。関連するクライアントリクエストインタセプタ自身をORBに追加する前に,そのインタセプタが実体化される必要があります。

コードサンプル19-29 クライアント側リクエストインタセプタの初期化およびORBへの登録
C++の場合

public:
  void pre_init(PortableInterceptor::ORBInitInfo_ptr
   _info){
     SampleClientInterceptor *interceptor =
                                 new SampleClientInterceptor;
        try {
           _info->add_client_request_interceptor(interceptor);
           . . .

Javaの場合

public void pre_init(ORBInitInfo info){
  try {
     info.add_client_request_interceptor(new
                                   SampleClientInterceptor());
     . . .

OMG規格に従って,必須アプリケーションはregister_orb_initializerメソッドによってそれぞれのインタセプタを登録します。詳細については「19.3.2(2)(f) クライアントおよびサーバアプリケーションの開発」を参照してください。VisiBrokerには,このようなインタセプタの別のオプションの登録方法,(DLLによる登録など)があります。この登録方法を使用すると,アプリケーションはコードをまったく変更する必要がなく,その実行方法だけを変更すれば済むという利点があります。実行時の拡張オプションによって,インタセプタが登録され実行されます。オプションはVisiBroker 4.xインタセプタであるvbroker.orb.dynamicLibs=<DLL filename>と同様です。ここで,<DLL filename>はダイナミックリンクライブラリのファイル名であり,拡張子は,UNIXの場合は.so,.sl,.aなどで,Windowsの場合は.dllです。一つ以上のDLLファイルをロードするには,次のように各ファイル名をコンマ(,)で区切ります。

動的にインタセプタをロードするには,VISInitインタフェースが使用されます。これはVisiBroker 4.xインタセプタで使用されるものと同様です。詳細については「20. VisiBroker 4.xインタセプタの使用」を参照してください。ORB_initのインプリメンテーションでは,各インタセプタローダの登録は同様に行われます。

コードサンプル19-30 DLLのロードによるクライアント側のORBInitializerの登録(C++)

void ORB_init(int& argc,char* const* argv,CORBA::ORB_ptr orb)
{
  if(_bind_interceptors_installed)return;

  SampleClientLoader *client =new SampleClientLoader();
  PortableInterceptor::register_orb_initializer(client);

  . . .

クライアント側インタセプタローダの完全なインプリメンテーションを次に示します。

コードサンプル19-31 クライアント側インタセプタローダの完全なインプリメンテーション(C++)

//SampleClientLoader.C

#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"

#include "SampleClientInterceptor.h"

#if !defined(DLL_COMPILE )
#include "vinit.h"
#include "corba.h"
#endif

//USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

class SampleClientLoader :
  public PortableInterceptor::ORBInitializer
{
private:
  short int _interceptors_installed;

  #if defined(DLL_COMPILE )
  static SampleClientLoader _instance;
  #endif

public:
  SampleClientLoader(){
     _interceptors_installed =0;
  }

  void pre_init(PortableInterceptor::ORBInitInfo_ptr _info){
     if(_interceptors_installed)return;

     cout <<"=====>SampleClientLoader:Installing ..."<<endl;

     SampleClientInterceptor *interceptor =
                                new SampleClientInterceptor;

     try {
           _info->add_client_request_interceptor(interceptor);

           _interceptors_installed =1;
           cout <<"=====>SampleClientLoader:Interceptors loaded."
                <<endl;
     }
     catch(PortableInterceptor::ORBInitInfo::DuplicateName &e){
        cout <<"=====>SampleClientLoader:"
             <<e.name <<"already installed!"<<endl;
     }
     catch(...){
        cout <<"=====>SampleClientLoader:other exception occurred!"
             <<endl;
        }
     }

     void post_init(PortableInterceptor::ORBInitInfo_ptr _info){
  }
};

#if defined(DLL_COMPILE )

class VisiClientLoader :VISInit

{
private:
     static VisiClientLoader _instance;
     short int _bind_interceptors_installed;

public:
  VisiClientLoader():VISInit(1){
  _bind_interceptors_installed =0;
  }

  void ORB_init(int&argc,char*const*argv,CORBA::ORB_ptr orb){
     if(_bind_interceptors_installed)return;

     try {
           SampleClientLoader *client =new SampleClientLoader();
           PortableInterceptor::register_orb_initializer(client);

           _bind_interceptors_installed =1;
     }

     catch(const CORBA::Exception&e)
     {
        cerr <<e <<endl;
     }
  }
};

//static instance
VisiClientLoader VisiClientLoader::_instance;

#endif

コードサンプル19-32 クライアント側インタセプタローダの完全なインプリメンテーション(Java):SampleClientLoader.java

//SampleClientLoader.java

import org.omg.PortableInterceptor.*;
import org.omg.PortableInterceptor.ORBInitInfoPackage.*;

public class SampleClientLoader extends org.omg.CORBA.LocalObject
implements ORBInitializer
{
  public void pre_init(ORBInitInfo info){
     try {
        System.out.println("=====>SampleClientLoader:
                                                  Installing ...");
        info.add_client_request_interceptor
                                      (new SampleClientInterceptor());
        System.out.println("=====>SampleClientLoader:Interceptors
                                                            loaded.");
     }
     catch(DuplicateName dn){
        System.out.println("=====>SampleClientLoader:"+dn.name
                                               +"already installed.");
     }
     catch(Exception e){
        e.printStackTrace();
        throw new org.omg.CORBA.INITIALIZE(e.toString());
    }
  }

     public void post_init(ORBInitInfo info){
        //We do not do anything here.
     }
}

(b) サーバ側インタセプタでのORBInitializerのインプリメント

この段階では,クライアントリクエストインタセプタはすでに正しく実体化され,追加されているはずです。これ以降のコードサンプルは例外処理と結果表示だけを提供します。同様に,サーバ側のサーバリクエストインタセプタにも同じことが行われます。ただし,add_server_request_interceptor()メソッドを使用して関連サーバリクエストインタセプタをORBに追加することが異なります。

コードサンプル19-33 サーバ側リクエストインタセプタの初期化およびORBへの登録
C++の場合

public:
  void pre_init(PortableInterceptor::ORBInitInfo_ptr
   _info){
     SampleServerInterceptor *interceptor =
                                 new SampleServerInterceptor;
     try {
        _info->add_server_request_interceptor(interceptor);
        . . .

Javaの場合

public void pre_init(ORBInitInfo info){
  try {
     info.add_server_request_interceptor(
                               new SampleServerInterceptor());
     . . .

これは,サーバ側ORBInitializerクラスのDLLインプリメンテーションによるロードにも同様に適用されます。

コードサンプル19-34 DLLによってロードされるサーバ側リクエストORBInitializer(C++)

void ORB_init(int& argc,char* const* argv,CORBA::ORB_ptr orb)
{
  if(_poa_interceptors_installed)return;
  SampleServerLoader *server =new SampleServerLoader();
  PortableInterceptor::register_orb_initializer(server);
  . . .

サーバ側インタセプタローダの完全なインプリメンテーションを次に示します。

コードサンプル19-35 サーバ側インタセプタローダの完全なインプリメンテーション(C++)

//SampleServerLoader.C

#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"

#if defined(DLL_COMPILE )
#include "vinit.h"
#include "corba.h"
#endif

#include "SampleServerInterceptor.h"

//USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

class SampleServerLoader :
  public PortableInterceptor::ORBInitializer
{
private:
  short int _interceptors_installed;

public:
  SampleServerLoader(){
     _interceptors_installed =0;
  }

  void pre_init(PortableInterceptor::ORBInitInfo_ptr _info){
      if(_interceptors_installed)return;

      cout <<"=====>SampleServerLoader:Installing ..."<<endl;

      SampleServerInterceptor *interceptor =
                            new SampleServerInterceptor();

      try {
        _info->add_server_request_interceptor(interceptor);

        _interceptors_installed =1;
        cout <<"=====>SampleServerLoader:Interceptors loaded."
             <<endl;
      }
      catch(PortableInterceptor::ORBInitInfo::DuplicateName &e){
        cout <<"=====>SampleServerLoader:"
          <<e.name <<"already installed!"<<endl;
      }
      catch(...){
        cout <<"=====>SampleServerLoader:other exception occurred!"
          <<endl;
    }
  }
void post_init(PortableInterceptor::ORBInitInfo_ptr _info){}
};


#if defined(DLL_COMPILE )
class VisiServerLoader :VISInit
{
private:
  static VisiServerLoader _instance;
  short int _poa_interceptors_installed;

public:
  VisiServerLoader():VISInit(1){
  _poa_interceptors_installed =0;
}
void ORB_init(int& argc,char* const* argv,CORBA::ORB_ptr orb){
     if(_poa_interceptors_installed)return;
     try {
           SampleServerLoader *server =new SampleServerLoader();
           PortableInterceptor::register_orb_initializer(server);
           _poa_interceptors_installed =1;
     }
  catch(const CORBA::Exception&e)
     {
     cerr <<e <<endl;
     }
  }
};
//static instance
VisiServerLoader VisiServerLoader::_instance;

#endif

コードサンプル19-36 サーバ側インタセプタローダの完全なインプリメンテーション(Java):SampleServerLoader.java

//SampleServerLoader.java

import org.omg.PortableInterceptor.*;
import org.omg.PortableInterceptor.ORBInitInfoPackage.*;

public class SampleServerLoader extends org.omg.CORBA.LocalObject
implements ORBInitializer

{
  public void pre_init(ORBInitInfo info){
     try {
        info.add_server_request_interceptor(new
                 SampleServerInterceptor());
        System.out.println("=====>SampleServerLoader:
                 Interceptors loaded");
     }
     catch(DuplicateName dn){
        System.out.println("Interceptor:
                             "+dn.name +"already installed.");
     }
     catch(Exception e){
        e.printStackTrace();
        throw new org.omg.CORBA.INITIALIZE(e.toString());
     }
  }
  public void post_init(ORBInitInfo info){
     //We do not do anything here.
  }
}

(c) クライアント側およびサーバ側リクエストインタセプタでのRequestInterceptorのインプリメント

クライアント側またはサーバ側のリクエストインタセプタのインプリメンテーション時に,その両方に共通の別の二つのインタフェースをインプリメントする必要があります。それは,name()とdestroy()です。リクエストや応答でロードおよび呼び出しを行うインタセプタを正しく識別するためにORBに名前を提供するので,name()は重要です。CORBAの仕様に従うと,インタセプタはアノニマスでもかまいません。つまり,名前属性として空の文字列でもかまいません。このサンプルでは,SampleClientInterceptorという名前がクライアント側インタセプタに,SampleServerInterceptorという名前がサーバ側インタセプタに割り当てられています。

コードサンプル19-37 インタフェース属性,read-only属性名のインプリメンテーション
C++の場合

public:
  char *name(void){
     return _name;
}

Javaの場合

public String name(){
  return _name;
}

(d) クライアントでのClientRequestInterceptorのインプリメント

クライアントリクエストインタセプタでは,リクエストインタセプタが正しく動作するためにClientRequestInterceptorインタフェースをインプリメントする必要があります。クラスがインタフェースをインプリメントする場合,インプリメンテーションに関係なく五つのリクエストインタセプタメソッドがインプリメントされます。これにはsend_request()メソッド,send_poll()メソッド,receive_reply()メソッド,receive_exception()メソッド,およびreceive_other()メソッドがあります。さらに,事前にリクエストインタセプタのインタフェースをインプリメントしておくことが必要です。クライアント側のインタセプタでは,そのイベントに関して次のリクエストインタセプトポイントが起動されます。

コードサンプル19-38 public void send_request(ClientRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void send_request(PortableInterceptor::ClientRequestInfo_ptr ri){
  . . .

Javaの場合

public void send_request(ClientRequestInfo ri)
                                         throws ForwardRequest {
  . . .

コードサンプル19-39 void send_poll(ClientRequestInfo ri)インタフェースのインプリメンテーション
  • send_poll
    インタセプトポイントを提供し,TII(時間非依存呼び出し)ポーリング取得応答シーケンス時に情報をインタセプタが照会できるようにします。
C++の場合

void send_poll(PortableInterceptor::ClientRequestInfo_ptr ri){
  . . .

Javaの場合

public void send_poll(ClientRequestInfo ri){
  . . .

コードサンプル19-40 void receive_reply(ClientRequestInfo ri)インタフェースのインプリメンテーション
  • receive_reply
    インタセプトポイントを提供し,応答がサーバから戻されてから,制御がクライアントに戻る前にインタセプタがその応答に関する情報を照会できるようにします。
C++の場合

void receive_reply(PortableInterceptor::ClientRequestInfo_ptr
                                                          ri){
  . . .

Javaの場合

public void receive_reply(ClientRequestInfo ri){
  . . .

コードサンプル19-41 void receive_exception(ClientRequestInfo ri)インタフェースのインプリメンテーション
  • receive_exception
    インタセプトポイントを提供し,例外がクライアントに発生する前にインタセプタがその例外の情報を照会できるようにします。
C++の場合

void receive_exception
              (PortableInterceptor::ClientRequestInfo_ptr ri){
  . . .

Javaの場合

public void receive_exception(ClientRequestInfo ri)
                                       throws ForwardRequest {
  . . .

  • receive_other
    インタセプトポイントを提供し,リクエスト結果が正常応答または例外以外の結果になった場合に,インタセプタが利用可能な情報を照会できるようにします。例えば,リクエストの結果がリトライ(例: LOCATION_FORWARDステータスのGIOP応答を受信)になる場合です。非同期呼び出しの場合は,リクエストのあとにすぐに応答は行われませんが,制御はクライアントに戻り,終了インタセプトポイントが呼び出されます。
コードサンプル19-42 void receive_other(ClientRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void receive_other(PortableInterceptor::ClientRequestInfo_ptr
                                                         ri){
  . . .

Javaの場合

public void receive_other(ClientRequestInfo ri)
                                         throws ForwardRequest {
  . . .

クライアント側リクエストインタセプタの完全なインプリメンテーションを次に示します。

コードサンプル19-43 クライアント側リクエストインタセプタの完全なインプリメンテーション(C++)

//SampleClientInterceptor.h

#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"

//USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

class SampleClientInterceptor :
  public PortableInterceptor::ClientRequestInterceptor
{
private:
  char *_name;

  void init(char *name){
     _name =new char [strlen(name)+1 ];
     strcpy(_name,name);
  }

public:
  SampleClientInterceptor(char *name){
     init(name);
  }

  SampleClientInterceptor(){
     init("SampleClientInterceptor");
  }

char *name(void){
  return _name;
}

void destroy(void){
  //do nothing here

  cout <<"=====>SampleServerLoader:Interceptors unloaded"<<endl;
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* void preinvoke_premarshal(CORBA::Object_ptr target,
*                           const char*operation,
*                           IOP::ServiceContextList&servicecontexts,
*                           VISClosure&closure)=0;
*/
void send_request(PortableInterceptor::ClientRequestInfo_ptr ri){
  cout <<"=====>SampleClientInterceptor id "<<ri->request_id()
     <<"send_request =>"<<ri->operation()
     <<":Target ="<<ri->target()
     <<endl;
}

/**
* There is no equivalent interface for VisiBroker 4.x
* ClientRequestInterceptor.
*/

void send_poll(PortableInterceptor::ClientRequestInfo_ptr ri){
  cout <<"=====>SampleClientInterceptor id "<<ri->request_id()
     <<"send_poll =>"<<ri->operation()
     <<":Target ="<<ri->target()
     <<endl;
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* void postinvoke(CORBA::Object_ptr target,
*                 const IOP::ServiceContextList&service_contexts,
*                 CORBA_MarshalInBuffer&payload,
*                 CORBA::Environment_ptr env,
*                 VISClosure&closure)=0;
*
* with env not holding any exception value.
*/
void receive_reply(PortableInterceptor::ClientRequestInfo_ptr ri){
  cout <<"=====>SampleClientInterceptor id "<<ri->request_id()
     <<"receive_reply =>"<<ri->operation()
     <<endl;
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* void postinvoke(CORBA::Object_ptr target,
*                 const IOP::ServiceContextList&service_contexts,
*                 CORBA_MarshalInBuffer&payload,
*                 CORBA::Environment_ptr env,
*                 VISClosure&closure)=0;
*
* with env holding the exception value.
*/
void receive_exception(PortableInterceptor::ClientRequestInfo_ptr
                                                             ri){
  cout <<"=====>SampleClientInterceptor id "<<ri->request_id()
     <<"receive_exception =>"<<ri->operation()
     <<":Exception ="<<ri->received_exception()
     <<endl;
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* void postinvoke(CORBA::Object_ptr target,
*                 const IOP::ServiceContextList&service_contexts,
*                 CORBA_MarshalInBuffer&payload,
*                 CORBA::Environment_ptr env,
*                 VISClosure&closure)=0;
*
* with env holding the exception value.
*/
void receive_other(PortableInterceptor::ClientRequestInfo_ptr ri){
  cout <<"=====>SampleClientInterceptor id "<<ri->request_id()
     <<"receive_other =>"<<ri->operation()
     <<":Exception ="<<ri->received_exception()
     <<",Reply Status ="<<
    getReplyStatus(ri->reply_status())
    <<endl;
  }

protected:
  char *getReplyStatus(CORBA::Short status){
     if(status ==PortableInterceptor::SUCCESSFUL)
           return "SUCCESSFUL";
     else if(status ==PortableInterceptor::SYSTEM_EXCEPTION)
           return "SYSTEM_EXCEPTION";
     else if(status ==PortableInterceptor::USER_EXCEPTION)
           return "USER_EXCEPTION";
     else if(status ==PortableInterceptor::LOCATION_FORWARD)
           return "LOCATION_FORWARD";
     else if(status ==PortableInterceptor::TRANSPORT_RETRY)
           return "TRANSPORT_RETRY";
     else
           return "invalid reply status id";
     }
};

コードサンプル19-44 クライアント側リクエストインタセプタの完全なインプリメンテーション(Java):SampleClientInterceptor.java

//SampleClientInterceptor.java

import org.omg.PortableInterceptor.*;
import org.omg.Dynamic.*;

public class SampleClientInterceptor extends org.omg.CORBA.LocalObject
implements ClientRequestInterceptor {

  public SampleClientInterceptor(){
     this("SampleClientInterceptor");
}

public SampleClientInterceptor(String name){
_name =name;
}
private String _name =null;
/**
* InterceptorOperations implementation
*/
public String name(){
  return _name;
}

public void destroy(){
  System.out.println("=====>SampleServerLoader:Interceptors unloaded");
}

/**
* ClientRequestInterceptor implementation
*/

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* public void preinvoke_premarshal(org.omg.CORBA.Object target,
     String operation,
*   ServiceContextListHolder service_contexts_holder,Closure
   closure);
*/

public void send_request(ClientRequestInfo ri)throws ForwardRequest {
  System.out.println("=====>SampleClientInterceptor id "+
     ri.request_id()+
          "send_request =>"+ri.operation()+
          ":target ="+ri.target());
}

/**
* There is no equivalent interface for VisiBroker 4.x
* ClientRequestInterceptor.
*/

public void send_poll(ClientRequestInfo ri){
  System.out.println("=====>SampleClientInterceptor id "+
     ri.request_id()+
          "send_poll => " + ri.operation() +
          " : target = " + ri.target());
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* public void postinvoke(org.omg.CORBA.Object target,
*   ServiceContext[ ] service__contexts,InputStream payload,
*   org.omg.CORBA.Environment env,Closure closure);
*
* with env not holding any exception value.
*/
public void receive_reply(ClientRequestInfo ri){
  System.out.println("=====>SampleClientInterceptor id " +
    ri.request_id() +
          " receive_reply => " + ri.operation());
}

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* public void postinvoke(org.omg.CORBA.Object target,
*   ServiceContext[ ] service__contexts,InputStream payload,
*   org.omg.CORBA.Environment env,Closure closure);
*
* with env holding the exception value.
*/
public void receive_exception(ClientRequestInfo ri)throws ForwardRequest {
  System.out.println("=====>SampleClientInterceptor id "+
     ri.request_id() +
           " receive_exception => " + ri.operation() +
           ": exception = " + ri.received_exception());
}
/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* public void postinvoke(org.omg.CORBA.Object target,
*   ServiceContext[ ] service__contexts,InputStream payload,
*   org.omg.CORBA.Environment env,Closure closure);
*
* with env holding the exception value.
*/
public void receive_other(ClientRequestInfo ri) throws ForwardRequest {
  System.out.println("=====> SampleClientInterceptor id "+
     ri.request_id() +
          " receive_reply => " + ri.operation() +
          ": exception = " + ri.received_exception() +
          ", reply status = " + getReplyStatus(ri));
}
protected String getReplyStatus(RequestInfo ri){
  switch(ri.reply_status()){
     case SUCCESSFUL.value:
        return "SUCCESSFUL";
     case SYSTEM_EXCEPTION.value:
        return "SYSTEM_EXCEPTION";
     case USER_EXCEPTION.value:
        return "USER_EXCEPTION";
     case LOCATION_FORWARD.value:
        return "LOCATION_FORWARD";
     case TRANSPORT_RETRY.value:
        return "TRANSPORT_RETRY";
     default:
        return "invalid reply status id";
     }
  }
}

(e) サーバでのServerRequestInterceptorのインプリメント

サーバリクエストインタセプタでは,リクエストインタセプタが正しく動作するためにServerRequestInterceptorインタフェースをインプリメントする必要があります。サーバ側インタセプタでは,各イベントに関して次のリクエストインタセプトポイントが起動されます。

コードサンプル19-45 void receive_request_service_contexts (ServerRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void receive_request_service_contexts
               (PortableInterceptor::ServerRequestInfo_ptr
                                                       ri){
  . . .

Javaの場合

public void receive_request_service_contexts
      (ServerRequestInfo ri) throws ForwardRequest{
  . . .

コードサンプル19-46 void receive_request (ServerRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void receive_request(PortableInterceptor::ServerRequestInfo_ptr
                                                          ri){
  . . .

Javaの場合

public void receive_request(ServerRequestInfo ri)
                                        throws ForwardRequest {
  . . .

コードサンプル19-47 void send_reply (ServerRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void send_reply(PortableInterceptor::ServerRequestInfo_ptr
                                                     ri){
  . . .

Javaの場合

public void send_reply(ServerRequestInfo ri){
  . . .

コードサンプル19-48 void send_exception (ServerRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void send_exception(PortableInterceptor::ServerRequestInfo_ptr
                                                         ri) {
  . . .

Javaの場合

public void send_exception(ServerRequestInfo ri)throws
                                               ForwardRequest {
  . . .

コードサンプル19-49 void send_other (ServerRequestInfo ri)インタフェースのインプリメンテーション
C++の場合

void send_other(PortableInterceptor::ServerRequestInfo_ptr
                                                       ri){
  . . .

Javaの場合

public void send_other(ServerRequestInfo ri)throws
                                    ForwardRequest {
  . . .

すべてのインタセプトポイントによって,クライアントおよびサーバは異なる種類の情報を呼び出しの異なるポイントで取得できます。サンプルでは,このような情報はデバッグの形式で画面に表示されています。

サーバ側リクエストインタセプタの完全なインプリメンテーションを次に示します。

コードサンプル19-50 サーバ側リクエストインタセプタの完全なインプリメンテーション(C++):SampleServerInterceptor.cpp

// SampleServerInterceptor.h

#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"

//USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

class SampleServerInterceptor :
  public PortableInterceptor::ServerRequestInterceptor
{
private:
  char *_name;

  void init(char *name){
     _name =new char [strlen(name)+1 ];
     strcpy(_name,name);
}

public:
  SampleServerInterceptor(char *name){
     init(name);
  }

  SampleServerInterceptor(){
     init("SampleServerInterceptor");
  }

  char *name(void){
     return _name;
}

  void destroy(void){
     //do nothing here
     cout <<"=====>SampleServerLoader:Interceptors unloaded"<<endl;
  }

/**
* This is similar to VisiBroker 4.x ClientRequestInterceptor,
*
* void preinvoke_premarshal(CORBA::Object_ptr target,
*                           const char*operation,
*                           IOP::ServiceContextList&servicecontexts,
*                           VISClosure&closure)=0;
*/
void
receive_request_service_contexts(PortableInterceptor::
  ServerRequestInfo_ptr ri){
        cout <<"=====>SampleServerInterceptor id "<<ri->request_id()
        <<"receive_request_service_contexts =>"<<ri->operation()
        <<endl;
}

/**
* There is no equivalent interface for VisiBroker 4.x
* SeverRequestInterceptor.
*/
void receive_request(PortableInterceptor::ServerRequestInfo_ptr
                                                             ri)
{
  cout <<"=====>SampleServerInterceptor id "<<ri->request_id()
     <<"receive_request =>"<<ri->operation()
     <<":Object ID ="<<ri->object_id()
     <<",Adapter ID ="<<ri->adapter_id()
     <<endl;
}

/**
* There is no equivalent interface for VisiBroker 4.x
* SeverRequestInterceptor.
*/
void send_reply(PortableInterceptor::ServerRequestInfo_ptr ri){
  cout <<"=====>SampleServerInterceptor id "<<ri->request_id()
     <<"send_reply =>"<<ri->operation()
     <<endl;
}

/**
* This is similar to VisiBroker 4.x ServerRequestInterceptor,
*
* virtual void postinvoke_premarshal(CORBA::Object_ptr _target,
*                      IOP::ServiceContextList&_service_contexts,
*                                    CORBA::Environment_ptr _env,
*                                    VISClosure&_closure)=0;
*
*with env holding the exception value.
*/
void send_exception(PortableInterceptor::ServerRequestInfo_ptr
                                                             ri){
  cout << "=====> SampleServerInterceptor id " << ri->request_id()
       << " send_exception => " << ri ->operation()
       << " :Exception = " << ri ->sending_exception()
       << " ,Reply status = " << getReplyStatus(ri->reply_status())
       <<endl;
}

/**
* This is similar to VisiBroker 4.x ServerRequestInterceptor,
*
* virtual void postinvoke_premarshal(CORBA::Object_ptr _target,
*                                    IOP::ServiceContextList&_service_contexts,
*                                    CORBA::Environment_ptr _env,
*                                    VISClosure&_closure)=0;
*
* with env holding the exception value.
*/
void send_other(PortableInterceptor::ServerRequestInfo_ptr ri){
  cout <<"=====>SampleServerInterceptor id "<<ri->request_id()
     <<"send_other =>"<<ri->operation()
     <<":Exception ="<<ri->sending_exception()
     <<",Reply Status ="<<getReplyStatus(ri->reply_status())
     <<endl;
}

protected:
  char *getReplyStatus(CORBA::Short status){
     if(status ==PortableInterceptor::SUCCESSFUL)
        return "SUCCESSFUL";
           else if(status ==PortableInterceptor::SYSTEM_EXCEPTION)
        return "SYSTEM_EXCEPTION";
           else if(status ==PortableInterceptor::USER_EXCEPTION)
        return "USER_EXCEPTION";
           else if(status ==PortableInterceptor::LOCATION_FORWARD)
        return "LOCATION_FORWARD";
           else if(status ==PortableInterceptor::TRANSPORT_RETRY)
        return "TRANSPORT_RETRY";
           else
        return "invalid reply status id";
     }
};

コードサンプル19-51 サーバ側リクエストインタセプタの完全なインプリメンテーション(Java):SampleServerInterceptor.java

// SampleServerInterceptor.java

import org.omg.PortableInterceptor.*;
import org.omg.Dynamic.*;
import java.io.PrintStream;

public class SampleServerInterceptor extends org.omg.CORBA.LocalObject
implements ServerRequestInterceptor {

  private String _name =null;

  public SampleServerInterceptor(){
     this("SampleServerInterceptor");
  }

  public SampleServerInterceptor(String name){
     _name =name;
  }
/**
* InterceptorOperations implementation
*/
public String name() {
     return _name;
}

public void destroy(){
  System.out.println("=====>SampleServerLoader:Interceptors unloaded");
}

/**
* ServerRequestInterceptor implementation
*/

/**
* This is similar to VisiBroker 4.x ServerRequestInterceptor,
*
* public void preinvoke(org.omg.CORBA.Object target,
*   String operation,
*   ServiceContext[ ] service__contexts,InputStream payload,
*   Closure closure);
*/

public void receive_request_service_contexts(ServerRequestInfo ri)
     throws ForwardRequest {
  System.out.println("=====>SampleServerInterceptor id " +
          ri.request_id() +
          " receive_request_service_contexts => " + ri.operation());
}

/**
* There is no equivalent interface for VisiBroker 4.x
* SeverRequestInterceptor.
*/
public void receive_request(ServerRequestInfo ri)
     throws ForwardRequest {
  System.out.println("=====>SampleServerInterceptor id "
           + ri.request_id() +
           " receive_request => " + ri.operation() +
           ": object id = " + ri.object_id() +
           ", adapter_id = " + ri.adapter_id());
}

/**
* There is no equivalent interface for VisiBroker 4.x
* SeverRequestInterceptor.
*/
public void send_reply(ServerRequestInfo ri){
  System.out.println("=====> SampleServerInterceptor id " +
           ri.request_id() +
           " send_reply => " + ri.operation());
}

/**
* This is similar to VisiBroker 4.x ServerRequestInterceptor,
*
* public void postinvoke_premarshal(org.omg.CORBA.Object target,
* ServiceContextListHolder service_contexts_holder,
* org.omg.CORBA.Environment env,Closure closure);
*
*with env holding the exception value.
*/
public void send_exception(ServerRequestInfo ri)
     throws ForwardRequest {
  System.out.println("=====>SampleServerInterceptor id " +
           ri.request_id() +
           " send_exception => " + ri.operation() +
           ": exception = " + ri.sending_exception() +
           ", reply status = " + getReplyStatus(ri));
}

/**
* This is similar to VisiBroker 4.x ServerRequestInterceptor,
*
* public void postinvoke_premarshal(org.omg.CORBA.Object target,
*   ServiceContextListHolder service_contexts_holder,
*   org.omg.CORBA.Environment env,Closure closure);
*
* with env holding the exception value.
*/
public void send_other(ServerRequestInfo ri)throws ForwardRequest {
     System.out.print("=====>SampleServerInterceptor id "+
           ri.request_id() +
           " send_other =>" + ri.operation() +
           ": exception = " + ri.sending_exception() +
           ", reply status = " + getReplyStatus(ri));
}
     protected String getReplyStatus(RequestInfo ri){
        switch(ri.reply_status()){
           case SUCCESSFUL.value:
              return "SUCCESSFUL";
           case SYSTEM_EXCEPTION.value:
              return "SYSTEM_EXCEPTION";
           case USER_EXCEPTION.value:
              return "USER_EXCEPTION";
           case LOCATION_FORWARD.value:
              return "LOCATION_FORWARD";
           case TRANSPORT_RETRY.value:
              return "TRANSPORT_RETRY";
           default:
              return "invalid reply status id";
        }
     }
}

(f) クライアントおよびサーバアプリケーションの開発

インタセプタクラスを書き込んだあと,このクラスをそれぞれクライアントおよびサーバアプリケーションに登録する必要があります。

●C++の場合

C++では,クライアントとサーバはPortableInterceptor::register_orb_initializer(<class name>)メソッドによって,それぞれのORBInitializerクラスを登録します。

ここで,<class name>は登録するクラスの名前です。サンプルでは,DLL(動的リンクライブラリ)としてインタセプタクラスを登録する別の方法も説明します。この方法の利点は,アプリケーションがコードを変更する必要がなく,実行方法だけを変更すればいいということです。「19.3.2(4) クライアントおよびサーバアプリケーションの実行または配置」を参照してください。これはVisiBrokerの適切な登録方法であることに注意してください。OMGに完全に準拠するには,次に示す方法は使用しないでください。

DLLとしてインタセプタクラスをロードすること(すなわち,VisiBrokerの適切なメソッドを使用すること)を選択したら,クライアントおよびサーバアプリケーションに拡張コードを追加する必要はありません。サンプルでは,DLLコンパイルとリンク付けが指定されていないと,コードの部分がマクロによる適切な状態ではないことがわかります。

クライアントアプリケーションの完全なインプリメンテーションを次に示します。

コードサンプル19-52 クライアントアプリケーションの完全なインプリメンテーション(C++)

//Client.C

#include "Bank_c.hh"

//USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

#if !defined(DLL_COMPILE )
#include "SampleClientLoader.C"
#endif

int main(int argc, char* const* argv)
{
  try {
     // Instantiate the Loader *before* the orb initialization
     // if chose not to use DLL method of loading
     #if !defined(DLL_COMPILE )
     SampleClientLoader* loader = new SampleClientLoader;
     PortableInterceptor::register_orb_initializer(loader);
     #endif

     // Initialize the ORB.
     CORBA::ORB_var orb =CORBA::ORB_init(argc,argv);

     // Get the manager Id
     PortableServer::ObjectId_var managerId =
              PortableServer::string_to_ObjectId("BankManager");

     // Locate an account manager.Give the full POA name and the
     // servant ID.
     Bank::AccountManager_var manager =
             Bank::AccountManager::_bind("/bank_agent_poa"
                                                   ,managerId);

     // use argv [1 ] as the account name,,or a default.
     const char*name =argc >1 ?argv [1 ] ::"Jack B.Quick";

     // Request the account manager to open a named account.
     Bank::Account_var account =manager->open(name);

     // Get the balance of the account.
     CORBA::Float balance =account->balance();

     // Print out the balance.
     cout <<"The balance in "<<name <<"'s account is $"<<balance
           <<endl;
  }
  catch(const CORBA::Exception&e){
  cerr <<e <<endl;
  return 1;
  }
  return 0;
}

サーバアプリケーションの完全なインプリメンテーションを次に示します。

コードサンプル19-53 サーバアプリケーションの完全なインプリメンテーション(C++)

// Server.C

#include "BankImpl.h"

// USE_STD_NS is a define setup by VisiBroker to use the std namespace
USE_STD_NS

#if !defined(DLL_COMPILE )
#include "SampleServerLoader.C"
#endif

int main(int argc,char*const*argv)
{
  try {
      // Instantiate an interceptor loader before initializing
      // the orb:
      #if !defined(DLL_COMPILE )
      SampleServerLoader*loader = new SampleServerLoader();
      PortableInterceptor::register_orb_initializer(loader);
      #endif

      // Initialize the ORB.
      CORBA::ORB_var orb = CORBA::ORB_init(argc,argv);

      // get a reference to the rootPOA
      CORBA::Object_var obj = orb->
                                resolve_initial_references("RootPOA");
      PortableServer::POA_var rootPOA =
                                PortableServer::POA::_narrow(obj);

      CORBA::PolicyList policies;
      policies.length(1);
      policies [(CORBA::ULong)0 ] = rootPOA->
                 create_lifespan_policy( PortableServer::PERSISTENT );

      // get the POA Manager
      PortableServer::POAManager_var poa_manager =
                                             rootPOA->the_POAManager();

      // Create myPOA with the right policies
      PortableServer::POA_var myPOA =
                               rootPOA->create_POA("bank_agent_poa",
                                                        poa_manager,
                                                        policies);

      // Create the servant
      AccountManagerImpl managerServant;

      // Decide on the ID for the servant
      PortableServer::ObjectId_var managerId =
                  PortableServer::string_to_ObjectId("BankManager");

      // Activate the servant with the ID on myPOA
      myPOA->activate_object_with_id(managerId,&managerServant);

      // Activate the POA Manager
      poa_manager->activate();

      CORBA::Object_var reference =
      myPOA->servant_to_reference(&managerServant);
      cout <<reference <<"is ready"<<endl;

      // Wait for incoming requests
      orb->run();
  }
  catch(const CORBA::Exception&e){
     cerr <<e <<endl;
     return 1;
  }
  return 0;
}

●Javaの場合

Javaでは,OMG規格のregister_orb_initializerのマッピングに従います。すなわち,このクラスをJava ORBプロパティによって登録します。サンプルでは,クライアントおよびサーバアプリケーションは実際には,プロパティファイルから,org.omg.PortableInterceptor.ORBInitializerClass.<Service>(<Service>はorg.omg.PortableInterceptor.ORBInitializerをインプリメントするクラスの文字列名です)プロパティがあるclient.propertiesおよびserver.propertiesを読み取ります。この場合は,SampleClientLoaderおよびSampleServerLoaderという二つのクラスです。

また,ファイルからプロパティを読み取らないで,アプリケーションを書き込むことを選択する場合,コマンドラインオプションを使用することもできます。これには,アプリケーションを次のように実行する必要があります。

vbj -Dorg.omg.PortableInterceptor.ORBInitializerClass.
   SampleClientLoader = SampleClientLoaderClient
vbj -Dorg.omg.PortableInterceptor.ORBInitializerClass.
   SampleServerLoader = SampleServerLoaderServer

クライアントアプリケーションの完全なインプリメンテーションを次に示します。

コードサンプル19-54 クライアントアプリケーションの完全なインプリメンテーション(Java):Client.java

// Client.java

import org.omg.PortableServer.*;

import java.util.Properties;
import java.io.FileInputStream;

public class Client {

  private static Properties property =null;

  public static void main(String [ ] args){
     try {
        property = new Properties();
        property.load(new FileInputStream("client.properties"));

     // Initialize the ORB.
     org.omg.CORBA.ORB orb=org.omg.CORBA.ORB.init(args,property);
     // Get the manager Id
     byte[ ] AccountManagerId="BankManager".getBytes();
     // Locate an account manager.Give the full POA name and
     // the servant ID.
     Bank.AccountManager manager =
        Bank.AccountManagerHelper.bind(orb,
           "/bank_client_server_poa", AccountManagerId);
     // use args [0 ]as the account name,or a default.
     String name =null;
     name =args.length >0 ?args [0 ] :"Jack B.Quick";
     // Request the account manager to open a named account.
     Bank.Account account =manager.open(name);
     // Get the balance of the account.
     float balance =account.balance();
     // Print out the balance.
     System.out.println("The balance in "+name +"'s account is $"+
        balance);
     }
     catch(Exception e){
     e.printStackTrace();
     }
 }
}

サーバアプリケーションの完全なインプリメンテーションを次に示します。

コードサンプル19-55 サーバアプリケーションの完全なインプリメンテーション(Java):Server.java

// Server.java

import org.omg.PortableServer.*;
import java.util.Properties;
import java.io.FileInputStream;

public class Server {

  private static Properties property = null;

  public static void main(String[ ] args)){
     try {
        property =new Properties();
        property.load(new FileInputStream("server.properties"));

        // Initialize the ORB.
        org.omg.CORBA.ORB orb =
                           org.omg.CORBA.ORB.init(args,property);
        // get a reference to the rootPOA
        POA rootPOA =POAHelper.narrow(orb.resolve_initial_references
                                                         ("RootPOA"));

        // Create policies for our persistent POA
        org.omg.CORBA.Policy[ ] policies =={
            rootPOA.create_lifespan_policy(
                        LifespanPolicyValue.PERSISTENT)
        };

        // Create myPOA with the right policies
        POA myPOA =rootPOA.create_POA("bank_client_server_poa",
                         rootPOA.the_POAManager(),policies );

        // Create Account servants
        AccountManagerImpl managerServant =
                                        new AccountManagerImpl();
        byte[ ] managerId == "BankManager".getBytes();
        myPOA.activate_object_with_id(managerId,managerServant);
        rootPOA.the_POAManager().activate();

        // Announce Servants are ready
        System.out.println(myPOA.servant_to_reference
                                   (managerServant) + "is ready.");
        //Wait for incoming requests
        orb.run();
     }
     catch (Exception e){
     e.printStackTrace();
    }
  }
}

(3) コンパイルの手順

●C++の場合

VisiBrokerのC++サンプルをコンパイルするには,次のコマンドを実行します。

UNIX

$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.cpp

Windows

%VBROKERDIR%¥examples¥vbe¥pi¥client_server>nmake -f Makefile.cpp

VisiBrokerのC++サンプルをコンパイルするには,次のコマンドを実行します。

UNIX

$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.cpp dll

Windows

%VBROKERDIR%¥examples¥vbe¥pi¥client_server>nmake -f Makefile.cpp dll

●Javaの場合

Javaのサンプルをコンパイルするには,次のコマンドを実行します。

UNIX

$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.java

Windows

%VBROKERDIR%¥examples¥vbe¥pi¥client_server>vbmake

または,環境変数%VBROKERDIR%¥binが環境変数PATHにすでに追加されている場合は,バッチファイルアイコンをダブルクリックします。

(4) クライアントおよびサーバアプリケーションの実行または配置

●C++の場合

VisiBrokerのC++サンプルを実行するには,サーバとクライアントを次のように起動します。

UNIX(二つのコンソールウィンドウをオープンします)
$VBROKERDIR/examples/vbe/pi/client_server>Server(最初のウィンドウ)
$VBROKERDIR/examples/vbe/pi/client_server>Client John(2番目のウィンドウ:任意の名前を使用)
または,
$VBROKERDIR/examples/vbe/pi/client_server> Client(2番目のウィンドウ:デフォルトの名前を使用)
Windows
%VBROKERDIR%¥examples¥vbe¥pi¥client_server> start Server(新しいコマンドプロンプトウィンドウ下で実行)
%VBROKERDIR%¥examples¥vbe¥pi¥client_server> Client John(任意の名前を使用)
または,
%VBROKERDIR%¥examples¥vbe¥pi¥client_server> Client(デフォルトの名前を使用)

VisiBrokerのC++サンプルを実行するには,サーバとクライアントを次のように起動します。

UNIX(二つのコンソールウィンドウをオープンします)
$VBROKERDIR/examples/vbe/pi/client_server>Server
-Dvbroker.orb.dynamicLibs=./SampleServerLoader.so(最初のウィンドウ)
$VBROKERDIR/examples/vbe/pi/client_server>Client
-Dvbroker.orb.dynamicLibs=./SampleClientLoader.so John(2番目のウィンドウ:任意の名前を使用)
Windows
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>start Server -Dvbroker.orb.dynamicLibs=SampleServerLoader.dll(新しいコマンドプロンプトウィンドウ下で実行)
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>Client John -Dvbroker.orb.dynamicLibs=SampleClientLoader.dll(任意の名前を使用)
または,
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>Client -Dvbroker.orb.dynamicLibs=SampleClientLoader.dll(デフォルトの名前を使用)
●Javaの場合

インストール済みのポータブルインタセプタでJavaサンプルを実行するには,サーバとクライアントを次のように起動します。

UNIX(二つのコンソールウィンドウをオープンします)
$VBROKERDIR/examples/vbe/pi/client_server>vbj Server(最初のウィンドウ)
$VBROKERDIR/examples/vbe/pi/client_server>vbj Client John(2番目のウィンドウ:任意の名前を使用)
または,
$VBROKERDIR/examples/vbe/pi/client_server>vbj Client(2番目のウィンドウ:デフォルトの名前を使用)
Windows
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>start vbj Server(新しいコマンドプロンプトウィンドウ下で実行)
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>vbj Client John(任意の名前を使用)