NonStop Software

Developing Server Applications

Previous Topic | Next Topic | Contents | Index
Getting Started Guide | Administration Guide | Reference Guide

Subtopics

Basic Server main Program Tasks
Producing an Implementation Header File
Producing an Object Implementation
Producing User Exceptions
Producing a Server main Program

Basic Server main Program Tasks

This section covers topics you need to know to produce a server program that hosts an object implementation:

The sample presented here illustrates a server hosting a single transient object. Additional server programming techniques are covered in the Portable Object Adapter topic.

Producing an Implementation Header File

An implementation header file contains a definition for the class or classes to be implemented in a server object. The class contains a constructor and destructor for the object and declarations of the methods to be implemented in the class.

Given the Stock interface definition file stock.idl, the IDL compiler produces an implementation header file. This file is named stock_header.h by default. That file is shown here:
Example 1. The Stock Header File
class POA_Stock
        : public virtual NSDOM_ServantBase,
          public Stock
{
    public:
        POA_Stock() { }

     . . .
	 
        // The following operations need to be implemented by the server.

        virtual void quote(
                    const char* Symbol,
                    CORBA::Double_out Last,
                    CORBA::Double_out High,
                    CORBA::Double_out Low,
                    CORBA::ULong_out Volume, 
                    CORBA::Environment &pr_env) = 0;

        virtual void update(
                    const char* Symbol,
                    CORBA::Double Price,
                    CORBA::ULong Volume, 
                    CORBA::Environment &pr_env) = 0;

        // End of operations to be implemented by the server.

      . . .
}	 

The IDL declarations of the two methods quote( ) and update( ) have generated pure, virtual methods in this class. The implementation header file contains a new class called Stock_impl:
Example 2. C++ Declarations For quote( ) And update( )
#include "stock_server.h"

class Stock_impl: public POA_Stock
{
public: 
  Stock_impl();
  ~Stock_impl(){}

  void quote(const char* Symbol,
	     CORBA::Double_out Last,
	     CORBA::Double_out High,
	     CORBA::Double_out Low,
	     CORBA::ULong_out Volume, 
	     CORBA::Environment &pr_env);

  void update(const char* Symbol,
	      CORBA::Double Price,
	      CORBA::ULong Volume, 
	      CORBA::Environment &pr_env);
};

The implementation header file begins by including the server header produced by the IDL compiler. We are naming the new class Stock_impl but are free to choose any name. The class must inherit from the POA_Stock class generated by the IDL compiler. We add declarations for the constructor and destructor. The methods quote( ) and update( ) are given concrete declarations. These methods will be implemented in the object implementation file.

The implementation header file must have a declaration for each method that appears in the interface definition. The easiest way to insert these definitions is to copy the abstract definitions in POA_Stock, eliminating the virtual and  =0 parts.

You can add other usual C++ constructs, private instance variables, and additional helper methods as needed.

Producing an Object Implementation

The object implementation contains the actual method implementations. The basic structure of the object implementation file that corresponds to the implementation header file is shown here:

Example 3: Method Implementations
#include "stock.h"

Stock_impl::Stock_impl()
{
    // Implementation code for this constructor
}

void Stock_impl::quote(const char* Symbol,
		       CORBA::Double_out Last,
		       CORBA::Double_out High,
		       CORBA::Double_out Low,
		       CORBA::ULong_out Volume, 
		       CORBA::Environment &pr_env)
{
   // Implementation code for this method
}

void Stock_impl::update(const char* Symbol,
			CORBA::Double Price,
			CORBA::ULong Volume, 
			CORBA::Environment &pr_env)
{
   // Implementation code for this method
}

First, we include the implementation header file that contains the implementation class definition. The method signatures are copied from the implementation header file. We add the class name and scope operator in front of the method name. Then add the implementation code to the body of the method.

The implementation code performs whatever logic is necessary. Generally, input parameters are used in this logic, and output values are computed and passed back to the caller via the output parameters and return value. If the method definition (in the IDL file) defined user exceptions for the method, exceptions can be returned via the environment parameter.

Producing User Exceptions

If a method detects an unusual situation, it can raise an exception. The exception condition is communicated back to the requester, which can take the appropriate action. When an exception is raised, the output parameters and return value for the method are undefined.

In the stock.idl, an exception named operationFailed was defined. The quote( ) method was declared to be able to raise this exception. The operationFailed exception declaration causes the IDL compiler to produce an operationFailed class. An exception of this type is thrown by creating an instance of this class and then raising the exception.
Example 4: Raising an Exception
     pr_env.exception(new Stock::operationFailed(NOT_FOUND));

The method signature produced by the IDL compiler includes a CORBA::Environment variable in an environment where there is no native C++ compiler exception support. We use the exception( ) method defined in CORBA::Environment to raise the exception.

Producing a Server main Program

The main program for the server implementation sets up the environment for processing the requests. The first step is to initialize the ORB and obtain an object reference for the root POA:

Example 5: Initilizing the ORB And Obtaining an Object Reference
int main(int argc, char *argv[])
{
    CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);

    CORBAObject = orb->resolve_initial_references("RootPOA");

    PortableServer::POA_ptr rootPOA;
    rootPOA = PortableServer::POA::_narrow(pfobj);

Initializing the ORB is done in the same way as for a client program ORB_init( ). The POA manages the server and invokes methods on the objects hosted by the server. Invoking the resolve_initial_references( ) method provides us with a reference to a root (top level) POA. In the Stock server the root POA suffices. Other server processing requirements may compel one to use additional POA features. See the POA topic for details on additional POA capabilities. The resolve_initial_references( ) method returns a CORBA object. We narrow this to a PortableServer object reference so we can invoke methods on the POA.

An instance of the Stock_impl object is created. This is the object that will be servicing the requests arriving from clients. The POA is told to activate this object. Once activated, the object can service requests. The activate_object( ) method returns an object Id. Because we have no further use for it, we delete it.
Example 6: Object Activation
  Stock_impl *TestServant = new Stock_impl;
 
  PortableServer::ObjectId_ptr oid
    = rootPOA->activate_object(TestServant);
  delete oid;

Now, let clients know about the newly created object by creating a stringified or external form of the object reference. The stringified form is written to a file.

Example 7: Externalizing a Stringified Object Reference
  CORBAObject = rootPOA->servant_to_reference(TestServant);
  char* IORString = orb->object_to_string( CORBAObject );

  FILE *IORFile = fopen( "ior.txt", "w" );
  fwrite( IORString, strlen( IORString ) + 1, 1, IORFile );
  fclose( IORFile );

The final steps are to activate the POA and allow it to begin servicing requests.
Example 8: Activating and Running the POA
  rootPOA->the_POAManager()->activate();
  orb->run();

  return 0;
}

Stock Interface Definition File

Example 9. Contents of stock.idl
interface Stock 
{
    // status for user defined exceptions
    enum operation_status {
        NOT_FOUND       // Stock symbol not found
    };	
 
    // user defined exception
    exception operationFailed {
        operation_status status;        // The type of failure
    };
 
    void quote( in string Symbol, out double Last, out double High, 
                out double Low, out unsigned long Volume )
         raises( operationFailed );
 
    void update( in string Symbol,
                 in double Price, in unsigned long Volume ) 
         raises( operationFailed );
};

Previous Topic | Next Topic | Contents | Top
Getting Started Guide | Administration Guide | Reference Guide
Bibliography | Glossary | Index
© Tandem, a division of Compaq. All rights reserved. Legal notices.