Interoperability between C++ and Java
Objects using CORBA
A Tutorial Using
C++Builder 4, JBuilder 2 and VisiGenic ORB
Furrukh S. Khan
Summer 1999
Introduction
This is a tutorial, which demonstrates interoperability between Java
and C++ objects using CORBA. In this tutorial we implement objects
conforming to the following IDL interfaces:
module Bank {
interface Account {
float balance();
};
interface AccountManager {
Account open(in string name);
};
};
This tutorial specifically uses C++Builder 4 (Enterprise Edition) and
JBuilder 2 (Client/Server Edition). Both these products come with
VisiGenic, the commercial ORB from Inprise.
This tutorial guides you, step by step, to build servers in C++ and
Java, which serve objects conforming to the above IDL interfaces, and
to build clients in C++ and Java, which use these objects through these
interfaces. All the servers and clients built in this tutorial can
interoperate, independent of the language of implementation, by using
the VisiGenic ORB.
1
C++
Create Folders
D:\CorbaDemo
D:\CorbaDemo\Cpp
D:\CorbaDemo\Cpp\ClientCpp
D:\CorbaDemo\Cpp\ServerCpp
C++ Server
Start C+Builder4
Start a new CORBA Server project: File->New->Multitier Tag->Corba
SERVER
Choose Console Application in the wizard
Save project: File->Save
Save project in D:\CorbaDemo\Cpp\ServerCpp as [Link]
C++Builder makes the project and automatically produces a
cpp file named [Link] in D:\CorbaDemo\Cpp\ServerCpp
//------------------- [Link] -----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("[Link]");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB and BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
// Wait for incoming requests
boa->impl_is_ready();
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
2
}
return 0;
}
Create [Link]
Choose File->NewMultitier Tag-> CORBA idl File
Save it as [Link] in D:\CorbaDemo\Cpp\ServerCpp
Use the C++Builder editor to enter the following IDL interfaces in
[Link]:
module Bank {
interface Account {
float balance();
};
interface AccountManager {
Account open(in string name);
};
};
Compile [Link]:
Choose Project Manager: view->Project Manager
right click on [Link] in the Project Manager and choose compile
C++Builder produces the following files in the directory
D:\CorbaDemo\Cpp\ServerCpp
Bank_c.hh (header file for stub classes)
Bank_c.cpp (implementation for stub classes)
Bank_s.hh (header file for skeleton classes)
Bank_s.cpp (implementation for skeleton classes)
Implement the AccountManager and Account Interfaces:
Invoke the implementation wizard: File->New->Multitier Tag-> CORBA
Object Implementation
In the wizard, choose:
Unit Name: AccountManagerServer (this is the name of the .h and
.cpp files of the AccountManager implementaion, you will need to
fill in the implementation details of empty methods in the file
[Link])
Class Name: AccountManagerImpl (name of the class which
implements the AccountManager interface. This class will
initially have an empty body, you will need to fill in the
implementation details)
Deligation Tie: Unchecked
In Main: Checked
3
Object Name: AccountManagerObject
C++Builder modifies the [Link] file to:
//------------------- [Link] -----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include "AccountManagerServer.h"
#include <corba.h>
#include <condefs.h>
USEIDL("[Link]");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
USEUNIT("[Link]"); /* [Link]: CORBAIdlFile */
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB and BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
AccountManagerImpl
accountManager_AccountManagerObject("AccountManagerObject");
boa->obj_is_ready(&accountManager_AccountManagerObject);
// Wait for incoming requests
boa->impl_is_ready();
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
}
return 0;
}
Account Interface:
File->New->Multitier Tag-> CORBA Object Implementation
In the wizard, choose:
Unit Name: AccountServer (this is the name of the .h and .cpp files of
the Account implementaion you will need to fill in the implementation
details of empty methods in the file [Link])
Class Name: AccountImpl (name of the class which implements the
interface. This class will initially have an empty body, you will need
to fill in the implementation details)
4
Deligation Tie: unchecked
In Main: Checked
Object Name: AccountObject
CppBuilder modifies the [Link] file to:
//------------------- [Link] -----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include "AccountServer.h"
#include "AccountManagerServer.h"
#include <corba.h>
#include <condefs.h>
USEIDL("[Link]");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
USEUNIT("[Link]"); /* [Link]: CORBAIdlFile */
USEUNIT("[Link]"); /* [Link]: CORBAIdlFile */
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB and BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
AccountManagerImpl
accountManager_AccountManagerObject("AccountManagerObject");
boa->obj_is_ready(&accountManager_AccountManagerObject);
AccountImpl account_AccountObject("AccountObject");
boa->obj_is_ready(&account_AccountObject);
// Wait for incoming requests
boa->impl_is_ready();
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
}
return 0;
}
By now, c++Builder has produces the following .h, and .cpp files, which
contain classes with empty bodies (i.e. no implementation), we need to
fill in the implementaion ourselves. Here are the files as initially
generated:
5
//---------------------- AccountManagerServer.h ---------------------
#ifndef AccountManagerServerH
#define AccountManagerServerH
#include "Bank_s.hh"
//---------------------------------------------------------------------
class AccountManagerImpl: public _sk_Bank::_sk_AccountManager
{
protected:
public:
AccountManagerImpl(const char *object_name=NULL);
Bank::Account_ptr open(const char* name);
};
#endif
//-----------------[Link]----------------------------
#include <corbapch.h>
#pragma hdrstop
#include <corba.h>
#include "AccountManagerServer.h"
//---------------------------------------------------------------------
#pragma package(smart_init)
AccountManagerImpl::AccountManagerImpl(const char *object_name):
_sk_Bank::_sk_AccountManager(object_name)
{
}
Bank::Account_ptr AccountManagerImpl::open(const char* name)
{
}
//----------------- AccountServer.h -----------------------------
#ifndef AccountServerH
#define AccountServerH
#include "Bank_s.hh"
//---------------------------------------------------------------------
class AccountImpl: public _sk_Bank::_sk_Account
{
protected:
public:
AccountImpl(const char *object_name=NULL);
CORBA::Float balance();
};
#endif
//-------------------[Link]---------------------------------
#include <corbapch.h>
#pragma hdrstop
#include <corba.h>
#include "AccountServer.h"
//---------------------------------------------------------------------
#pragma package(smart_init)
6
AccountImpl::AccountImpl(const char *object_name):
_sk_Bank::_sk_Account(object_name)
{
}
CORBA::Float AccountImpl::balance()
{
}
Filling in the empty bodies of the methods
The changes are shown in bold
//---------------------AccountServer.h---------------------------------
#ifndef AccountServerH
#define AccountServerH
#include "Bank_s.hh"
//---------------------------------------------------------------------
class AccountImpl: public _sk_Bank::_sk_Account
{
private:
CORBA::Float _balance;
public:
AccountImpl(const char *object_name=NULL, CORBA::Float
balance=0.0);
CORBA::Float balance();
};
#endif
//-----------------[Link]---------------------------
#include <corbapch.h>
#pragma hdrstop
#include <corba.h>
#include "AccountServer.h"
//---------------------------------------------------------------------
#pragma package(smart_init)
AccountImpl::AccountImpl(const char *object_name, CORBA::Float balance
): _sk_Bank::_sk_Account(object_name), _balance(balance)
{
std::cout<<" Creating Account Object ... "<<std::endl;
}
CORBA::Float AccountImpl::balance()
{
return _balance;
}
7
//-------------AccountManagrServer.h--------------------------
#ifndef AccountManagerServerH
#define AccountManagerServerH
#include "Bank_s.hh"
//---------------------------------------------------------------------
class AccountManagerImpl: public _sk_Bank::_sk_AccountManager
{
private:
int accountCount;
public:
AccountManagerImpl(const char *object_name=NULL);
Bank::Account_ptr open(const char* name);
};
#endif
//------------[Link]---------------------------------
#include <corbapch.h>
#include "AccountServer.h"
#pragma hdrstop
#include <corba.h>
#include "AccountManagerServer.h"
//---------------------------------------------------------------------
#pragma package(smart_init)
AccountManagerImpl::AccountManagerImpl(const char *object_name):
_sk_Bank::_sk_AccountManager(object_name), accountCount(0)
{
std::cout<<"Creating AccountManager Object ... "<<std::endl;
}
Bank::Account_ptr AccountManagerImpl::open(const char* name)
{
++accountCount;
CORBA::Float balance = accountCount*100.0;
AccountImpl* pAccount= new AccountImpl(name, accountCount*100.0 );
_boa()->obj_is_ready(pAccount);
Bank::Account_ptr acc_ptr = Bank::Account::_narrow(pAccount);
return acc_ptr;
}
8
C++ Client
Start C++Builder 4
Copy [Link] to D:\CorbaDemo\Cpp\ClientCpp
Start a new CORBA Server project,
File->New->Multitier Tab->CORBA Client
In the wizard, choose:
Console Application: Checked
Enable VCL: Not Checked
Window Application: Not Checked
BOA init: Checked
Add IDL Files: Add D:\CorbaDemo\Cpp\ClientCpp\[Link]
Save project: File->Save
Save project in D:\CorbaDemo\Cpp\ClientCpp as [Link]
C++Builder automatically makes the file [Link]
//-----------------[Link]-----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("[Link]");
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB and BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
}
return 0;
}
Compile [Link]
view->Project Manager right click on [Link] and choose compile
9
C++Builder produces the files in the directory.
D:\CorbaDemo\Cpp\ClientCpp
Bank_c.hh (header file for stub classes)
Bank_c.cpp (implementation for stub classes)
Bank_s.hh (header file for skeleton classes)
Bank_s.cpp (implementation for stub classes)
C++Builder updates [Link] to:
//-----------------[Link]-----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("[Link]");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB and BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
}
return 0;
}
Fill in the [Link] file.
//-----------------[Link]-----------------------------
#include <corbapch.h>
#pragma hdrstop
//---------------------------------------------------------------------
#include "Bank_c.hh"
#include <corba.h>
#include <condefs.h>
#include <iostream>
USEIDL("[Link]");
USEUNIT("Bank_c.cpp");
USEFILE("Bank_c.hh");
10
USEUNIT("Bank_s.cpp");
//---------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
try
{
// Initialize the ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
Bank::AccountManager_var theAccountManager =
Bank::AccountManager::_bind("AccountManagerObject");
Bank::Account_ptr theAccount1 =
theAccountManager->open("Nadia");
float theBalance = theAccount1->balance();
std::cout<<"The Balance for Account1 is:
"<<theBalance<<std::endl;
Bank::Account_ptr theAccount2 =
theAccountManager->open("Furrukh");
theBalance = theAccount2->balance();
std::cout<<"The Balance for Account2 is:
"<<theBalance<<std::endl;
Bank::Account_var theAccount3 =
Bank::Account::_bind("AccountObject");
theBalance = theAccount3->balance();
std::cout<<"The Balance for Account3 is:
"<<theBalance<<std::endl;
// Pause
char c;
std::cout<<"Input a char to quit ..."<<std::endl;
std::cin>>c;
}
catch(const CORBA::Exception& e)
{
cerr << e << endl;
return(1);
}
return 0;
}
11
Java
Create folders:
D:\CorbaDemo\Java
D:\CorbaDemo\Java\ClientJava
D:\CorbaDemo\Java\ServerJava
Java Client
Start Jbuilder2
File->New Project
Make directory D:\CorbaDemo\Java\clientJava
Save project in this directory
In the properties for this project select:
Project JDK version: Java Version JDK1.1.6_Borland
Source Root Directories: D:\CorbaDemo\Java
Output Root Directory: D:\CorbaDemo\Java
Make sure to add VisiBroker 3.2 to the Java Libraries list
Copy [Link] into this directory
Add [Link] to this project
Compile [Link]
Right click on [Link] in the project explorer and choose Rebuild
The VisiBroker IDL compiler, idl2java, produces the directory
D:\CorbaDemo\Java\Generated Source\Bank, and places the following files
in this directory:
_AccountImplBase.java (skeleton)
_st_Account.java (stub)
[Link] (java interface corresponding to the idl interface)
[Link] (helper class for locating server
implementations)
[Link] (class to enable out parameters in IDL)
_AccountManagerImplBase.java (skeleton)
_st_AccountManager.java (stub)
[Link] (java interface corresponding the idl interface)
[Link] (helper class for locating server
implementations)
[Link] (class to enable out parameters in IDL)
12
//-------------------------[Link]-----------------------------
package clientJava;
import Pause.*;
public class ClientJava {
public static void main(String[] args) {
[Link] orb = [Link](args, null);
[Link] theAccountManager =
[Link](orb,
"AccountManagerObject");
[Link] theAccount1 = [Link]("Nadia");
float theBalance = [Link]();
[Link]("The Balance for Account1 is: "+theBalance );
[Link] theAccount2 = [Link]("Furrukh");
theBalance = [Link]();
[Link]("The Balance for Account2 is: "+theBalance);
[Link] theAccount3 = [Link](orb,
"AccountObject");
theBalance = [Link]();
[Link]("The Balance for Account3 is: "+theBalance);
[Link]();
}
}
Java Server
Start Jbuilder2
File->New Project
Make directory D:\CorbaDemo\Java\serverJava
Save project in this directory
In the properties for this project select:
Project JDK version: Java Version JDK1.1.6_Borland
Source Root Directories: D:\CorbaDemo\Java
Output Root Directory: D:\CorbaDemo\Java
Make sure to add VisiBroker 3.2 to the Java Libraries list
Copy [Link] into this directory
Add [Link] to this project
Compile [Link]
Right click on [Link] in the project explorer and choose Rebuild
The VisiBroker IDL compiler, idl2java, produces the directory
D:\CorbaDemo\Java\Generated Source\Bank (if it already does not exist),
and places the following files in this directory (these files may
already be there if you have already built the Java Client in this
tutorial):
13
_AccountImplBase.java (skeleton)
_st_Account.java (stub)
[Link] (java interface corresponding the idl interface)
[Link] (helper class for locating server
implementations)
[Link] (class to enable out parameters in IDL)
_AccountManagerImplBase.java (skeleton)
_st_AccountManager.java (stub)
[Link] (java interface corresponding the idl interface)
[Link] (helper class for locating server
implementations)
[Link] (class to enable out parameters in IDL)
Implement the Account Interface
Start a new calss: File->New->New Tab->Class
Choose AccountImpl as class name, and fill in the implementation of the
Account interface as follows:
//-------------------------[Link]----------------------------
package ServerJava;
import [Link].*;
public class AccountImpl extends Bank._AccountImplBase {
private float _balance = 0.0f;
public AccountImpl( String objectName, float balance) {
super(objectName);
_balance = balance;
[Link](" Creating Account Object ... ");
}
public float balance() {
return _balance;
}
}
Implement the AccountManager Interface
Start a new calss: File->New->New Tab->Class
Choose AccountManagerImpl as class name, and fill in the implementation
of the AccountManager interface as follows:
//-------------------------[Link]---------------------
package ServerJava;
public class AccountManagerImpl extends Bank._AccountManagerImplBase {
private int accountCount = 0;
public AccountManagerImpl(String objectName) {
super(objectName);
accountCount = 0;
[Link]("Creating AccountManager Object ... ");
14
}
public synchronized [Link] open(String name) {
++accountCount;
float balance = accountCount*100.0f;
[Link] account = new AccountImpl(name, accountCount*100.0f );
_boa().obj_is_ready(account);
return account;
}
}
Creating ServerJava
File->New->VisiBroker Tab->CORBA Server
Java file: D:\CorbaDemo\Java\serverJava\[Link]
Class: AccountManagerImpl
Package: ServerJava
ClassName: ServerJava (this does not have to be the same as the package
name, it just happens to be the same in this example)
Jbuilder produces:
//-------------------[Link]-----------------------------------
package ServerJava;
import [Link].*;
public class ServerJava {
public static void main(String[] args) {
try {
[Link] orb = [Link]();
[Link] boa = orb.BOA_init();
[Link] implObject =
new AccountManagerImpl("AccountManager");
boa.obj_is_ready(implObject);
[Link](implObject+ " is ready.");
boa.impl_is_ready();
}
catch (Exception e) {
[Link]();
}
}
}
Edit this file to:
//-------------------[Link]-----------------------------------
package ServerJava;
import [Link].*;
public class ServerJava {
public static void main(String[] args) {
15
try {
[Link] orb = [Link]();
[Link] boa = orb.BOA_init();
[Link] accountManager_AccountManagerObject =
new AccountManagerImpl("AccountManagerObject");
boa.obj_is_ready(accountManager_AccountManagerObject);
[Link] account_AccountObject =
new AccountImpl("AccountObject", 123.00f);
boa.obj_is_ready(account_AccountObject);
boa.impl_is_ready();
}
catch (Exception e) {
[Link]();
}
}
}
16
Running the Clients and Servers
Finally, follow these steps to use the services provided by the C++ or
Java Servers, in C++ or Java Clients, with complete interoperability.
Run Smart Agrent, which is an object location service provided by
VisiGenic. Smart agent can be run either from the DOS prompt
directly as:
Start->Programs->VisiBroker->VisiBroker Samrt Agent
Or from within C++Builder, and JBuilder as:
Tools->VisiBroker SmartAgent
Start either a C++ or Java server process
For C++ just double click the server executable:
D:\CorbaDemo\Cpp\ServerCpp\[Link]
For Java double click the server project
D:\CorbaDemo\Java\serverJava\[Link]
and select Run->Run ServerJava. After the server starts, you
can minimize the server console window and exit JBuilder. There
is no need for JBuilder to be running.
Now the server is running and waiting to serve clients
Start either a C++ or Java client process
For C++ just double click the client executable:
D:\CorbaDemo\Cpp\ClientCpp\[Link]
For Java double click the client project
D:\CorbaDemo\Java\clientJava\[Link]
and select Run->Run ClientJava.
17