An Overview of

Distributed Computing using

CORBA

By

Manjit Dhillon

Advisor: Prof. J. Dicther

Part I: CORBA Overview. 4

brief summaries of all OMG's specifications: 5

corba history?. 6

CORBA Alternatives: 7

Object Management Architecture - OMA: 9

Common Object Request Broker Architecture.. 10

Object Request Broker (ORB) : 11

IDL - Interface Defination Language: 11

Language Mapping: 12

Stubs and Skeletons: 12

Dynamic Invocationa and Dispatch: 14

Object Adapters: 15

IIOP - Internet Inter-ORB Protocols: 16

Conclusion: 17

Part II: CORBA Client and Server.. 18

DEFINING THE IDL. 19

Building the Client: 20

Building the Server: 22

Tips to Run this example: 23

Source Listing. 24

Time.Java  -  source file. 24

TimeOperation.JAVA  -  SOURCE FILE. 25

TimeHelper.JAVA  -  SOURCE FILE. 26

TimeHolder.JAVA  -  SOURCE FILE. 28

_TimeStub.JAVA  -  SOURCE FILE. 29

_TimeImplBase.JAVA  -  SOURCE FILE. 31

Client -  source file. 33

Server  -  source file. 34

Part III: A Distributed Client-Server Example Using JDBC.. 34

IDL.. 35

CORBA CLIENT.. 36

DBAccess.java.. 38

Server Class. 40

IDL generated.. 41

DB.DBAccess.java.. 41

IDL generated  - DB.DBAccessHelper.java.. 42

IDL generated  - DB.DBAccessHolder.java.. 44

IDL generated - DB.DBAccessOperations.java.. 45

IDL generated  - DB._DBAccessStub.java.. 46

IDL generated  - DB._DBAccessImplBase.java.. 48

Part IV – IONA’s Orbix Client Server Example.. 50

Description.. 50

Details. 50

Building the executables. 50

Registering the server.. 50

Running the client.. 50

Expected output.. 51

Client.. 51

Server.. 51

MAKEFILE.. 53

BANKSIMPLE.IDL.. 54

Acknowledgements: 57

Part I: 57

Part II: 57

Part III: 57

Part IV: 57


Part I: CORBA Overview.

To begin a discussion about CORBA we need to have some background on OMG and OMA. CORBA is a complex specification and I have tried to put it in an easy to understand format.

what is omg?

 

Object Management Group, OMG, is a global organization which was founded in April 1989 by eleven companies, including 3Com Corporation, American Airlines, Canon, Inc., Data General, Hewlett-Packard, Philips Telecommunications N.V., Sun Microsystems and Unisys Corporation. Now it has over 800 members who are working towards developing and refining the standards.

In October 1989, the OMG began independent operations as a not-for-profit corporation.

 

what does OMG do?

The OMG manages an open, vendor-neutral process which proposes technologies and invites proposals and invites feedback from any member company before coming to consensus on a final specification, which becomes an adopted standard.  Some of the standards the OMG has developed include

·                    CORBA,

·                    UML and

·                    IIOP.

The OMG is moving forward in establishing CORBA as the "Middleware that's Everywhere" through its worldwide standard specifications: CORBA/IIOP, Object Services, Internet Facilities and Domain Interface specifications, UML and other specifications supporting Analysis and Design.


 

brief summaries of all OMG's specifications:

 

Analysis and Design Specifications:

 

UML, the Unified Modeling Language, is a graphical language that expresses program design in a standard way, allowing design tools to interchange models (using XMI, discussed below). It's an object-oriented language that standardizes an impressive number of diagram types including Class and Object diagrams, Structure diagrams, Use Case diagrams, and more.

 

XMI, for XML Metadata Interchange, is a stream format for interchange of metadata including the UML models that you create during your analysis and design activities. It's useful for transferring the model from one step to the next as your design and coding progress, or for transferring from one design tool to another.

 

OMG's Object Management Architecture (OMA):

 

The OMA - Object Management Architecture - categorizes objects into four categories: the CORBAservices, CORBAfacilities, CORBAdomain objects, and Application Objects.

 

 

CORBA: ( More details below )

 

CORBA is the acronym for Common Object Request Broker Architecture. CORBA is OMG's open, vendor-independent specification for an architecture and infrastructure that computer applications use to work together over networks. Interoperability results from two key parts of the specification: OMG Interface Definition Language (OMG IDL), and the standardized protocols GIOP and IIOP. These allow a CORBA-based program from any vendor, on almost any computer, operating system, programming language, and network, to interoperate with a CORBA-based program from the same or another vendor, on almost any other computer, operating system, programming language, and network.

 


 

corba history?

Historically we are moving from a monolithic sytem to a client - server model.

Mainframes:

In the beginning we had mainframe computers, which had some hierarchical database and dumb terminals. Data and the business logic and all data access functionality where contained in one large application.

PCs:

With the advent of PCs, clients got processing power and we saw the computing model change to the client - server model. Unix servers made smaller companies and departments of bigger corporations more control over their computing environment. This two tier model gave way to a multi - tier client - server model. The application was divided into three parts, the client, the business logic and the database. To enhance this model the next logical step was to introduce a distributed model. A big enterprise would have different systems in the various departments and or counrties it operates in. A need arose to link all these systems via an common interface.   

 

Some Features and Benefits:

CORBA is a complete Distributed Object platfrom. A CORBA ORB connects a client application to the server object it wishes to use. Transparent to the client , the ORB will locate and connect to the Object on the same machine or on a remote machine. The ORB takes care of the details of locating the object, routing the request, and returning the results.

 


 

CORBA Alternatives:

Corba may not be the only way to program distributed systems. These are some of the alternatives to CORBA:

 

Socket programming allow us to communicate between machines or processes on the same machine. The socket API is rather low - level and can to difficult to code for a complex situation.

Remote Procedure Call ( RPC ) provides a function oriented interface to socket level programming. This more high level than scokets, but RPC protocol has incompatible implementations by differrent vendors.

Distributed Component Object Model ( DCOM ) which offers facilities similar to CORBA but it runs most efficiently on the Windows platfrom. It is not a true Object Oriented system. DCOM objects do not maintain state between connections.

Remote Method Invocation ( RMI ) is also similar to CORBA but is a Java only solution. RMI does not support dynamic invocations. It also lacks a inter ORB protocol like IIOP. Though some vendors are working on the DCOM and RMI bridges to ORB.

