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