CORBA, OMNIORB, Asynchronous Method Invocation
AMI: Asynchronous Method Invocation under CORBA allows generation of asynchronous callback handlers and poolers.
The idl compiler generates de corresponding code to handle the responses.
1- Create a 'idl' folder and create AMIExample.idl file into it:
2- Create a compile script in the previous folder, for example idlcompile.bat:
Parameter -bami AmiExample.idl >> AmiExample.txt indicates the compiler that it should create a description of the created interfaces and put it into AmiExample.txt.
After executing the compiling script AmiExample.hh,AmiexampleSK.cc and AmiExample.txt will be created into the folder.
AmiExample.txt gives a detailed definition of the available interfaces in the generated class.
In this example we will focus on a Callback handler, a client will perform an asynchronous method call on the servant and the response will be received (asynchronously) by a callback handler:
We need:
CPP
The servant return "Hello World" so that it is received asynchronously by the Handler:
The callback handler adds three exclamation marks to the response and "Hello World!!!" is shown in the standard output.
Code:
https://dl.dropboxusercontent.com/u/23142124/Visual%20Studio%202010%20C%2B%2B%20CORBA%20with%20OmniOrb%20and%20Java%20ORBD/AMI/CorbaAMIVS2010.zip
Ramon Talavera.
The idl compiler generates de corresponding code to handle the responses.
1- Create a 'idl' folder and create AMIExample.idl file into it:
interface AMIExample { string asyncMe(in string inputValue); };
2- Create a compile script in the previous folder, for example idlcompile.bat:
set OMINIDL=C:\omniorb\omniORB-4.2.0\bin\x86_win32\omniidl %OMINIDL% -bcxx -bami AmiExample.idl >> AmiExample.txt %OMINIDL% -bcxx -Wbami AmiExample.idl
Parameter -bami AmiExample.idl >> AmiExample.txt indicates the compiler that it should create a description of the created interfaces and put it into AmiExample.txt.
After executing the compiling script AmiExample.hh,AmiexampleSK.cc and AmiExample.txt will be created into the folder.
AmiExample.txt gives a detailed definition of the available interfaces in the generated class.
// ReplyHandler for interface AMIExample interface AMI_AMIExampleHandler : Messaging::ReplyHandler { void asyncMe(in string ami_return_val); void asyncMe_excep(in ::Messaging::ExceptionHolder excep_holder); }; // Poller valuetype for interface AMIExample abstract valuetype AMI_AMIExamplePoller : Messaging::Poller { void asyncMe(in unsigned long ami_timeout, out string ami_return_val); }; // AMI implied operations for interface AMIExample interface AMIExample { void sendc_asyncMe(in ::AMI_AMIExampleHandler ami_handler, in string inputValue); ::AMI_AMIExamplePoller sendp_asyncMe(in string inputValue); };
In this example we will focus on a Callback handler, a client will perform an asynchronous method call on the servant and the response will be received (asynchronously) by a callback handler:
We need:
- A Servant of type AMIExample
- A Client
- A Handler of type AMIExampleHandler
Coding the Servant (Project A):
AmiExampleImpl:
HPP
#pragma once
CPP#include "idl/AmiExample.hh" #include <iostream> #include <fstream> using namespace std; class AmiExampleImpl : public POA_AMIExample { public: AmiExampleImpl(void); virtual ~AmiExampleImpl(void); virtual char *asyncMe(const char *); };
#include "StdAfx.h" #include "AmiExampleImpl.hh" #include <iostream> #include <fstream> #include <sstream> #include <assert.h> AmiExampleImpl::AmiExampleImpl(void) { } AmiExampleImpl::~AmiExampleImpl(void) { } char * AmiExampleImpl::asyncMe(const char *str) { CORBA::string_dup(str); }
The Servant Launcher:
CPP
#include "stdafx.h" #include "idl/AmiExample.hh" #include "AmiExampleImpl.hh" #include <iostream> #include <fstream> #include <assert.h> using namespace std; int main(int argc, char** argv) { const char *servantName="AMIExample"; // -------------------------------------------------------------------------- // Start CORBA server: // -------------------------------------------------------------------------- cout<<"Welcome, initialising CORBA"<<endl; try { //------------------------------------------------------------------------ // 1) Initialize ORB // 2) Get reference to root POA // 3) Bind to name service // 4) Initialize servant object //------------------------------------------------------------------------ //------------------------------------------------------------------------ // Initialize CORBA ORB - "orb" //------------------------------------------------------------------------ cout<<"Corab Servant Initialising Arguments:"<<endl; for (int i=0;i<argc;i++) { cout<<argv[i]<<endl; } cout<<"--------------------------------------"<<endl; CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); cout<<"Corba initialised"<<endl; //------------------------------------------------------------------------ // Servant must register with POA in order to be made available for client // Get reference to the RootPOA. //------------------------------------------------------------------------ CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var _poa = PortableServer::POA::_narrow(obj.in()); cout<<"Servant Registered"<<endl; //------------------------------------------------------------------------ // Operations defined in object interface invoked via an object reference. // Instance of CRequestSocketStream_i servant is initialized. //------------------------------------------------------------------------ AmiExampleImpl* myService = new AmiExampleImpl; cout<<"Interface implementation created"<<endl; //------------------------------------------------------------------------ // ObjectId_var class defined in poa.h // typedef String_var ObjectId_var; CORBA_ORB.h // ??????? //------------------------------------------------------------------------ // Servant object activated in RootPOA. // (Object id used for various POA operations.) //------------------------------------------------------------------------ PortableServer::ObjectId_var myservice_oid = _poa->activate_object(myService); cout<<"POA Activated"<<endl; //------------------------------------------------------------------------ // Obtain object reference from servant and register in naming service(??) //------------------------------------------------------------------------ CORBA::Object_var SA_obj = myService->_this(); cout<<"Reference to servant obtained"<<endl; //------------------------------------------------------------------------ // Obtain a reference to the object, and print it out as string IOR. //------------------------------------------------------------------------ CORBA::String_var sior(orb->object_to_string(SA_obj.in())); cerr << "'" << (char*)sior << "'" << endl; cout<<"IOR Obtained"<<endl; //======================================================================== // Bind (rebind) object (orb) to name (SA_obj) //======================================================================== //------------------------------------------------------------------------ // Bind object to name service as defined by directive InitRef // and identifier "NameService" in config file omniORB.cfg. //------------------------------------------------------------------------ cout<<"--------->Binding to name service"<<endl; CORBA::Object_var initServ=orb->resolve_initial_references("NameService"); if (!CORBA::is_nil(initServ)) { cout<<"NameService found"<<endl; } else { cout<<"NameService not found"<<endl; } assert(!CORBA::is_nil(initServ)); //------------------------------------------------------------------------ // narrow this to the naming context //------------------------------------------------------------------------ cout<<"Narrowing Name Context"<<endl; CosNaming::NamingContext_var rootContext; rootContext = CosNaming::NamingContext::_narrow(initServ); cout<<"Narrow"<<endl; assert(!CORBA::is_nil(rootContext)); cout<<"Narrowing was suscessfull"<<endl; //------------------------------------------------------------------------ // Bind to CORBA name service. Same name to be requested by client. //------------------------------------------------------------------------ cout<<"Binding"<<endl; CosNaming::Name name; name.length(1); name[0].id=CORBA::string_dup(servantName); rootContext->rebind (name,SA_obj.in()); cout<<"Bound as"<<servantName<<endl; //======================================================================== myService->_remove_ref(); //------------------------------------------------------------------------ // Activate the POA manager //------------------------------------------------------------------------ PortableServer::POAManager_var pmgr = _poa->the_POAManager(); pmgr->activate(); cout<<"POA Activated"<<endl; //------------------------------------------------------------------------ // Accept requests from clients //------------------------------------------------------------------------ cout<<"Accepting requests from clients"<<endl; orb->run(); //this is a blocking call //------------------------------------------------------------------------ // If orb leaves event handling loop. // - currently configured never to time out (??) //------------------------------------------------------------------------ orb->destroy(); cout<<"Servant destroyed"<<endl; free(name[0].id); // str_dup does a malloc internally getchar(); } catch(CORBA::SystemException&) { cerr << "Caught CORBA::SystemException." << endl; getchar(); } catch(CORBA::Exception&) { cerr << "Caught CORBA::Exception." << endl; getchar(); } catch(omniORB::fatalException& fe) { cerr << "Caught omniORB::fatalException:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; getchar(); } catch(...) { cerr << "Caught unknown exception." << endl; getchar(); } return 0; }
Coding the Client and the Handler (Project B):
Client:
HPP
#pragma once #include <iostream> #include <fstream> #include "idl/AmiExample.hh" class CorbaAMIClient { public: CorbaAMIClient(void); CorbaAMIClient(CORBA::ORB_ptr orb); virtual ~CorbaAMIClient(void); // CORBA ORB CORBA::ORB_var m_orb; CORBA::Object_var m_nameService; CosNaming::Name m_corbaCosName; CosNaming::NamingContext_var m_nameContext; CORBA::Object_var m_corbaref; // Resolved id to object reference // Resolved and narrowed CORBA object for proxy calls AMIExampleRef m_remoteInterface; }; class DS_ServerConnectionException{ public: DS_ServerConnectionException() { cerr << "CORBA COMM_FAILURE" << endl; }; }; class DS_SystemException{ public: DS_SystemException() { cerr << "CORBA Exception" << endl; }; }; class DS_FatalException{ public: DS_FatalException() { cerr << "CORBA Fatal Exception" << endl; }; }; class DS_Exception{ public: DS_Exception() { cerr << "Exception" << endl; }; };CPP
#include "stdafx.h" #include "idl/AmiExample.hh" #include "AmiExampleHandlerImpl.hh" #include "AmiExampleHandlerImpl.hh" #include <iostream> #include <fstream> #include <assert.h> #include "CorbaAMIClient.hh" using namespace std; CorbaAMIClient::CorbaAMIClient(void) { } CorbaAMIClient::~CorbaAMIClient(void) { } CorbaAMIClient::CorbaAMIClient(CORBA::ORB_ptr orb) { const char *servantName="AMIExample"; try { /* cout<<"Corba Client Initialising Arguments:"<<endl; for (int i=0;i<argc;i++) { cout<<argv[i]<<endl; }*/ m_orb=orb; cout<<"--------------------------------------"<<endl; //------------------------------------------------------------------------ // Initialize ORB object. //------------------------------------------------------------------------ //int argc=0; // Dummy variables to support following call. //char** argv=0; //CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); /*this->m_orb= CORBA::ORB_init(argc, argv); cout<<"orb inited"<<endl; */ //------------------------------------------------------------------------ // Bind ORB object to name service object. // (Reference to Name service root context.) //------------------------------------------------------------------------ cout<<"getting name service"<<endl; //CORBA::Object_var obj = orb->resolve_initial_references("NameService"); this->m_nameService = this->m_orb->resolve_initial_references("NameService"); assert (!CORBA::is_nil(this->m_nameService.in())); //------------------------------------------------------------------------ // Narrow this to the naming context (Narrowed reference to root context.) //------------------------------------------------------------------------ cout<<"Narrowing"<<endl; //CosNaming::NamingContext_var nc = // CosNaming::NamingContext::_narrow(obj.in()); this->m_nameContext = CosNaming::NamingContext::_narrow(this->m_nameService.in()); assert (!CORBA::is_nil(this->m_nameContext)); cout<<"narrow done"<<endl; //------------------------------------------------------------------------ // The "name text" put forth by CORBA server in name service. // This same name ("DataServiceName1") is used by the CORBA server when // binding to the name server (CosNaming::Name). //------------------------------------------------------------------------ cout<<"binding to "<<servantName<<endl; /*CosNaming::Name _corbaCosName; _corbaCosName.length(1); _corbaCosName[0].id=CORBA::string_dup("Dummy1");*/ this->m_corbaCosName.length(1); this->m_corbaCosName[0].id=CORBA::string_dup(servantName); //------------------------------------------------------------------------ // Resolve "name text" identifier to an object reference. //------------------------------------------------------------------------ cout<<"Resolving "<<servantName<<endl; //CORBA::Object_var obj1 = nc->resolve(_corbaCosName); this->m_corbaref= this->m_nameContext->resolve(this->m_corbaCosName); assert(!CORBA::is_nil(this->m_corbaref)); cout<<"narrowing AMIExample"<<endl; this->m_remoteInterface= AMIExample::_narrow(this->m_corbaref.in()); if (CORBA::is_nil(this->m_remoteInterface)) { cerr << "IOR is not an SA object reference." << endl; } cout<<servantName<<" Client prepared."<<endl; } catch(CORBA::COMM_FAILURE& ) { cerr << "Caught system exception COMM_FAILURE -- unable to contact the " << "object." << endl; throw DS_ServerConnectionException(); return; } catch(CORBA::SystemException& ) { cerr << "Caught a CORBA::SystemException." << endl; throw DS_SystemException(); return; } catch(CORBA::Exception& ) { cerr << "Caught CORBA::Exception." << endl; throw DS_Exception(); return; } catch(omniORB::fatalException& fe) { cerr << "Caught omniORB::fatalException:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; throw DS_FatalException(); return; } catch(...) { cerr << "Caught unknown exception." << endl; throw DS_Exception(); return; } return; }
Callback Handler:
HPP
#pragma once #include "idl/AmiExample.hh" #include <iostream> #include <fstream> using namespace std; class AmiExampleHandlerImpl : public virtual POA_AMI_AMIExampleHandler { public: AmiExampleHandlerImpl(void); virtual ~AmiExampleHandlerImpl(void); void asyncMe(const char* ami_return_val); void asyncMe_excep(::Messaging::ExceptionHolder* excep_holder); };CPP
#include <fstream> #include <sstream> #include <assert.h> #include "AmiExampleHandlerImpl.hh" AmiExampleHandlerImpl::AmiExampleHandlerImpl(void) { } AmiExampleHandlerImpl::~AmiExampleHandlerImpl(void) { } void AmiExampleHandlerImpl::asyncMe(const char* ami_return_val) { std::cout<<ami_return_val<<"!!!"<<std::endl; } void AmiExampleHandlerImpl::asyncMe_excep(::Messaging::ExceptionHolder* excep_holder) { try { excep_holder->raise_exception(); } catch (CORBA::Exception& ex) { cout << "echoString exception: " << ex._name() << endl; } }
Client Launcher:
CPP
int main(int argc, char** argv) { CORBA::ORB_ptr orb= CORBA::ORB_init(argc, argv); // Resolve and activate the Root POA // Without it, creating Handlers will FAIL! CORBA::Object_var poa_obj = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow(poa_obj); PortableServer::POAManager_var pman = poa->the_POAManager(); pman->activate(); //Create the callback Handler AMI_AMIExampleHandler_ptr handler_ptr = (new AmiExampleHandlerImpl())->_this(); cout<<"Welcome, initialising CORBA CLIENT"<<endl; CorbaAMIClient client(orb); client.m_remoteInterface->sendc_asyncMe(handler_ptr,"HELLO WORLD"); // Wait for a while -- the call should complete within this time omni_thread::sleep(2); getchar(); PortableServer::ObjectId *oid = poa->reference_to_id(handler_ptr); poa->deactivate_object(*oid); poa->destroy(false,false); pman->deactivate(false,false); orb->destroy(); return 0; }
Results:
The client invokes the servant asynchronously:sendc_asyncMe(handler_ptr,"HELLO WORLD!!!");
The servant return "Hello World" so that it is received asynchronously by the Handler:
void AmiExampleHandlerImpl::asyncMe(const char* ami_return_val) { std::cout<<ami_return_val<<"!!!"<<std::endl; }
The callback handler adds three exclamation marks to the response and "Hello World!!!" is shown in the standard output.
Code:
https://dl.dropboxusercontent.com/u/23142124/Visual%20Studio%202010%20C%2B%2B%20CORBA%20with%20OmniOrb%20and%20Java%20ORBD/AMI/CorbaAMIVS2010.zip
Ramon Talavera.
Comments
Post a Comment