HTTP/CGI is being used today to deliver web based applications. This protocol is stateless and is very slow. It is not very robust to provide an enterprise solution.


 

can I join OMG?

OMG is mainly for companies who are developing software and want to contribute to the standards being developed by OMG. The fee is based on the sales of the company. The good news is that Universities can become voting members by paying a nominal annual fee.

 

Before diving into the CORBA standard, there are some myths about its founding organization, which I plan to point out and help clear out any mysteries about OMG, OMA or CORBA.

 

some myths about OMG - demystified.

 

myth :  The OMG is only about CORBA and other infrastructure standards.....

 

reality :  Though CORBA is an important part of OMG, other areas it does work in, are, analysis and design work with the Unified Modeling Language™ (UML™) specification which has been an OMG specification since 1997, to the Domain work focused on building consensus in industries such as Telecommunications, Manufacturing, Health Care, Finance, Life Sciences and many more.

 

myth  : The OMG is not a worldwide consortium...

 

reality: OMG is truely a global organization. It has over 800 members spanning the five continents. The OMG is headquartered in Needham, MA, USA and has international marketing offices in Bahrain, Brazil, Germany, India, Italy, Japan and the UK, along with a government representative in Washington, D.C.


 

Object Management Architecture - OMA:

( This forms the basis for CORBA )

 

The OMA is composed of two basic models on which CORBA and all its standard interfaces are based. They are Object Model and Reference Model.

Object Model:

The is defines how object distributed over a hetrogeneous can be described. This is an abstract specification, without going into syntatical details of the oject interfaces. This provides the basis for CORBA, but is more relevant to ORB designers than to application programmers.

Reference Model:

This defines the development model for CORBA and its standard interfaces which the developers can use to create frameworks, compoments and objects. The figure below shows the reference model. The Object Request Broker ( ORB ) is at the center and is reponsible for facilitating communication between clients and ojects. There are four object interface categories which use the ORB. They are

·                    Object Services - These are Domain-independent interfaces and are used  a number of distributed programs. Naming Service is an example of the Object Services. This allows clients to locate objects by names. There are many Object Services specifications for lifecycle management, security, transactions and event notifications.

·                    Domain Interfaces - These interfaces provide support for application from specific industry domains.

·                    Common Facilities - These interfaces provide application level services across domains.

·                    Application Interfaces - These are interfaces which are developed for a specific application.

 

 


 

Common Object Request Broker Architecture

( CORBA )

 

These days we have very large computer systems which need to connect over the network to other systems to exchange data or in some cases use the processing power of better and fast systems. This has made networks very complex and network programming very difficult as, programs have been written in many different languages and are running on different operating systems. A network programmer needs to deal with these issues while designing a distributed application. CORBA defines a framework for developing object-oriented distributed applications. This framework makes network programing easier by making remote objects appear local and the objects can interact as though the have being written in the same language and are on the same machine.

CORBA was one of the first specifications adopted by OMG. It details the interfaces and the characteristics of the ORB component of the OMA. The main features of CORBA are:

·                    ORB

·                    IDL - Interface Defination Language

·                    Interface Repository

·                    Language Mapping

·                    Stubs and Skeletons

·                    Dynamic Invocationa and Dispatch

·                    Object Adapters

·                    IIOP - Inter-ORB Protocols

 


 

Object Request Broker (ORB) :

 

 

 

The ORB delivers request to objects ( the server object )and returns any response to the client object.

 

As evident by the figure above the client invokes the member method of a remote CORBA object. The ORB collects this method call and redirects the method call to the target object over the network. Then the ORB will collect the response and return it to the client.

 

The main feature of the ORB is that it hides the details of the communication between the client and server objects. The ORB allows the programmer to concentrate more on their application, rather than the details of the low level distributed system programming issues. The ORB hides the following from the client:

·                    Object Location: The client does not know where the target object resides.

·                    Object Implementation: The client does not know what language the target object is written in or the operating system / hardware it runs on.

·                    Object Execution State: The client at the time it makes the request does not know if the object is activated. The ORB can transparently start the object if required.

·                    Object Communication mechanisms: The client does not know the low level mechanisms, such as TCP/IP, shared memory, etc ,used by the ORB.

 

The job of the ORB is to provide communication and activation infrastructure for distributed object applications.

 

IDL - Interface Defination Language:

An object's interface specifies the operations and the types supported by the object. This interface is defined using the Interface Defination Language. The IDL is language independent, it is a declarative language and not a programming language. This allows objects written in different programming languages to communicate. For example the client could be a java applet and the server could be written in C++.

 

 

 

 

 

Language Mapping:

In CORBA the objects are not directly coded in the IDL, but as explained the IDL is a declarative language, and not a programming language. Instead language mapping exists to map the IDL features to those of an programming language. For example check the table which shows the IDL type to C++ mapping.

 

There are standardized mapping for Java, C, C++, SmallTalk

and Ada 95. More and more languages are being added. Once you have created an IDL file, you will compile it using a special IDL compiler which will create output source files for the client and the server (explained below). The type of IDL compiler will determine the language of the output files. Each supported language there will be an IDL compiler.For example if you use an IDL to  C++ compiler, then the output would be in C++.

 

 

Stubs and Skeletons:

 

The IDL compiler translates the interfaces and outputs client-side stubs and server-side skeletons. The stubs enable the client to issue requests to the remote objects. While the skeletons on the server deliver the requests to the target objects, and also help to deliver the results back to the client. All the low level network handshaking is hidden in these two files. The programmer can now make a remote method call, without knowing the details of the network protocols.

The process of converting the remote method call into a format to transmit over the network is called marshalling. This has to be undone or unmarshalled at the server-side and convert it back to a method call. The figure below shows this process of making a remote method call.

Using the stubs and skeletons is called static invocation. We need to know the inetrfaces during compile time. This maybe a disadvantage at times, when we are dealing with a very dynamic environment, like a Gateway, which allows foriegn objects to access CORBA objects. We would need to recompile this Gateway everytime someone added an interface to the system. It would be better if this Gateway could dynamically determine the interface information. For this we would need an online Interface database or repository.

 

 

Interface Repository:

 

The Interface Repository is an online database of the ORB object types. The object information stored includes  module, interfaces, operations, attributes and exceptions.

Clients could query this database to find out method in a remote object.


 

Dynamic Invocationa and Dispatch:

Aclient at runtime will query the database and get information about the interfaces. Then it would use a component of the ORB called the Dynamic Call Interface or DII to make a method call. Similar to the DII, on the server we have the Dynamic Skeleton Interface or DSI. The DSI allows the server to be written without the compile time skeletons for the object being invoked.

 

 

 


 

