このサンプルでは,コードを変更しないで,既存のCORBAアプリケーションにポータブルインタセプタを追加する簡単な方法を実際に説明します。ポータブルインタセプタはクライアント側およびサーバ側の両方のどのアプリケーションにも追加できます。これは,ランタイム時に設定する指定のオプションやプロパティで,関連するアプリケーションを再実行することによって行えます。
使用するクライアントおよびサーバアプリケーションは,$VBROKERDIR/examples/vbe/basic/bank_agent(UNIX)または%VBROKERDIR%¥examples¥vbe¥basic¥bank_agent(Windows)にあるアプリケーションと類似しています。サンプル全体は抜粋であり,ポータブルインタセプタはランタイム構成時に追加されています。その理由は,VisiBrokerのインタセプタを熟知している開発者にVisiBrokerのインタセプタとOMG固有ポータブルインタセプタ間のコーディングを早く行える方法を提供するためです。
ポータブルインタセプタインタフェースを使用するには,関連パッケージまたはヘッダファイルが組み込まれている必要があります。Java ORBで,DuplicateNameやInvalidNameのようなポータブルインタセプタの例外を使用している場合,org.omg.PortableInterceptor.ORBInitInfoPackageはオプションであることに注意してください。
#include "PortableInterceptor_c.hh"
#include "IOP_c.hh"
import org.omg.PortableInterceptor.*;
import org.omg.PortableInterceptor.ORBInitInfoPackage.*;
まずクライアント側で,リクエストインタセプタの各部分の書き方について詳細に説明します。クライアント側のリクエストインタセプタをロードするには,インタフェースをインプリメントするクラスであるORBInitializerをインプリメントする必要があります。また,これは初期化を考慮するとサーバ側のリクエストインタセプタにも該当します。
次にこれをインプリメントするコードを示します。
class SampleClientLoader :
public PortableInterceptor::ORBInitializer
public class SampleClientLoader extends
org.omg.CORBA.LocalObject implements ORBInitializer
class SampleServerLoader :
public PortableInterceptor::ORBInitializer
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に追加する前に,そのインタセプタが実体化される必要があります。
public:
void pre_init(PortableInterceptor::ORBInitInfo_ptr
_info){
SampleClientInterceptor *interceptor =
new SampleClientInterceptor;
try {
_info->add_client_request_interceptor(interceptor);
. . .
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のインプリメンテーションでは,各インタセプタローダの登録は同様に行われます。
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);
. . .
クライアント側インタセプタローダの完全なインプリメンテーションを次に示します。
//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
//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.
}
}
この段階では,クライアントリクエストインタセプタはすでに正しく実体化され,追加されているはずです。これ以降のコードサンプルは例外処理と結果表示だけを提供します。同様に,サーバ側のサーバリクエストインタセプタにも同じことが行われます。ただし,add_server_request_interceptor()メソッドを使用して関連サーバリクエストインタセプタをORBに追加することが異なります。
public:
void pre_init(PortableInterceptor::ORBInitInfo_ptr
_info){
SampleServerInterceptor *interceptor =
new SampleServerInterceptor;
try {
_info->add_server_request_interceptor(interceptor);
. . .
public void pre_init(ORBInitInfo info){
try {
info.add_server_request_interceptor(
new SampleServerInterceptor());
. . .
これは,サーバ側ORBInitializerクラスのDLLインプリメンテーションによるロードにも同様に適用されます。
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);
. . .
サーバ側インタセプタローダの完全なインプリメンテーションを次に示します。
//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
//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.
}
}
クライアント側またはサーバ側のリクエストインタセプタのインプリメンテーション時に,その両方に共通の別の二つのインタフェースをインプリメントする必要があります。それは,name()とdestroy()です。リクエストや応答でロードおよび呼び出しを行うインタセプタを正しく識別するためにORBに名前を提供するので,name()は重要です。CORBAの仕様に従うと,インタセプタはアノニマスでもかまいません。つまり,名前属性として空の文字列でもかまいません。このサンプルでは,SampleClientInterceptorという名前がクライアント側インタセプタに,SampleServerInterceptorという名前がサーバ側インタセプタに割り当てられています。
public:
char *name(void){
return _name;
}
public String name(){
return _name;
}
クライアントリクエストインタセプタでは,リクエストインタセプタが正しく動作するためにClientRequestInterceptorインタフェースをインプリメントする必要があります。クラスがインタフェースをインプリメントする場合,インプリメンテーションに関係なく五つのリクエストインタセプタメソッドがインプリメントされます。これにはsend_request()メソッド,send_poll()メソッド,receive_reply()メソッド,receive_exception()メソッド,およびreceive_other()メソッドがあります。さらに,事前にリクエストインタセプタのインタフェースをインプリメントしておくことが必要です。クライアント側のインタセプタでは,そのイベントに関して次のリクエストインタセプトポイントが起動されます。
void send_request(PortableInterceptor::ClientRequestInfo_ptr ri){
. . .
public void send_request(ClientRequestInfo ri)
throws ForwardRequest {
. . .
void send_poll(PortableInterceptor::ClientRequestInfo_ptr ri){
. . .
public void send_poll(ClientRequestInfo ri){
. . .
void receive_reply(PortableInterceptor::ClientRequestInfo_ptr
ri){
. . .
public void receive_reply(ClientRequestInfo ri){
. . .
void receive_exception
(PortableInterceptor::ClientRequestInfo_ptr ri){
. . .
public void receive_exception(ClientRequestInfo ri)
throws ForwardRequest {
. . .
void receive_other(PortableInterceptor::ClientRequestInfo_ptr
ri){
. . .
public void receive_other(ClientRequestInfo ri)
throws ForwardRequest {
. . .
クライアント側リクエストインタセプタの完全なインプリメンテーションを次に示します。
//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";
}
};
//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";
}
}
}
サーバリクエストインタセプタでは,リクエストインタセプタが正しく動作するためにServerRequestInterceptorインタフェースをインプリメントする必要があります。サーバ側インタセプタでは,各イベントに関して次のリクエストインタセプトポイントが起動されます。
void receive_request_service_contexts
(PortableInterceptor::ServerRequestInfo_ptr
ri){
. . .
public void receive_request_service_contexts
(ServerRequestInfo ri) throws ForwardRequest{
. . .
void receive_request(PortableInterceptor::ServerRequestInfo_ptr
ri){
. . .
public void receive_request(ServerRequestInfo ri)
throws ForwardRequest {
. . .
void send_reply(PortableInterceptor::ServerRequestInfo_ptr
ri){
. . .
public void send_reply(ServerRequestInfo ri){
. . .
void send_exception(PortableInterceptor::ServerRequestInfo_ptr
ri) {
. . .
public void send_exception(ServerRequestInfo ri)throws
ForwardRequest {
. . .
void send_other(PortableInterceptor::ServerRequestInfo_ptr
ri){
. . .
public void send_other(ServerRequestInfo ri)throws
ForwardRequest {
. . .
すべてのインタセプトポイントによって,クライアントおよびサーバは異なる種類の情報を呼び出しの異なるポイントで取得できます。サンプルでは,このような情報はデバッグの形式で画面に表示されています。
サーバ側リクエストインタセプタの完全なインプリメンテーションを次に示します。
// 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";
}
};
// 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";
}
}
}
インタセプタクラスを書き込んだあと,このクラスをそれぞれクライアントおよびサーバアプリケーションに登録する必要があります。
C++では,クライアントとサーバはPortableInterceptor::register_orb_initializer(<class name>)メソッドによって,それぞれのORBInitializerクラスを登録します。
ここで,<class name>は登録するクラスの名前です。サンプルでは,DLL(動的リンクライブラリ)としてインタセプタクラスを登録する別の方法も説明します。この方法の利点は,アプリケーションがコードを変更する必要がなく,実行方法だけを変更すればいいということです。「19.3.2(4) クライアントおよびサーバアプリケーションの実行または配置」を参照してください。これはVisiBrokerの適切な登録方法であることに注意してください。OMGに完全に準拠するには,次に示す方法は使用しないでください。
DLLとしてインタセプタクラスをロードすること(すなわち,VisiBrokerの適切なメソッドを使用すること)を選択したら,クライアントおよびサーバアプリケーションに拡張コードを追加する必要はありません。サンプルでは,DLLコンパイルとリンク付けが指定されていないと,コードの部分がマクロによる適切な状態ではないことがわかります。
クライアントアプリケーションの完全なインプリメンテーションを次に示します。
//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;
}
サーバアプリケーションの完全なインプリメンテーションを次に示します。
// 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では,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
クライアントアプリケーションの完全なインプリメンテーションを次に示します。
// 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();
}
}
}
サーバアプリケーションの完全なインプリメンテーションを次に示します。
// 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();
}
}
}
VisiBrokerのC++サンプルをコンパイルするには,次のコマンドを実行します。
$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.cpp
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>nmake -f Makefile.cpp
VisiBrokerのC++サンプルをコンパイルするには,次のコマンドを実行します。
$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.cpp dll
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>nmake -f Makefile.cpp dll
Javaのサンプルをコンパイルするには,次のコマンドを実行します。
$VBROKERDIR/examples/vbe/pi/client_server>make -f Makefile.java
%VBROKERDIR%¥examples¥vbe¥pi¥client_server>vbmake
VisiBrokerのC++サンプルを実行するには,サーバとクライアントを次のように起動します。
VisiBrokerのC++サンプルを実行するには,サーバとクライアントを次のように起動します。
インストール済みのポータブルインタセプタでJavaサンプルを実行するには,サーバとクライアントを次のように起動します。