1. CORBA by Example
G. Roy Antony Arnold
Lecturer / CSE
Infant Jesus College of Engineering
Tuticorin, Tamilnadu, India
2. CORBA Program Steps:
1) Use the idlj compiler to compile *.idl file,
generating up to six files for each interface defined.
2) Implement each interface as a ‘servant’.
3) Create the server (incorporating servants).
4) Compile the server and the idlj-generated files.
5) Create a client.
6) Compile the client.
7) Run the application.
3. 1: Create IDL File
The file will be called Hello.idl and will hold a
module called SimpleExample. The contents of this
file are shown below.
module SimpleExample
{
interface Hello
{
string getGreeting();
};
};
4. 2: Compile IDL file
idlj –fall Hello.idl
This causes a sub-directory with the same name as
the module (i.e.,SimpleExample) to be created,
holding the six files listed below.
• Hello.java
Contains the Java version of our IDL interface. It
extends interface HelloOperations , as well as
org.omg.CORBA.Object (providingstandard
CORBA object functionality) and
org.omg.CORBA.portable.IDLEntity.
5. • HelloHelper.java : Provides auxiliary functionality, notably the
narrow method required to cast CORBA object references into Hello
references.
• HelloHolder.java : Holds a public instance member of type Hello.
If there were any out or inout arguments, this file would also provide
operations for them.
• HelloOperations.java : Contains the Java method signatures for all
operations in our IDL file. In this application, it contains the single
method getGreeting.
• _HelloImplBase.java : An abstract class comprising the server
skeleton. It provides basic CORBA functionality for the server and
implements the Hello interface. Each servant (interface
implementation) that we create for this service must extend
_HelloImplBase.
• _HelloStub.java : This is the client stub, providing CORBA
functionality for the client. Like _HelloImplBase.java, it implements
the Hello interface.
6. 3: Implement the Interface
The implementation of an interface is called a ‘servant’,
so we shall name our implementation class HelloServant.
This class must extend _HelloImplBase. Here is the
code:
class HelloServant extends _HelloImplBase
{
public String getGreeting()
{
return ("Hello there!");
}
}
This class will be placed inside the same file as our server code.
7. 4: Create the Server
The following three standard CORBA packages:
• org.omg.CosNaming (for the naming service);
• org.omg.CosNaming.NamingContextPackage (for special
exceptions thrown by the naming service);
• org.omg.CORBA
There are several steps required of the server…
(i) Create and initialize the ORB.
This is effected by calling static method init of class ORB.
This method takes two arguments: a String array and a
Properties object. The first of these is usually set to the
argument list received by main, while the second is almost
invariably set to null:
ORB orb = ORB.init(args,null);
8. 4: (contd)
(ii) Create a servant.
HelloServant servant = new HelloServant();
(iii) Register the servant with the ORB.
This allows the ORB to pass invocations to the servant and is
achieved by means of the ORB class’s connect method:
orb.connect(servant);
(iv) Get a reference to the root naming context.
Method resolve_initial_references of class ORB is called with the
String argument “NameService” (defined for all CORBA ORBs)
and returns a CORBA Object reference that points to the naming
context:
org.omg.CORBA.Object objectRef =
orb.resolve_initial_references("NameService");
9. 4: (contd)
(v) ‘Narrow’ the context reference.
In order for the generic Object reference from the previous step
to be usable, it must be ‘narrowed’ (i.e., typecast ‘down’ into its
appropriate type). This is achieved by the use of method narrow
of class NamingContextHelper :
NamingContext namingContext =
NamingContextHelper.narrow(objectRef);
(vi) Create a NameComponent object for our interface.
The NameComponent constructor takes two String
arguments, the first of which supplies a name for our service.
The second argument can be used to specify a category for
the first argument, but is typically left as an empty string:
NameComponent nameComp = new
NameComponent("Hello", "");
10. 4: (contd)
(vii) Specify the path to the interface.
This is effected by creating an array of NameComponent
objects, each of which is a component of the path (in
‘descending’ order), with the last component specifying the
name of the NameComponent reference that points to the
service. For a service in the same directory, the array will
contain a single element, as shown below.
NameComponent[] path = (nameComp};
(viii) Bind the servant to the interface path.
The rebind method of the NamingContext object created
earlier is called with arguments that specify the path and
service respectively:
namingContext.rebind(path,servant);
11. 4: (contd)
(ix) Wait for client calls.
Unlike our previous server programs, this is not
achieved via an explicitly ‘infinite’ loop. A call is made
to method wait of (Java class) Object. This call is
isolated within a code block that is declared
synchronized, as shown below.
java.lang.Object syncObj = new java.lang.Object();
synchronized(syncObj)
{
syncObj.wait();
}
12. import SimpleCORBAExample.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
public class HelloServer {
public static void main(String[] args) {
try {
ORB orb = ORB.init(args,null);
HelloServant servant = new HelloServant();
orb.connect(servant);
org.omg.CORBA.Object objectRef = orb.resolve_initial_references("NameService");
NamingContext namingContext = NamingContextHelper.narrow(objectRef);
NameComponent nameComp = new NameComponent("Hello", "");
NameComponent[] path = {nameComp};
namingContext.rebind(path,servant);
java.lang.Object syncObj = new java.lang.Object();
synchronized(syncObj) {
syncObj.wait();
}
}
catch (Exception ex) {
System.out.println("*** Server error! ***");
ex.printStackTrace(); class HelloServant extends _HelloImplBase {
} public String getGreeting() {
} return ("Hello there!");
} }
}