Object Adapters:

 

The final subcomponent of CORBA, the Object Adapters (OA). An OA is an object which that adapts the interface on another object to the inetrface expected by a caller.

The figure below shows graphically the role of the OA. The caller expects interface A, but the target object has an interface called X. To enable communications we need an OA to translate the interface X to A, fro the caller object.

OAs have other roles and help keep the ORB implementation simple. Some responsibilities include,

·                    Object Registration.

·                    Object Reference Generation.

·                    Server Process activation.

·                    Oblect Activation.

·                    Request demultiplexing.

·                    Object upcalls.

 


 

IIOP - Internet Inter-ORB Protocols:

In the earlier releases of CORBA the ORBs from different vendors did not inter-operate. This was due to the fact that  there was no communication protocol defined by the OMG. In CORBA 2.0  a general ORB interoperability architecture was provided to help ORB to ORB interoperability. This was based on the General Inter-ORB Protocol ( GIOP). GIOP is designed to be simple and easy to implement while allowing reasonable scalability and performance. The IIOP specifies how GIOP is built over TCP/IP transport.


 

Conclusion:

 

Recap:

There is lots more to CORBA and distributed application. In my opinion I have covered most for the fundaments of the OMG's CORBA specification.  In a nutshell CORBA is to objects what HTTP is to web pages. Different web pages can be liked from one page. If we write our text in HTML any web server can read and display it. Similarly if we make our application CORBA ready, by using the IDL when any other CORBA objects can interact with this object. The best part is that the low level network programming details are hidden from the programmer.

 


 

Part II: CORBA Client and Server

 

The Timeserver Example:

 

I will describe the basic steps needed to create a distributed application using CORBA and the JAVA IDL. This application is called the Time Server, and the only task of the server is to return the time, when requested by a client. There are three basic steps in building this application. They are

·                    Creating the IDL

·                    The Client and

·                    The Server Program.

 

The server will have a method called "gettime" which will return the time in a string format. The CORBA client will request the ORB for the obejct reference to this server object, also called the "Servant" object. After receiving this object reference it will call this method as if it resides on the local machine. The IDL generated support files and the ORB will marshal the parameters over the network and the server - side ORB will unmarshal the request and pass it to the skelEton files who in turn will invoke the server method. The process is reversed to pass the result back to the client. All the network activity is handled transparent ot the client programmer.


 

DEFINING THE IDL.

 

// Time Server IDL file

 

module TimeServer {

  interface Time      {

    string getTime();

                        };

};

// end of file:

 

Some points about this file:

·                    Module - it acts like a container for realted interfaces and declarations. It maps to the "package" statement in Java.

·                    Interface - maps to the "Interface" statement in Java. The client and server may have different implmentations for the same interface.

·                    Operations - are fucntions that a server will provide to other CORBA clients. This maps to the methods in Java. the method here is called "getTime".

 

Next we compile this file to generate the necessary helper files.

 

c:\>idlj -fall TimeServer.idl

 

Note: we use the -fall switch to generate the server skeleton files.

 

The compiler will create a folder called TimeServer and will generate six files in it. It is important to understand what each file does.

·                    TimeHolder.java - this file is needed to support the out and inout parameter passing modes. In java all parameters are passed by value, so these holder classes are used to provide a level of indirection and are passed instead of the actual type.

·                    TimeHelper.java - This class provides methods for reading and writing the objects to a stream and casting the object to/from a CORBA "Any".

·                    _TimeStub.java - This files helps our client to pass the marshalling information to the ORB.

·                    Time.java - This maps to the IDL file.

·                    TimeOperations.java - This contains all the operations listed in the IDL file.

·                    _TimeImplBase.java - This is the server skeleton file.

 

Check appendix A: for the source for these files and some more explanation.


 

Building the Client:

 

We need to make a call to the getTime() method on the server. The following are the steps needed.

 

We need to import the necessary packages. These are

import TimeServer.*;

import org.omg.CosNaming.*;

import org.omg.CORBA.*;

 

CosNaming contains the Naming Service and all Objects need to use the CORBA package.

 

Next step is to create an ORB object, which will help in marshalling the parameters. Every client needs to instantiate an org.omg.CORBA.ORB object.

 

ORB orb = ORB.init (args, null);

 

Note:

 

ORB class has a method called init().

 

java.lang.Object

  |

  +--org.omg.CORBA.ORB

 

 

Next we need to find the initail naming context. We use the resolve_initial_references() method of the ORB call.

 

org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService");

The string "NamingServer" is defined for all CORBA ORBs.

 

The reference returned is of an generic type, and we need to narrow it down before using it. We narrow it by using the Helper Classes of the naming service.

 

NamingContext ncRef = NamingContextHelper.narrow (objRef);

 

Now that we have a reference to the initial naming context, we need to find the path to our server object. The naming service stores the names in a namecomponent object. these objects are stored in a tree structure, similar to the files and directory structure.

 

So first we create a namecomponent object for our timeserver,

NameComponent nc = new NameComponent ("TimeServer", "");

We need to convert the NameComponent into an array as the resolve() method of the naming service expects an array.

NameComponent path[] = {nc};

Time timeRef = TimeHelper.narrow (ncRef.resolve(path));

We wrap the resolve() method in out TimeHelper.Narrow method to narrow the returning reference.

 

Now we have the object reference of the server object and can use it as if the server object is local. CORBA invocations look like a method call on a local object. The complications of marshaling parameters over the wire, routing them to the server-side ORB, unmarshaling, and placing the upcall to the server method are completely transparent to the client programmer. Because so much is done for you by generated code, invocation is the easiest part of CORBA programming.

 

String time = "Time on the Server is " + timeRef.getTime ();

 

Finally, we add code to print the results of the invocation to standard output

 

System.out.println (time);

 


 

Building the Server:

A server is a process which instantiates one or more servant objects. The servants implement the interface generated by the IDL and it handles the operations listed in the IDL.

 

The Servant Class.

 

We define the class for the servant object as follows.

 

class TimeServer extends _TimeImplBase {

 public String getTime () {

  SimpleDateFormat formatter =

  new SimpleDateFormat ("MMMMM dd, yyyyy GGG, hh:mm:ss:SSS aaa");

  Date date = new Date ();

  return formatter.format ( date );

 }

}

 

This class extends the skeleton class generated by the IDL compiler. It also has the getTime operation.

 

 

