Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Mobile

Examining CORBA Interoperability


Jun01: Programmer's Toolchest

Finding out about ORB interoperability and code portability

Eric is a graduate student at the University of Alabama in Huntsville; Letha is an assistant professor in the computer science department; and David is a member of the U.S. Army PM-TMDE. They can be contacted at [email protected], letzkorn@ cs.uah.edu, and [email protected], respectively.


The current drive in computing is to develop client/server programs that are portable and that can communicate across platforms and programming languages. The Object Management Group's approach to this problem is its Common Object Request Broker Architecture (CORBA). CORBA's purpose is to stand between diverse applications and handle all low-level communications, eliminating platform and language barriers. In addition to alleviating the communication and migration barriers, CORBA provides services and facilities that add enhanced functionality to client/server computing.

The underlying principal in CORBA is the CORBA Object Request Broker (ORB) and the CORBA Interface Definition Language (IDL). The ORB handles all communications between the object (client or server) and other applications, regardless of the application's location, native operating system, or programming language. Since all CORBA-compatible ORBs must meet OMG CORBA specifications, interactions between ORBs should be transparent to users.

The CORBA IDL makes this transparency possible. Application designers use IDL to make public the services and capabilities of their application. ORBs then use these interfaces to pass communication from one application to another. Once an application has an ORB and an interface, it can supposedly interact with any other application capable of using the same interface and an ORB. Without CORBA, each object requires a communication interface for each object it will communicate with (point-to-point interface). In most cases, these interfaces need to be built from scratch. Figure 1 is a typical CORBA system architecture.

Our Study

In this article, we present conclusions from a study of ORB interoperability and code portability we performed for the U.S. Army. The purpose of the study was twofold:

  • To determine the feasibility of CORBA as an interoperable standard for both new and legacy code within mobile and/or embedded computing environments.
  • Create a working demonstration of the mobile/embedded environment using CORBA.

