You are on page 1of 17

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 ServerCpp.bpr

C++Builder makes the project and automatically produces a


cpp file named ServerCpp.cpp in D:\CorbaDemo\Cpp\ServerCpp

//------------------- ServerCpp.cpp -----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("Bank.idl");
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 Bank.idl
Choose File->NewMultitier Tag-> CORBA idl File

Save it as Bank.idl in D:\CorbaDemo\Cpp\ServerCpp

Use the C++Builder editor to enter the following IDL interfaces in


Bank.idl:

module Bank {
interface Account {
float balance();
};
interface AccountManager {
Account open(in string name);
};
};

Compile Bank.idl:
Choose Project Manager: view->Project Manager
right click on Bank.idl 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
AccountManagerServer.cpp)

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 ServerCpp.cpp file to:

//------------------- ServerCpp.cpp -----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include "AccountManagerServer.h"

#include <corba.h>
#include <condefs.h>
USEIDL("Bank.idl");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
USEUNIT("AccountManagerServer.cpp"); /* Bank.idl: 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 AccountServer.cpp)

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 ServerCpp.cpp file to:

//------------------- ServerCpp.cpp -----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include "AccountServer.h"

#include "AccountManagerServer.h"

#include <corba.h>
#include <condefs.h>
USEIDL("Bank.idl");
USEUNIT("Bank_c.cpp");
USEUNIT("Bank_s.cpp");
USEUNIT("AccountManagerServer.cpp"); /* Bank.idl: CORBAIdlFile */
USEUNIT("AccountServer.cpp"); /* Bank.idl: 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

//-----------------AccountManagerServer.cpp----------------------------
#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

//-------------------AccountServer.cpp---------------------------------
#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

//-----------------AccountServer.cpp---------------------------
#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

//------------AccountManagerServer.cpp---------------------------------
#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 Bank.idl 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\Bank.idl

Save project: File->Save


Save project in D:\CorbaDemo\Cpp\ClientCpp as Client.bpr

C++Builder automatically makes the file ClientCpp.cpp

//-----------------ClientCpp.cpp-----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("Bank.idl");
//---------------------------------------------------------------------
#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 Bank.idl
view->Project Manager right click on Bank.idl 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 ClientCpp.cpp to:

//-----------------ClientCpp.cpp-----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include <corba.h>
#include <condefs.h>
USEIDL("Bank.idl");
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 ClinetCpp.cpp file.

//-----------------ClientCpp.cpp-----------------------------

#include <corbapch.h>
#pragma hdrstop

//---------------------------------------------------------------------
#include "Bank_c.hh"
#include <corba.h>
#include <condefs.h>
#include <iostream>

USEIDL("Bank.idl");
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 Bank.idl into this directory


Add Bank.idl to this project

Compile Bank.idl

Right click on Bank.idl 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)
Account.java (java interface corresponding to the idl interface)
AccountHelper.java (helper class for locating server
implementations)
AccountHolder.java (class to enable out parameters in IDL)

_AccountManagerImplBase.java (skeleton)
_st_AccountManager.java (stub)
AccountManager.java (java interface corresponding the idl interface)
AccountManagerHelper.java (helper class for locating server
implementations)
AccountManagerHolder.java (class to enable out parameters in IDL)

12
//-------------------------ClientJava.java-----------------------------
package clientJava;
import Pause.*;

public class ClientJava {

public static void main(String[] args) {


org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);

Bank.AccountManager theAccountManager =
Bank.AccountManagerHelper.bind(orb,
"AccountManagerObject");
Bank.Account theAccount1 = theAccountManager.open("Nadia");
float theBalance = theAccount1.balance();
System.out.println("The Balance for Account1 is: "+theBalance );
Bank.Account theAccount2 = theAccountManager.open("Furrukh");
theBalance = theAccount2.balance();
System.out.println("The Balance for Account2 is: "+theBalance);

Bank.Account theAccount3 = Bank.AccountHelper.bind(orb,


"AccountObject");
theBalance = theAccount3.balance();
System.out.println("The Balance for Account3 is: "+theBalance);

Pause.pause();
}
}

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 Bank.idl into this directory


Add Bank.idl to this project

Compile Bank.idl
Right click on Bank.idl 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)
Account.java (java interface corresponding the idl interface)
AccountHelper.java (helper class for locating server
implementations)
AccountHolder.java (class to enable out parameters in IDL)

_AccountManagerImplBase.java (skeleton)
_st_AccountManager.java (stub)
AccountManager.java (java interface corresponding the idl interface)
AccountManagerHelper.java (helper class for locating server
implementations)
AccountManagerHolder.java (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:

//-------------------------AccountImpl.java----------------------------
package ServerJava;
import java.io.*;

public class AccountImpl extends Bank._AccountImplBase {


private float _balance = 0.0f;

public AccountImpl( String objectName, float balance) {


super(objectName);
_balance = balance;
System.out.println(" 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:

//-------------------------AccountManagerImpl.java---------------------
package ServerJava;

public class AccountManagerImpl extends Bank._AccountManagerImplBase {

private int accountCount = 0;

public AccountManagerImpl(String objectName) {


super(objectName);
accountCount = 0;
System.out.println("Creating AccountManager Object ... ");

14
}

public synchronized Bank.Account open(String name) {


++accountCount;
float balance = accountCount*100.0f;
Bank.Account 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\AccountManagerImpl.java


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:

//-------------------ServerJava.java-----------------------------------
package ServerJava;

import java.util.*;

public class ServerJava {

public static void main(String[] args) {


try {
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.BOA boa = orb.BOA_init();
Bank.AccountManager implObject =
new AccountManagerImpl("AccountManager");
boa.obj_is_ready(implObject);
System.out.println(implObject+ " is ready.");
boa.impl_is_ready();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Edit this file to:

//-------------------ServerJava.java-----------------------------------
package ServerJava;

import java.util.*;

public class ServerJava {

public static void main(String[] args) {

15
try {
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.BOA boa = orb.BOA_init();
Bank.AccountManager accountManager_AccountManagerObject =
new AccountManagerImpl("AccountManagerObject");
boa.obj_is_ready(accountManager_AccountManagerObject);
Bank.Account account_AccountObject =
new AccountImpl("AccountObject", 123.00f);
boa.obj_is_ready(account_AccountObject);
boa.impl_is_ready();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

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\ServerCpp.exe
For Java double click the server project
D:\CorbaDemo\Java\serverJava\ServerJava.jpr
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\ClientCpp.exe
For Java double click the client project
D:\CorbaDemo\Java\clientJava\ClientJava.jpr
and select Run->Run ClientJava.

17

You might also like