The Server Class:

 

We first create an obejct of the timeserver class.

TimeServer timeRef = new TimeServer ();

 

Next, we connect the servant to the ORB, so the ORB can recognize invocations on it and pass them along to the correct servant:

orb.connect (timeRef);

 

Like the client we need to get the object reference to the initial naming context and narrow the reference to the namingcontext type.

org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService");

NamingContext ncRef = NamingContextHelper.narrow (objRef);

 

Registering the servant with the Name Service.

Now we create a NameComponent called "TimeServer".

NameComponent nc = new NameComponent ("TimeServer", "");

NameComponent path[] = {nc};

 

Next we have to bind the servant object reference to the namecomponent and add it to the naming context.

ncRef.rebind (path, timeRef);

 

Now, when the client calls resolve("TimeServer") on the initial naming context, the Naming Service returns an object reference to the Time servant.

 

Now the server just waits for a client invocation.


 

Tips to Run this example:

 

1> Start the name service by typing the following

C:\>tnameserv

 

This will start the Naming Service on the default port of 900.

 

2> Start the Server.

C:\>java Server

 

3>Run the Client.

C:\>java Client

 

 


 

Source Listing.

 

 

Time.Java  -  source file.

 

 

This files maps to the IDL file.

package TimeServer;

/**

* TimeServer/Time.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:12 PM EST

*/

 

public interface Time extends TimeOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity

{

} // interface Time

 

 


 

TimeOperation.JAVA  -  SOURCE FILE.

 

package TimeServer;

 

 

/**

* TimeServer/TimeOperations.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:12 PM EST

*/

 

public interface TimeOperations

{

  String getTime ();

} // interface TimeOperations

 


 

TimeHelper.JAVA  -  SOURCE FILE.

 

package TimeServer;

 

 

/**

* TimeServer/TimeHelper.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:11 PM EST

*/

 

abstract public class TimeHelper

{

  private static String  _id = "IDL:TimeServer/Time:1.0";

 

  public static void insert (org.omg.CORBA.Any a, TimeServer.Time that)

  {

    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();

    a.type (type ());

    write (out, that);

    a.read_value (out.create_input_stream (), type ());

  }

 

  public static TimeServer.Time extract (org.omg.CORBA.Any a)

  {

    return read (a.create_input_stream ());

  }

 

  private static org.omg.CORBA.TypeCode __typeCode = null;

  synchronized public static org.omg.CORBA.TypeCode type ()

  {

    if (__typeCode == null)

    {

      __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc (TimeServer.TimeHelper.id (), "Time");

    }

    return __typeCode;

  }

 

  public static String id ()

  {

    return _id;

  }

 

  public static TimeServer.Time read (org.omg.CORBA.portable.InputStream istream)

  {

    return narrow (istream.read_Object (_TimeStub.class));

  }

 

  public static void write (org.omg.CORBA.portable.OutputStream ostream, TimeServer.Time value)

  {

    ostream.write_Object ((org.omg.CORBA.Object) value);

  }

 

  public static TimeServer.Time narrow (org.omg.CORBA.Object obj)

  {

    if (obj == null)

      return null;

    else if (obj instanceof TimeServer.Time)

      return (TimeServer.Time)obj;

    else if (!obj._is_a (id ()))

      throw new org.omg.CORBA.BAD_PARAM ();

    else

    {

      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();

      return new TimeServer._TimeStub (delegate);

    }

  }

 

}

 


 

TimeHolder.JAVA  -  SOURCE FILE.

 

package TimeServer;

 

/**

* TimeServer/TimeHolder.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:11 PM EST

*/

 

public final class TimeHolder implements org.omg.CORBA.portable.Streamable

{

  public TimeServer.Time value = null;

 

  public TimeHolder ()

  {

  }

 

  public TimeHolder (TimeServer.Time initialValue)

  {

    value = initialValue;

  }

 

  public void _read (org.omg.CORBA.portable.InputStream i)

  {

    value = TimeServer.TimeHelper.read (i);

  }

 

  public void _write (org.omg.CORBA.portable.OutputStream o)

  {

    TimeServer.TimeHelper.write (o, value);

  }

 

  public org.omg.CORBA.TypeCode _type ()

  {

    return TimeServer.TimeHelper.type ();

  }

 

}


 

_TimeStub.JAVA  -  SOURCE FILE.

 

package TimeServer;

 

 

/**

* TimeServer/_TimeStub.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:11 PM EST

*/

 

public class _TimeStub extends org.omg.CORBA.portable.ObjectImpl implements TimeServer.Time

{

  // Constructors

  // NOTE:  If the default constructor is used, the

  //        object is useless until _set_delegate (...)

  //        is called.

  public _TimeStub ()

  {

    super ();

  }

 

  public _TimeStub (org.omg.CORBA.portable.Delegate delegate)

  {

    super ();

    _set_delegate (delegate);

  }

 

  public String getTime ()

  {

    org.omg.CORBA.portable.InputStream _in = null;

    try {

       org.omg.CORBA.portable.OutputStream _out = _request ("getTime", true);

       _in = _invoke (_out);

       String __result = _in.read_string ();

       return __result;

    } catch (org.omg.CORBA.portable.ApplicationException _ex) {

       _in = _ex.getInputStream ();

       String _id = _ex.getId ();

       throw new org.omg.CORBA.MARSHAL (_id);

    } catch (org.omg.CORBA.portable.RemarshalException _rm) {

       return getTime ();

    } finally {

        _releaseReply (_in);

    }

  } // getTime

 

  // Type-specific CORBA::Object operations

  private static String[] __ids = {

    "IDL:TimeServer/Time:1.0"};

 

  public String[] _ids ()

  {

    return (String[])__ids.clone ();

  }

 

  private void readObject (java.io.ObjectInputStream s)

  {

     try

     {

       String str = s.readUTF ();

       org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init ().string_to_object (str);

       org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();

       _set_delegate (delegate);

     } catch (java.io.IOException e) {}

  }

 

  private void writeObject (java.io.ObjectOutputStream s)

  {

     try

     {

       String str = org.omg.CORBA.ORB.init ().object_to_string (this);

       s.writeUTF (str);

     } catch (java.io.IOException e) {}

  }

} // class _TimeStub

 


 

 

_TimeImplBase.JAVA  -  SOURCE FILE.

 

package TimeServer;

 

 

/**

* TimeServer/_TimeImplBase.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from TimeServer.idl

* Tuesday, November 28, 2000 8:57:11 PM EST

*/

 