The chosen CORBA Standards version for this study was CORBA 2.2 and CORBA 2.3, as mandated by an Army architecture committee (Joint Technical Architecture-Army [JTA-A], Version 6.0, http://arch-odisc4.army.mil/aes/aea/jta-a/jtaa60/html/jtaa60.htm, May 8, 2000). Also, because there was a major change to the CORBA Standards between CORBA 2.1 and 2.2, we did not target the CORBA 2.1 Standard. Table 1 lists the specific goals for the study, Table 2 the testing software we used, and Table 3 the testing structure.

Basic CORBA Structure of Clients/Servers

Our first task was to perform a single interoperability and code mobility study (Goals 1-3 in Table 1). The starting point was a simple interface that provided evidence that a connection had been made. Thus, we decided upon an echo function that receives a string from a client and returns the string. Listing One is the echo interface IDL. A second interface was based on the passing of a sequence-type data item to test the passage of user-defined structures. We developed tests using the basic echo interface and modified them to use the sequence echo interface; see Listing Two. Tests were also developed with and without exception handling because of the specific error handling abilities of each ORB. For example, the TAO ORB (http://www.cs.wustl.edu/~schmidt/TAO .html) easily handles standard Windows NT exceptions. On Linux (specifically, Red Hat Linux 6.1), however, the TAO ORB requires specific coding and recompilation of the ORB to handle native exceptions. For this study, we decided to use exceptions when special exception handling was not required (for example, TAO on Windows NT) and omit them when special handling was required (TAO on Linux).

The server object was designed to connect to and register itself via a static server name with a Naming Service using either the default name server address or an interoperable object reference (IOR). In the case of the TAO servers, the naming service was located using a proprietary network multicast provided with TAO. Though this function is not supported by the CORBA specifications, we found it convenient for speeding up development. Minimally, CORBA-compliant servers would need to use either the default address or IOR methods. Servers were explicitly created (activated by our code, then bound to the ORB) and operated until terminated by users. The echo function on the server was constructed to print the input string to the screen and return the input string to the client unchanged.

Client objects were designed to connect to the naming service using a default address or IOR reference. Once the client object was connected to the naming service, it used the static server name to locate and bind to the server. Once the server was bound to the client, the echo function was called and the return parameter printed to the screen. Table 3 lists the tests we ran between various ORBs and programming languages.

Our second task (Goal 4 of Table 1) was to expand the simple interoperability study to a more complicated framework. This new framework would support the specific needs of the Army and is a peer-to-peer application structure (Figure 2). In the peer-to-peer structure, the simple client was modified to instantiate a subservant within itself. Once the peer-to-peer client is bound to the server, the client creates the subservant and passes a stringified reference of the subservant to the server. For the peer-to-peer server, the standard server was modified to include a linked list of subclients. Thus, when the peer-to-peer client binds to the server, the server receives the client's subservant stringified reference, creates a subclient, places the subclient into a linked list structure, and uses the stringified reference parameter to bind the new subclient to the client's subservant. After the peer-to-peer structure is set up, communications between the server and client can be initiated from either side (within the constraints of the interfaces used). Because there are two sets of server/client pairs (server client and subserver subclient), different interfaces could be used for each pairing. This lets users independently set how much control the client has over the server and how much control the server has over the client.

Delphi Client/Server Testing

Because Linux versions of Borland's Delphi did not exist at the time of this study, we tested Delphi exclusively on Windows NT. The latest version of Delphi supported the Borland Visibroker 3.4 ORB (CORBA 2.1 compatible) instead of the Visibroker 4.0 ORB (CORBA 2.3 compatible); however, we tested this CORBA variation because our customer uses Delphi heavily. Using the built-in wizards, we quickly had a working demonstration of a Delphi Client/Server using the OS Agent (a proprietary naming service of Visibroker). However, complications arose when we tried to make the Delphi objects operate with a Java/Visibroker 4.0 partner. Delphi's wizards are great for getting things going quickly, but they hide most of the direct CORBA calls. Several standard CORBA calls are apparently not even implemented in Delphi. This prevented us from making changes to the CORBA connections that were required to make the older Visibroker 3.4 ORB easily communicate with the newer Visibroker 4.0 ORB. Delphi's use of the older CORBA 2.1 Standard and the lack of direct CORBA access resulted in an inability to communicate with objects using the newer 2.2 Standard.

An unexpected result of the Delphi interoperability problem was the identification of the apparent lack of compatibility between the CORBA 2.1-compliant (Visibroker 3.4) and CORBA 2.2-compliant (Visibroker 4.0) ORBs. The change between CORBA 2.1 and CORBA 2.2 was a fairly major redefinition of CORBA. The Basic Object Adapter (BOA) used in previous versions of CORBA was completely dropped in favor of a Portable Object Adapter (POA). OMG did this to avoid the limitations of the BOA and the resulting proprietary implementations by various ORBs. Many of the ORBs evaluated, including Visibroker, still contain the BOA, but interactions between the BOA and POA are difficult at best. In this specific case, Visibroker changed the libraries that access the BOA. Thus, code written under the 2.1 Standard may not compile or run without modification under the 2.2 Standard.

Java Client/Server Testing

Next, we tested the interoperability of Java Visibroker with the C++ TAO ORB. The starting point for the Java investigations was Java applications instead of applets. Because of the application's standalone nature and fewer security restrictions, we believed it would be easier to get applications running. Once we had an operational client and server (see Listings Three and Four, respectively) using both the Visibroker ORB/OS Agent Naming Service and IOR strings, we replaced the Visibroker OS Agent with the TAO Naming Service. The simple client/server case worked well. When we moved to the peer-to-peer structured client/servers, we also achieved satisfactory results. However, when the peer-to-peer Java client was converted to an applet, problems developed.

One of the fundamental advantages of Java, applet isolation, also appears to be its major drawback in the case of peer-to-peer CORBA client/server communication. Because of the security restrictions that Java imposes on its programs, the establishment of a server within an applet can be difficult, if not impossible. This is because the establishment of a true server would give the remote object direct access to the local computer. Obviously, this is counter to the goals of Java developers. The use of signed applets presumably solves this problem, but because of time constraints, we did not develop signed applets. We were unable to establish peer-to-peer communications using a standard browser and applet without the use of signed applets, although our applet worked well under JDK Appletviewer.

Another problem with the use of an applet was the amount of time required to download the applet. Internet Explorer does not contain a built-in CORBA ORB and Netscape's built-in Visibroker ORB was not 2.3 compatible at the time of testing. Netscape provided a way to install a user-defined ORB (replace the iiop10.jar file with your ORBs *.jar file), but this would require each browser implementation to be modified upon application deployment. An alternate, and easier, method is to download a copy of the ORB with the applet to the remote computer. For this study, the applet was required to download the ORB to the remote computer to work. For the Visibroker ORB used with our applet, this required downloading a file that was approximately 5 MB in size. A file this size poses a problem for systems with slow communication speeds.

C++ Client/Server Testing

For C++ code, we decided to work with two independent ORBs. The TAO ORB and the MICO ORB (http://www.mico .org/; also see "The MICO CORBA Compliant System," by Arno Puder, DDJ, November 1998) are both freely available. Once the code was downloaded, we proceeded to wrestle with the installation and compilation of each ORB. When the precompiled versions can be used, everything works well. However, when the ORBs must be recompiled, the process is complex and time consuming. We had particular trouble compiling these ORBs for Linux. However, both ORBs have helpful user groups. Once the ORBs were compiled, we were quickly running our simple client/server demonstrations on Windows NT. Listings Five and Six are the NT C++ TAO client and server code, respectively. Listing Seven is the C++ MICO server code, while Listings Eight and Nine are the C++ TAO sequence client and server code, respectively. TAO and MICO seemed quite compatible for this simple interaction.

During the testing of the TAO ORB we found a bug in relation to the ORB destroy call. This problem has been recognized by others and is further discussed on the TAO mailing list. This fault affected the termination of the ORB and had no effect on our implementation of the TAO ORB, since our programs ran until terminated by users.

When the C++ TAO code was moved from Windows NT to Linux, we discovered that exception handling was not directly portable because the compiler used to compile TAO on Linux does not support native exception handling easily nor efficiently. To deal with this problem, TAO developers presented us with three options. The first is to call specialized macros created by the TAO developers within each function that throws an exception. For most applications this would require quite a bit of work. The second option was to recompile the TAO ORB without exception handling support and remove all exception handling from our code. Since most run-time applications depend on exceptions for fault tolerance and reliability, this is not a viable option. However, we were not required to develop a fault-tolerant demonstration, so we removed the exception-handling routines. This required minor changes to our code and IDL interface to move the clients/servers to Linux from Windows NT. The only other option would be to recompile the ORB to use native exceptions. According to the TAO mailing list, this results in a reduction of efficiency.

Even though our peer-to-peer client/ server code was compiled without exceptions to run on Linux, the TAO ORB failed to work properly. Unfortunately, the error we encountered did not involve a fault or interrupt — the ORB simply returned from the orb.run(); call immediately without doing anything. After several attempts to correct this problem, we finally contacted the TAO user group, which informed us that this was a problem in the current production version of the TAO ORB. The problem was, however, fixed in the October 2000 Beta release. So, we downloaded the beta version and went through the long TAO compile sequence again. This beta ORB worked fine but led to a naming service connectivity problem.

Because the beta version of the TAO ORB was required to run on Linux, we attempted to use the beta version of the TAO Naming Service. We discovered that the beta version of the TAO Naming Service for Linux was not compatible with the production release of the Windows NT TAO ORB. However, testing was successful when using the production release of the TAO Naming Service (on either Linux or Windows NT). This was not an obvious error — the NT client was able to find the Linux Beta Naming Service, but was unable to resolve the server name using it. It cost us several hours before we determined the problem.

Moving from Windows NT to Linux

We should note two general problems encountered when moving from Windows NT to Linux. The first was the inclusion of carriage-return characters in our code by Windows NT when porting the code to Linux. On the Linux side, these carriage returns were interpreted as invalid characters and caused compilation errors. Thus, for each file that was transferred from Windows NT to Linux, the carriage returns had to be removed prior to compiling. The second problem involved the issue of case sensitivity. Windows NT is not case sensitive to its file and directory names, and Linux is. To make matters worse, transfers between the two operating systems resulted in all uppercase letters being automatically replaced by lowercase letters. When Java classes with uppercase letters were transferred (in either direction) and run, errors resulted from the case sensitivity of Java names.

Code Migration from One Language to Another

In an ideal situation, code that works for one ORB would work for another ORB without modification. Obviously, due to the variation in purpose of the various ORBs and their development by different teams, their operation is not identical. Code transferred from one ORB to another may require a great deal of massaging to get it to work, even though the standard CORBA calls are supposed to be the same. While this may add functionality to an ORB or decrease development costs, it is a major obstacle to code migration between ORBs.

A second problem that appears to be corrected with the new CORBA 3.0 Standard is connecting to a default naming service. Some ORBs in this study had proprietary connection methods to automate server and client connections to a Naming Service, which did not work with Naming Services of other ORBs. For example, TAO uses an IOR multicast on the local area network to find the TAO Naming Service. Once the TAO Naming Service receives an IOR multicast, it responds with a copy of its IOR so that the requesting object can connect. The MICO Naming Service does not respond to the TAO object's multicast, making it impossible to automatically attach a TAO object to a MICO Naming Service using the TAO IOR multicast method.

The CORBA 3.0 Standard allows the definition of default naming services at a general URL rather than a specific IOR address. This allows for naming-service migration and automatic connection via lookup servers. This specification of the naming service appears to be much more functional than the CORBA 2.3 Naming Service specification.

Conclusion

As Table 3 shows, our interoperability study was generally successful. The only major problems encountered involved the use of CORBA peer-to-peer communications in a Java Applet and the use of Delphi Visibroker with anything other than Delphi. Despite these problems, our tests indicate that CORBA could be a useful tool for the embedded mobile computing environment in which a central testing facility administers tests over a network on several test subjects. The ability to define a single interface for each server object and have multiple client objects use this interface is a major advantage over writing proprietary single-use code for every interaction.

However, because of the lack of automation in the CORBA specifications, primarily in initiating contact between clients and servers, setting up a client/server is still too complicated and lacks robustness. The loss of a connection could require complicated reinitialization steps outside the technical abilities of standard users (restart server, restart naming service, find naming service IOR string, and so on).

The basic structure of our test code did not change drastically during this study, but the process of migrating from one operating system to another or from one ORB to another was quite complex. This resulted from the myriad of details each ORB uniquely requires, such as setting correct environment paths, initiating the ORB correctly, starting the Naming Service in a certain way, and accessing the naming service. For each of these details, the CORBA mapping to the language, the implementation by the ORB of the CORBA Standards, and the operating system had to be taken into account. Approximately half of these problems result from the use of varied development platforms, operating systems, and languages, and the remainder resulted from how the ORBs themselves chose to implement the CORBA Standards.

In a conversation, Michael Stahl (Siemens's representative to the OMG) told us that CORBA is currently a moving target. ORBs that interoperate today may or may not interoperate tomorrow based on the version of the Standards used and how they implement those changing Standards. However, it is expected that changes as significant as the change from CORBA 2.1 to 2.2 will not occur in the future as CORBA matures into a fully implementable standard. This appears to be the case for the CORBA 3.0 Standard, which simply adds to the functionality of the CORBA 2.3 Standard. Unfortunately, as of the time of this study, there are no ORBs that completely implement CORBA 3.0.

Despite the favorable findings of this study concerning the interoperability of code, installing the ORBs and ancillary software needed to execute this study took up a substantial amount of our time and effort. While this is not directly related to CORBA, it is a problem with any development or distribution of an application. It is believed that most of these issues could have been overcome with better installation/operating instructions from the various ORB and programming environment producers.

DDJ

Listing One

module echomodule
{
  interface echo
  {
    string echostring(in string message);
  };
};

Back to Article

Listing Two

module echomodule
{
  interface echo
  {
    typedef sequence<float> FloatSeq;
    string echoseq(inout FloatSeq smsg);
  };
};

Back to Article

Listing Three

import org.omg.CORBA.*;

public class Client {
  public static void main(String[] args) {
    // Initialize the ORB.
    org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
    org.omg.CORBA.Object obj = orb.string_to_object(args[0]);
    echomodule.echo echo = echomodule.echoHelper.narrow(obj);
    String mystring = "This is a test";
    System.out.println("The value to be sent is "+mystring);
    String echoed_string = echo.echostring(mystring);
    // Print out the balance.
    System.out.println
      ("The echoed value is " + echoed_string);
  }
}

Back to Article

Listing Four

import org.omg.PortableServer.*;
public class Server {
  public static void main(String[] args) {
    try {
     // Initialize the ORB.
     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
     // get a reference to the root POA
     POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
     // Create policies for our persistent POA
     org.omg.CORBA.Policy[] policies = {
        rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),
        rootPOA.create_request_processing_policy(RequestProcessingPolicyValue.
                                          USE_DEFAULT_SERVANT)
      };
      // Create myPOA with the right policies
      POA myPOA = rootPOA.create_POA( "echo_poa", rootPOA.the_POAManager(),
                                        policies );
      // Create the servant
      echoImpl myServant = new echoImpl();
      myPOA.set_servant(myServant);
      // Decide on the ID for the servant
      byte[] myservantId = "echoModuleecho".getBytes();
      // Activate the servant with the ID on myPOA
      myPOA.activate_object_with_id(myservantId, myServant);
      // Activate the POA manager
      rootPOA.the_POAManager().activate();
      // Create the object
      org.omg.CORBA.Object ref;
      ref = myPOA.create_reference_with_id("echo".getBytes(),
                                           "IDL:echomodule/echo:1.0");
      // Print out the IOR string of this object
      System.out.println(orb.object_to_string(ref));
      // Wait for incoming requests
      orb.run();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Back to Article

Listing Five

// File Client.cpp
#include "EchoC.h"
#include "TAO\orbsvcs\orbsvcs\CosNamingC.h"
#include <iostream>

int main (int argc, char* argv[])
{
  try {
    // First initialize the ORB
    CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "");
    // Convert the IOR to a reference
    CORBA::Object_var naming_context_object = 
                                      orb->string_to_object(argv[1]);
    // Narrow the Naming Service
    CosNaming::NamingContext_var naming_context =
           CosNaming::NamingContext::_narrow (naming_context_object.in ());
    // Build a name
    CosNaming::Name name (1);
    name.length (1);
    name[0].id = CORBA::string_dup ("echo");
    // Find the server
    CORBA::Object_var obj = naming_context->resolve (name);
    // Narrow the server object
    echomodule::echo_var myecho;
    try {
    myecho=echomodule::echo::_narrow(obj);
    } 
    catch (const CORBA::SystemException &se) {
    std::cerr << "Cannot narrow reference" << std::endl;
    throw 0;
    }
    // Call the echo function
    std::cout << "Initial message is " << "Harry Potter" << std::endl;
    CORBA::String_var echostring = myecho->echostring("Harry Potter");
    // Print out the results
    std::cout << "Echoed message is " << echostring.in() << std::endl;       
    // NOTE: There's a bug in the TAO destroy() method orb->destroy ();
  }
  catch (CORBA::Exception &) {
    std::cerr << "CORBA exception raised!" << std::endl;
  }
  return 0;
}

Back to Article

Listing Six

// File Server.cpp
#include "Echo_i.h"
#include "TAO\orbsvcs\orbsvcs\CosNamingC.h"
#include <iostream>

int main (int argc, char* argv[])
{
  try {
   // First initialize the ORB
   CORBA::ORB_var orb =
      CORBA::ORB_init (argc, argv,"");
   CORBA::Object_var poa_object = orb->resolve_initial_references ("RootPOA");
   PortableServer::POA_var poa = 
                              PortableServer::POA::_narrow (poa_object.in ());
   PortableServer::POAManager_var poa_manager = poa->the_POAManager ();
   poa_manager->activate ();
   // Create the servant
    echo_i servant;
   // Activate it to obtain the object reference
    echomodule::echo_var myobject=servant._this();
   // Get the Naming Context reference
   CORBA::Object_var naming_context_object =
      orb->resolve_initial_references ("NameService");
   CosNaming::NamingContext_var naming_context =
      CosNaming::NamingContext::_narrow (naming_context_object.in ());
   // Create and initialize the name.
   CosNaming::Name name (1);
   name.length (1);
   name[0].id = CORBA::string_dup ("echo");
   // Bind the object
   naming_context->bind (name, myobject.in ());
   orb->run ();
   // Destroy the POA, waiting until the destruction terminates
   //poa->destroy (1, 1);
   //orb->destroy ();
 }
 catch (CORBA::Exception &) {
    std::cerr << "CORBA exception raised!" << std::endl;
 }
 return 0;
}
// File Echo_i.cpp
#include "Echo_i.h"
#include <iostream>

echo_i::echo_i ()
{
}
char *
echo_i::echostring(const char * message) throw (CORBA::SystemException)
{
    std::cout << "Message in " << message << std::endl;
    char * smsg = CORBA::string_dup(message);
    std::cout << "Returning " << smsg << std::endl;
    return smsg;
}
// File Echo_i.h:
#ifndef TAO_ECHO_SERVER_I_H

#include "EchoS.h"
#include <string>

class echo_i : public POA_echomodule::echo {
public:
  echo_i ();
  char *echostring (const char * message) 
      throw (echomodule::Invalid_Message);
private:
};
#endif /* TAO_ECHO_SERVER_I_H */

Back to Article

Listing Seven

// File Server.cpp
#include <time.h>
#include <iostream.h>
#include <stdio.h>
#include "server.h"
#include <mico/CosNaming.h>
char *
echo_impl::
echostring(const char *message) throw(CORBA::SystemException)
{
    printf("message is %s\n", message);
    char *smsg= strcat(CORBA::string_dup(message)," Grainger");
    printf("Returning %s\n", smsg);
    return smsg;
}
int
main(int argc, char * argv[])
{
    try 
    {
        // Initialize orb
        CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
        // Get reference to Root POA.
        CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
        PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
        // Activate POA manager
        PortableServer::POAManager_var mgr = poa->the_POAManager();
        mgr->activate();
        // Create an object
        echo_impl time_servant;
        // Write its stringified reference to stdout
        echomodule::echo_var tm = time_servant._this();
        CORBA::String_var str = orb->object_to_string(tm);
        cout << str << endl;
     // Register server with Naming Service (nsd)
     {
          CORBA::Object_var obj;
          obj = orb->resolve_initial_references ("NameService");
          CosNaming::NamingContext_var inc;
          inc = CosNaming::NamingContext::_narrow (obj);
          CosNaming::Name name;
          name.length (1);
          name[0].id = CORBA::string_dup("echo");
          inc->bind (name, tm);
         }
         // Accept requests
         orb->run();
    }
    catch (const CORBA::Exception & e) 
    {
        cerr << "CORBA exception: " << e << endl;
        return 1;
    }
    return 0;
}
// File server.h:
#ifndef server_HH_
#define server_HH_
#include "echo.h"

class echo_impl : public virtual POA_echomodule::echo {
    public:
        virtual char *  echostring(const char * message) 
            throw(CORBA::SystemException);
};
#endif

Back to Article

Listing Eight

// File Client.cpp
#include "EchoC.h"
#include "TAO\orbsvcs\orbsvcs\CosNamingC.h"
#include <iostream>

int main (int argc, char* argv[])
{
  try 
  {
    // First initialize the ORB
    CORBA::ORB_var orb =
        CORBA::ORB_init (argc, argv, "");
    // Get the naming context reference
    CORBA::Object_var naming_context_object = orb->string_to_object(argv[1]);
    CosNaming::NamingContext_var naming_context =
        CosNaming::NamingContext::_narrow (naming_context_object.in ());
    // Create and initialize the name.
    CosNaming::Name name (1);
    name.length (1);
    name[0].id = CORBA::string_dup ("echo sequence");
    // Bind the object
    CORBA::Object_var obj = naming_context->resolve (name);
    // Narrow the object
    echomodule::echo_var myecho;
    try 
    {
        myecho=echomodule::echo::_narrow(obj);
    }
    catch (const CORBA::SystemException &se) {
    std::cerr << "Cannot narrow reference" << std::endl;
    throw 0;
    }
    // Initialize the sequence
    echomodule::echo::FloatSeq seq;
    seq.length(5);
    seq[0] = 0.0;
    seq[1] = (float)0.1;
    seq[2] = (float)0.2;
    seq[3] = (float)0.3;
    seq[4] = (float)0.4;
    std::cout << "seq[0] starts as " << seq[0] << std::endl;
    std::cout << "seq[1] starts as " << seq[1] << std::endl;
    std::cout << "seq[2] starts as " << seq[2] << std::endl;
    std::cout << "seq[3] starts as " << seq[3] << std::endl;
    std::cout << "seq[4] starts as " << seq[4] << std::endl;

    // Test the sequence function
    CORBA::String_var echostring = myecho->echoseq(seq);

    // Output the sequence
    std::cout << "Message is " << echostring.in() << std::endl; 
    std::cout << "seq[0] is now " << seq[0] << std::endl;
    std::cout << "seq[1] is now " << seq[1] << std::endl;
    std::cout << "seq[2] is now " << seq[2] << std::endl;
    std::cout << "seq[3] is now " << seq[3] << std::endl;
    std::cout << "seq[4] is now " << seq[4] << std::endl;

    // NOTE: There's a bug in this code if the ORB is destroyed.
    // orb->destroy ();
  }
  catch (CORBA::Exception &) {
    std::cerr << "CORBA exception raised!" << std::endl;
  }
  return 0;
}

Back to Article

Listing Nine

// File Server.cpp
#include "Echo_i.h"
#include "TAO\orbsvcs\orbsvcs\CosNamingC.h"
#include <iostream>

int main (int argc, char* argv[])
{
  try {
    // First initialize the ORB
    CORBA::ORB_var orb = 
      CORBA::ORB_init (argc, argv,"");
    // Create POA and activate it
    CORBA::Object_var poa_object=orb->resolve_initial_references ("RootPOA");
    PortableServer::POA_var poa = 
                       PortableServer::POA::_narrow (poa_object.in ());
    PortableServer::POAManager_var poa_manager = poa->the_POAManager ();
    poa_manager->activate ();
    // Create the servant
    echo_i servant;
    // Activate it to obtain the object reference
    echomodule::echo_var myobject=servant._this();
    // Get the Naming Context reference
    CORBA::Object_var naming_context_object =
      orb->resolve_initial_references ("NameService");
    CosNaming::NamingContext_var naming_context =
      CosNaming::NamingContext::_narrow (naming_context_object.in ());
    // Create and initialize the name.
    CosNaming::Name name (1);
    name.length (1);
    name[0].id = CORBA::string_dup ("echo sequence");
    // Bind the object
    naming_context->bind (name, myobject.in ());
    orb->run ();
    // Destroy the POA, waiting until the destruction terminates
    poa->destroy (1, 1);
    orb->destroy ();
  }
  catch (CORBA::Exception &) {
    std::cerr << "CORBA exception raised!" << std::endl;
  }
  return 0;
}
// File Echo_i.cpp:
#include "Echo_i.h"
#include <iostream>

echo_i::echo_i (){}
char *
echo_i::echoseq(echomodule::echo::FloatSeq &seq) 
                                    throw (CORBA::SystemException)
{
    CORBA::ULong seqlen = seq.length();
    seq[0] = (float)99.0;
    seq[1] = (float)99.1;
    seq[2] = (float)99.2;
    seq[3] = (float)99.3;
    seq[4] = (float)99.4;

    std::cout << "seq[0] is " << seq[0] << std::endl;
    std::cout << "seq[1] is " << seq[1] << std::endl;
    std::cout << "seq[2] is " << seq[2] << std::endl;
    std::cout << "seq[3] is " << seq[3] << std::endl;
    std::cout << "seq[4] is " << seq[4] << std::endl;

    char * message=CORBA::string_dup("Server Says Hi!");
    return message;
}
// File Echo_i.h:
#ifndef TAO_SEQUENCE_SERVER_ECHO_I_H
#define TAO_SEQUENCE_SERVER_ECHO_I_H

#include "EchoS.h"
#include <string>

class echo_i : public POA_echomodule::echo {
    public:
        echo_i ();
        char * echoseq (echomodule::echo::FloatSeq &seq) 
            throw (echomodule::Invalid_Message);
    private:
};
#endif /* TAO_SEQUENCE_SERVER_ECHO_I_H */


Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.