public abstract class _TimeImplBase extends org.omg.CORBA.portable.ObjectImpl

                implements TimeServer.Time, org.omg.CORBA.portable.InvokeHandler

{

 

  // Constructors

  public _TimeImplBase ()

  {

  }

 

  private static java.util.Hashtable _methods = new java.util.Hashtable ();

  static

  {

    _methods.put ("getTime", new java.lang.Integer (0));

  }

 

  public org.omg.CORBA.portable.OutputStream _invoke (String method,

                                org.omg.CORBA.portable.InputStream in,

                                org.omg.CORBA.portable.ResponseHandler rh)

  {

    org.omg.CORBA.portable.OutputStream out = null;

    java.lang.Integer __method = (java.lang.Integer)_methods.get (method);

    if (__method == null)

      throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

 

    switch (__method.intValue ())

    {

       case 0:  // TimeServer/Time/getTime

       {

         String __result = null;

         __result = this.getTime ();

         out = rh.createReply();

         out.write_string (__result);

         break;

       }

 

       default:

         throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

    }

 

    return out;

  } // _invoke

 

  // Type-specific CORBA::Object operations

  private static String[] __ids = {

    "IDL:TimeServer/Time:1.0"};

 

  public String[] _ids ()

  {

    return __ids;

  }

 

 

} // class _TimeImplBase

 


 

Client -  source file.

 

import TimeServer.*; // The package containing our stubs.

import org.omg.CosNaming.*; // Client will use the naming service.

import org.omg.CORBA.*; // All CORBA applications need these classes.

 

public class Client {

 public static void main (String args[]) {

  try {

   // Create and initialize the ORB

   ORB orb = ORB.init (args, null);

   // Get the root naming context

   org.omg.CORBA.Object objRef =

                                orb.resolve_initial_references ("NameService");

   NamingContext ncRef = NamingContextHelper.narrow (objRef);

   // Resolve the object reference in naming

   NameComponent nc = new NameComponent ("TimeServer", "");

   NameComponent path[] = {nc};

   Time timeRef = TimeHelper.narrow (ncRef.resolve (path));

   // Call the time server object and print results

   String time = "Time on the Server is " + timeRef.getTime ();

   System.out.println (time);

  } catch (Exception e) {

   e.printStackTrace ();

  }

 }

}


 

Server  -  source file.

// The package containing our stubs.

import Tracker.*;

// Server will use the naming service.

import org.omg.CosNaming.*;

// The package containing special exceptions thrown by the name

// service.

import org.omg.CosNaming.NamingContextPackage.*;

// All CORBA applications need these classes.

import org.omg.CORBA.*;

 

import java.util.*;

import java.text.*;

 

class TimeServer extends _TimeImplBase {

 public String getTime () {

  SimpleDateFormat formatter =

              new SimpleDateFormat ("MMMMM dd, yyyyy GGG, hh:mm:ss:SSS aaa");

  Date date = new Date ();

  return formatter.format (date);

 }

}

public class Server {

 public static void main (String args[]) {

  try {

   // Create and initialize the ORB

   ORB orb = ORB.init (args, null);

   // Create the servant and register it with the ORB

   TimeServer timeRef = new TimeServer ();

   orb.connect (timeRef);

   // Get the root naming context

   org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService");

   NamingContext ncRef = NamingContextHelper.narrow (objRef);

   // Bind the object reference in naming

   NameComponent nc = new NameComponent ("TimeServer", "");

   NameComponent path[] = {nc};

   ncRef.rebind (path, timeRef);

   // Wait forever for current thread to die

   Thread.currentThread ().join ();

  } catch (Exception e) {

   e.printStackTrace ();

  }  } }

Part III: A Distributed Client-Server Example Using JDBC

 

______<<Source Listing and Explanations>>_____

 

The first step in making a distributed CORBA application is to determine the interfaces that will be exposed through this process. This is an example of a client-server application. The client calls a method of the remote server object. This method contains some JDBC code needed to query the database on the server. The results are then returned to the client. In this example we query an Access database, using the JDBC-ODBC Bridge built into Java 2. I have included the source and relevant explanation below.


IDL

This IDL file contains one interface, called DBAccess. This contains one operation called runQuery. After creating this file, we compile it using the idl compiler in Java 2. This will create the stub and the skeleton files. Some helper files will also be created. Those files are listed below.

 

// module maps to the Java Package statement

module DB {

// interface maps to the Java Interface statement

  interface DBAccess {

/* we have defined one operation called runQuery

 this maps to a method*/

            string runQuery(in string query);

  };

};

 

_____<Completes the list of DBAccess.idl>______

 


CORBA CLIENT

The client firsts initializes an ORB. Then it tries to find the Initial Naming Context of the Naming Service. Then it looks for the reference to the remote object in the Naming Service. After receiving this, it narrows the reference and then calls the remote method.

 

 

 

import DB.*;

/* this folder holds all the files generated by the IDL compiler */

 

import org.omg.CosNaming.*;

/* Client will use the naming service. */

 

import org.omg.CORBA.*;

/* All CORBA applications need these classes. */

 

/*Client Class starts*/

public class Client {

 

 public static void main (String args[]) {

  String str;

/* checks if the user has send any SQL string*/

  if( args.length == 0) {

    str = "SELECT * FROM test";

    System.out.println("Using default sql query -> " + str);  

  }

  else

  {

    str = args[0];

  }

/* Wrap the CORBA ORB communication in a try-catch loop*/

  try {

   // Create and initialize the ORB

   ORB orb = ORB.init (args, null);

 

   /* Get the root naming context and narrow it down using the helper classes*/

   org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService");

   NamingContext ncRef = NamingContextHelper.narrow (objRef);

 

   // Resolve the object reference in naming

   NameComponent nc = new NameComponent ("DBAccess", "");

   NameComponent path[] = {nc};

/* In one step we get the Object Reference and cast it to the proper type*/

   DB.DBAccess dbRef = DBAccessHelper.narrow (ncRef.resolve (path));

 

   // Call the time server object and print results

   String query = "The result: \n" + dbRef.runQuery (str);

   System.out.println (query);

  } catch (Exception e) {

   e.printStackTrace ();

  } //end try-catch

 } // end main()

}//end class 

 

_____<Completes the list of Client.java>______


DBAccess.java

This class implements the method mention in the IDL. This class sits on the server and the server program will create an object of this class and register it with the Naming Service. This class also contains some JDBC code. The first step is to load the JDBC-ODBC Brdige. Then we attach a ODBC connection to this. Then we create a Statement object and pass it the SQL we want to run. The executeUpdate method will send the query to the database. The results are returned in a Resultset Object.

 

// The package containing our stubs.

import DB.*;

// This package contains the JDBC classes

import java.sql.*;

// Server will use the naming service.

import org.omg.CosNaming.*;

/* The package containing special exceptions thrown by the name

service.*/

import org.omg.CosNaming.NamingContextPackage.*;

// All CORBA applications need these classes.

import org.omg.CORBA.*;

 

import java.util.*;

import java.text.*;

/* This is our class which contains the interface and the operaton defined in the IDL. This class extends the server-side skeleton files*/

class DBAccess extends _DBAccessImplBase {

//This is the operation that is exposed through the IDL

public String runQuery (String q) {

 String name = "";

 

// The JDBC database operations are done in a try-catch block.

try {

 

// Load the JDBC-ODBC Bridge.

  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();

           

// make a connection to the specified URL

  Connection con = DriverManager.getConnection( "jdbc:odbc:Shalimar_Access", "", "");

       

// get a Statement object from the Connection

  Statement stmt = con.createStatement();

           

/* ignore any exception for DROP TABLE; it will most assuredly throw one if the table does not exist*/

    try {

         stmt.executeUpdate("DROP TABLE test");

        } catch (Exception e) {

                // do nothing

        }

       

// create a table

 stmt.executeUpdate("CREATE TABLE test(name CHAR(25), id INT) " );

           

// insert a couple of rows.

 stmt.executeUpdate("INSERT INTO test VALUES('Brian', 1)");

 stmt.executeUpdate("INSERT INTO test VALUES('Hank',  2)");

           

// Execute a query

 ResultSet rs = stmt.executeQuery(q);

 

  while(rs.next()) {

// retrieve each column by name

   name += rs.getString("name") + ", ID: " + rs.getInt("id") + "\n";

 }

 

                        System.out.print(name);

          stmt.close();

          con.close();

          System.out.println("Operation successful.");

        } catch (Exception e) {

            e.printStackTrace();

            System.exit(-1);

        }

  return (name);

 }

}

 

_____<Completes the list of DBAccess.java>______

 


Server Class

The server class contains code to created a new DBAccess object. This object reference is added to the Naming Service. Then the server just waits of an invocation.

 

 

 

// The package containing our stubs.

import DB.*;

 

// Server will use the naming service.

import org.omg.CosNaming.*;

 

/* The package containing special exceptions thrown by the name

service.*/

import org.omg.CosNaming.NamingContextPackage.*;

 

// All CORBA applications need these classes.

import org.omg.CORBA.*;

 

import java.util.*;

import java.text.*;

 

/* This class creates the CORBA object and makes it available to the naming service*/

public class Server {

 

 public static void main (String args[]) {

  try {

// Create and initialize the ORB

   ORB orb = ORB.init (args, null);

 

// Create the servant and register it with the ORB

   DBAccess dbRef = new DBAccess ();

   orb.connect (dbRef);

 

// Get the root naming context and narrow it

   org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService");

   NamingContext ncRef = NamingContextHelper.narrow (objRef);

 

// Bind the object reference in naming

   NameComponent nc = new NameComponent ("DBAccess", "");

   NameComponent path[] = {nc};

   ncRef.rebind (path, dbRef);

// Wait forever for current thread to die

   Thread.currentThread ().join ();

  } catch (Exception e) {

   e.printStackTrace ();

  }

 }

}

 

 

_____<Completes the list of Server.java>______

 


IDL generated

DB.DBAccess.java

 

The follow source files are generated by the IDL compiler. The are used to translate the User defined objects to the ORB. The ORB knows how to transmit the data over the wires, but it does not know the classed defined by the user. These IDL generated files help the ORB to understand these classes.
This file contains the class which maps to the interface statement in the IDL.

 

package DB;

 

 

/**

* DB/DBAccess.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

public interface DBAccess extends DBAccessOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity

{

} // interface DBAccess

 

_____<Completes the list of DB.DBAccess.java>______

 


IDL generated  - DB.DBAccessHelper.java

This files contains an important method called “narrow”. This is used to convert the type of the Object Reference returned. This method provides functionality similar to the casting operation.

 

package DB;

 

 

/**

* DB/DBAccessHelper.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

abstract public class DBAccessHelper

{

  private static String  _id = "IDL:DB/DBAccess:1.0";

 

  public static void insert (org.omg.CORBA.Any a, DB.DBAccess that)

  {

    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();

    a.type (type ());

    write (out, that);

    a.read_value (out.create_input_stream (), type ());

  }

 

  public static DB.DBAccess extract (org.omg.CORBA.Any a)

  {

    return read (a.create_input_stream ());

  }

 

  private static org.omg.CORBA.TypeCode __typeCode = null;

  synchronized public static org.omg.CORBA.TypeCode type ()

  {

    if (__typeCode == null)

    {

      __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc (DB.DBAccessHelper.id (), "DBAccess");

    }

    return __typeCode;

  }

 

  public static String id ()

  {

    return _id;

  }

 

  public static DB.DBAccess read (org.omg.CORBA.portable.InputStream istream)

  {

    return narrow (istream.read_Object (_DBAccessStub.class));

  }

 

  public static void write (org.omg.CORBA.portable.OutputStream ostream, DB.DBAccess value)

  {

    ostream.write_Object ((org.omg.CORBA.Object) value);

  }

 

  public static DB.DBAccess narrow (org.omg.CORBA.Object obj)

  {

    if (obj == null)

      return null;

    else if (obj instanceof DB.DBAccess)

      return (DB.DBAccess)obj;

    else if (!obj._is_a (id ()))

      throw new org.omg.CORBA.BAD_PARAM ();

    else

    {

      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();

      return new DB._DBAccessStub (delegate);

    }

  }

 

}

 

_____<Completes the list of DB.DBAccessHelper.java>______

 


IDL generated  - DB.DBAccessHolder.java

Holder class is generated to provide support to the out and inout parameter passing modes.

 

package DB;

 

/**

* DB/DBAccessHolder.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

public final class DBAccessHolder implements org.omg.CORBA.portable.Streamable

{

  public DB.DBAccess value = null;

 

  public DBAccessHolder ()

  {

  }

 

  public DBAccessHolder (DB.DBAccess initialValue)

  {

    value = initialValue;

  }

 

  public void _read (org.omg.CORBA.portable.InputStream i)

  {

    value = DB.DBAccessHelper.read (i);

  }

 

  public void _write (org.omg.CORBA.portable.OutputStream o)

  {

    DB.DBAccessHelper.write (o, value);

  }

 

  public org.omg.CORBA.TypeCode _type ()

  {

    return DB.DBAccessHelper.type ();

  }

 

}

____<Completes the list of DB.DBAccessHolder.java>______


IDL generated - DB.DBAccessOperations.java

This files contains the operations mentioned in the IDL file.

 

package DB;

 

 

/**

* DB/DBAccessOperations.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

public interface DBAccessOperations

{

  String runQuery (String query);

} // interface DBAccessOperations

 

_____<Completes the list of DB.DBAccessOperations.java>______

 

 


IDL generated  - DB._DBAccessStub.java

This is the client stub file. The client uses this file to talk to the ORB.

 

package DB;

 

 

/**

* DB/_DBAccessStub.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

public class _DBAccessStub extends org.omg.CORBA.portable.ObjectImpl implements DB.DBAccess

{

  // Constructors

  // NOTE:  If the default constructor is used, the

  //        object is useless until _set_delegate (...)

  //        is called.

  public _DBAccessStub ()

  {

    super ();

  }

 

  public _DBAccessStub (org.omg.CORBA.portable.Delegate delegate)

  {

    super ();

    _set_delegate (delegate);

  }

 

  public String runQuery (String query)

  {

    org.omg.CORBA.portable.InputStream _in = null;

    try {

       org.omg.CORBA.portable.OutputStream _out = _request ("runQuery", true);

       _out.write_string (query);

       _in = _invoke (_out);

       String __result = _in.read_string ();

       return __result;

    } catch (org.omg.CORBA.portable.ApplicationException _ex) {

       _in = _ex.getInputStream ();

       String _id = _ex.getId ();

       throw new org.omg.CORBA.MARSHAL (_id);

    } catch (org.omg.CORBA.portable.RemarshalException _rm) {

       return runQuery (query);

    } finally {

        _releaseReply (_in);

    }

  } // runQuery

 

  // Type-specific CORBA::Object operations

  private static String[] __ids = {

    "IDL:DB/DBAccess:1.0"};

 

  public String[] _ids ()

  {

    return (String[])__ids.clone ();

  }

 

  private void readObject (java.io.ObjectInputStream s)

  {

     try

     {

       String str = s.readUTF ();

       org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init ().string_to_object (str);

       org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();

       _set_delegate (delegate);

     } catch (java.io.IOException e) {}

  }

 

  private void writeObject (java.io.ObjectOutputStream s)

  {

     try

     {

       String str = org.omg.CORBA.ORB.init ().object_to_string (this);

       s.writeUTF (str);

     } catch (java.io.IOException e) {}

  }

} // class _DBAccessStub

 

_____<Completes the list of DB._DBAccessStub.java>______

 


IDL generated  - DB._DBAccessImplBase.java

This the server-skeleton file. This sits on the server-side and call the methods requested by the client. The requests are received by the ORB, which needs this file to find the object and the method requested.

 

package DB;

 

 

/**

* DB/_DBAccessImplBase.java

* Generated by the IDL-to-Java compiler (portable), version "3.0"

* from DBAccess.idl

* Monday, December 4, 2000 4:22:43 PM EST

*/

 

public abstract class _DBAccessImplBase extends org.omg.CORBA.portable.ObjectImpl

                implements DB.DBAccess, org.omg.CORBA.portable.InvokeHandler

{

 

  // Constructors

  public _DBAccessImplBase ()

  {

  }

 

  private static java.util.Hashtable _methods = new java.util.Hashtable ();

  static

  {

    _methods.put ("runQuery", new java.lang.Integer (0));

  }

 

  public org.omg.CORBA.portable.OutputStream _invoke (String method,

                                org.omg.CORBA.portable.InputStream in,

                                org.omg.CORBA.portable.ResponseHandler rh)

  {

    org.omg.CORBA.portable.OutputStream out = null;

    java.lang.Integer __method = (java.lang.Integer)_methods.get (method);

    if (__method == null)

      throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

 

    switch (__method.intValue ())

    {

       case 0:  // DB/DBAccess/runQuery

       {

         String query = in.read_string ();

         String __result = null;

         __result = this.runQuery (query);

         out = rh.createReply();

         out.write_string (__result);

         break;

       }

 

       default:

         throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

    }

 

    return out;

  } // _invoke

 

  // Type-specific CORBA::Object operations

  private static String[] __ids = {

    "IDL:DB/DBAccess:1.0"};

 

  public String[] _ids ()

  {

    return __ids;

  }

 

 

} // class _DBAccessImplBase

 

 

_____<Completes the list of DB._DBAccessImplBase.java>______

 

 

 

 

 

 


Part IV – IONA’s Orbix Client Server Example

 

BankSimple Example:

Description

The server implements two types of objects. On start-up it contains a single Bank objects, by calling the create_account method, clients can request the Bank to create a named Account object, or to look up an Account by name. Accounts allow you to to make deposits, withdrawals etc.

The client is a simple console menu based application which calls operations defined by in banksimple.idl. Parts of the IDL are given below;

The completed is attached at the back.

interface Bank

{

Account create_account (in string name); // Create a new account.

Account find_account (in string name); // Find an existing account.

};

The Bank interface lets you create an account or find an existing acccount.

interface Account

{

readonly attribute string name;

readonly attribute CashAmount balance;

void deposit (in CashAmount amount);

void withdraw (in CashAmount amount);

};

The account interface has methods to deposit, withdraw, get cash balance and the name attribute on the account.

Details

·        banksimple.idl: defines the IDL interfaces . The interfaces are defined inside a module to prevent clashes with similarly named interfaces defined in the other bank demos.

·        client.cxx: The main client program, does client initialization and then starts a menu. Uses the following files:

·        bankmenu.h, bankmenu.cxx: menu code which calls operations on the IDL Bank interface

·        accountmenu.h, accountmenu.cxx: menu code which calls operations on the IDL Account interface

·        server.cxx: the main server program, initializes the server and creates IDL implementation objects. Uses the following files:

·        banksimple_bankimpl.h, banksimple_bankimpl.cxx: Class which implements the Bank IDL interface

·        banksimple_accountimpl.h, banksimple_accountimpl.cxx: Class which implements the Account IDL interface

Building the executables.

Type nmake to build the executables.

Registering the server

First start a Dos Window and change to the "c:\iona\config" folder. I have installed IONA on my "c:" drive and in the default folder. Run the batch file called "orbvars.bat" which sets all the environment variables. Now start the Orbix ORB by typing the following command,

Type start orbixd to start the ORB

Type nmake /I register to register the servers

The makefile has the necessary commands to start the naming service and create the entries for the current application. The complete makefile is attached at the back.

 

Running the client

Type client to run the client. The client will display a text menu allowing you to choose the actions you want to take, and then prompt you for the necessary information. The server outputs messages when it processes incoming calls - you can see these messages by looking at the Orbix daemon's output window.

 

Expected output

The following is a sample of the output from the client and server

 

Client

client

[192: New IIOP Connection (machine:1570) ]

[192: New IIOP Connection (machine:1591) ]

0 - quit

1 - create_account

2 - find_account

Enter selection (0 - 2): 1

Enter account name: fred

[192: New IIOP Connection (machine:1595) ]

Using account named fred

0 - quit

1 - get the name attribute

2 - get the balance attribute

3 - call deposit operation

4 - call withdraw operation

Enter selection (0 - 4): 3

Current balance is: 0

Enter amount to deposit: 1000

Depositing 1000

New balance is: 1000

0 - quit

1 - get the name attribute

2 - get the balance attribute

3 - call deposit operation

4 - call withdraw operation

Enter selection (0 - 4): 4

Current balance is: 1000

Enter amount to withdraw: 345.26

Withdrawing 345.26

New balance is: 654.74

 

Server

[IT_Demo/BankSimple/Bank: Server "IT_Demo/BankSimple/Bank" is now available to the network ]

[ Configuration tcp/1604/cdr ]

[IT_Demo/BankSimple/Bank: New IIOP Connection (machine:1604) ]

create_account: Created account with name: fred

name: returning value fred

balance: returning value 0

deposit: amount = 1000

balance: returning value 1000

balance: returning value 1000

withdraw: amount = 345.26

balance: returning value 654.74

Screen snap shoots are included.


MAKEFILE

# @ Copyright 1998 IONA Technologies, PLC. All Rights Reserved.

#

# @ VERSION: Orbix 3.0c

#

 

 

# Include standard make variables & rules

#

!include "..\..\orbixcpp.mk"

 

DEMO=BankSimple

IDL_BASENAME=banksimple

 

 

CLIENT_OBJS=$(IDL_BASENAME)$(IDL_CLT_OBJ) BankMenu.obj AccountMenu.obj client.obj

 

SERVER_OBJS=$(IDL_BASENAME)$(IDL_SRV_OBJ) $(IDL_BASENAME)_BankImpl.obj \

            $(IDL_BASENAME)_AccountImpl.obj server.obj

 

 

# The following make rules differ slightly between demos.

#

 

all: build

 

build: DemoLib client.exe server.exe

            @echo == Build complete, to register server type: $(MAKE) /I register

 

register:

            @echo == Checking that the orbix daemon is running ...

            $(ORBIX_BINDIR)\pingit

            @echo == Make Imp.Rep. and NS directories

            @echo == Ignore errors indicating the directories already exist

            $(ORBIX_BINDIR)\mkdirit IT_Demo

            $(ORBIX_BINDIR)\mkdirit IT_Demo/$(DEMO)

            $(ORBIX_BINDIR)\putit NS "%ORBIX_HOME%\bin\ns.bat"

            $(ORBIX_BINDIR)\putit IT_Demo/$(DEMO)/Bank $(MAKEDIR)\server.exe

            $(NAMES_ROOT)\bin\putnewncns IT_Demo

            $(NAMES_ROOT)\bin\putnewncns IT_Demo.$(DEMO)

            server -bindns -timeout 0

            @echo == Now run the client by typing: client

 

 

clean: default_clean

 

 

# IDL compile rule (invokes implicit .idl.hh rule)

$(IDL_BASENAME)$(IDL_CLT_CPP) $(IDL_BASENAME)$(IDL_SRV_CPP): $(IDL_BASENAME).hh

 

client.exe: $(CLIENT_OBJS)

            $(LINK) $(LINK_FLAGS_EXE) /OUT:$@ $(CLIENT_OBJS) $(LINK_LIBS)

 

server.exe: $(SERVER_OBJS)

            $(LINK) $(LINK_FLAGS_EXE) /OUT:$@ $(SERVER_OBJS) $(LINK_LIBS)

 

 

BANKSIMPLE.IDL

 

// @ Copyright 1999 IONA Technologies, PLC. All Rights Reserved.

// @ VERSION: Orbix 3.0c

 

// DESCRIPTION:

// IDL for a simple, no-frills client/server Bank

// NOTE: These interfaces don't provide exceptions to indicate

// when things go wrong

//

 

#ifndef _BANK_BANKSIMPLE_IDL_

#define _BANK_BANKSIMPLE_IDL_

 

// Put our definitions inside a module to prevent namespace clashes.

//

module BankSimple

{

            typedef float CashAmount;        // Define a named type to represent money.

 

            interface Account;                     // Forward reference, Account is defined below.

 

            // The Bank creates or locates Accounts.

            //

            interface Bank

            {

                        Account create_account (in string name); // Create a new account.

                        Account find_account   (in string name); // Find an existing account.

            };

   

            // The account lets you check your balance, deposit or withdraw money.

            //

            interface Account

            {

                        readonly attribute string     name;    

                        readonly attribute CashAmount balance; 

 

                        void deposit  (in CashAmount amount);        

                        void withdraw (in CashAmount amount);          

            };

};

 

#endif

 

Client Console Application:

Start menu has two option, Create an Account or Find for a Account


 



 

Acknowledgements:

Part I:

Iona Orbix Product Documentaton.

Iona Knowledgebases on the Website.

Orb Specification document by OMG group.

IDL specification document by OMG group.

 

Part II:

Enterprise Java Computing-Applications and Architecture - Gopalan Suresh Raj (Co-Author)

The Awesome Power of JavaBeans - Gopalan Suresh Raj (Co-Author)

Package org.omg.CORBA which provides the mapping of the OMG CORBA APIs to the Java programming language

 

Part III:

Sun's documentaton on CORBA on java.sun.com.

Java 2.0 API documentation.

Java IDL documentation on java.sun.com.

 

Part IV:

Iona Orbix 3.01 product documentation.

Iona Orbix 3.01 BankSimple example.