This section explains the structure of the remainder of this guide, which together with the Orbix Reference Guide covers all of the features of Orbix. This guide is structured in parts: the first, Part I, Getting Started, precedes this part; the remaining parts are outlined in the following subsections.
Chapter 2, "The Interface Definition Language" describes the syntax and semantics of the Interface Definition Language (IDL), which is used to define the interfaces of Orbix objects. This language is a simple subset of the C++ syntax for declaring classes, and is therefore easy to learn.
Chapter 3, "Summary of IDL to C++ Mapping" explains the mapping between IDL and C++: that is, it explains the rules that Orbix uses when automatically building C++ classes from IDL specifications. An overview of the mapping is given in this chapter, and full details can be found in Chapter 1, "IDL to C++ Mapping" in the Orbix Reference Guide.
We proceed in Chapter 4, "Programming Orbix using C++", to consider a worked example of programming a simple distributed application, using IDL and C++. This chapter briefly explains how to register a server so that a process will automatically be launched when an invocation is made on one of the objects that it manages.
Chapter 5, "Naming and Binding" covers in detail the topics of object naming and binding.
Chapter 6, "Registration and Activation of Servers" details the registration of servers and their activation when their objects are used.
Chapter 7, "Exception Handling" explains the importance of exception handling, and shows how the example presented in Chapter 4 can be extended to raise and handle exceptions.
Chapter 8, "Inheritance" shows how that example can be further extended to use inheritance of IDL interfaces.
Chapter 9, "Configuring Orbix through its API" shows how a programmer can configure aspects of Orbix through its application programming interface.
Chapter 10, "Details++" presents more details of Orbix, and extends this with coverage of issues such as security and collocated systems (that is, clients and servers within a single address space). When a client and server object are in the same address space, Orbix optimizes out intermediary layers so that operation calls can be made as efficiently as normal function invocations in C++.
The programming of distributed applications is greatly simplified by the generation of proxy classes that allow clients to use normal C++ function invocation syntax. This approach naturally means that the set of interfaces that a client can use is fixed at compile time. Although this causes no difficulties for most applications, some applications (such as browsers) need to interact with interfaces which might not even have been defined when they were compiled. To cater for such applications, Orbix supports a dynamic invocation interface (DII), which allows an application to issue requests for any interface that exists when it is running. The DII can be used to construct a request for any operation of any interface at runtime and to invoke that request on any object implementing this interface. The basic DII is specified by CORBA, and Orbix extends this with a C++ stream-like interface which makes it significantly easier to use. Part III, Advanced CORBA Programming, of this guide shows how to use the DII and other dynamic aspects of Orbix.
Chapter 11, "TypeCode" describes the built-in IDL type TypeCode, which is used to describe basic IDL types and types defined in IDL. Values of this type can be used with the DII and other dynamic aspects of Orbix.
Chapter 12, "Type any" describes the built-in IDL type any. If an IDL operation has a parameter or return value of this type, the programmer must pass/return an object of type any, but that any can, in fact, be constructed to hold any type of datathat is, a value of any basic or user-defined IDL type. Each any holds a TypeCode that describes the type of the data value that it currently holds. The any and TypeCode types can be used by any Orbix programmer, but they are of particular importance when using the DII and the Interface Repository.
Chapter 13, "Dynamic Invocation Interface" shows how to use the DII itself. The standard CORBA mechanism is described, as well as the Orbix extensions that make it easier to use.
Chapter 14, "Dynamic Skeleton Interface" describes the server side equivalent to the DII, allowing a server to receive an operation or attribute invocation on any object, even one with an IDL interface unknown at compile time.
Chapter 15, "Interface Repository" explains how to use the Interface Repository, which can be used at runtime to find the definition of any IDL interface or type. Given a reference to an object, the object's interface and all information about that interface can be determined at runtime by calling functions defined by the Interface Repository. Such facilities can be important for tools, such as browsers; as well as for parts of applications which need to perform dynamic type checking. One use of the Interface Repository is to determine the interface to an object, and the details of its operations, before using the DII to make a call to one of these operations.
Chapter 16, "ORB Interoperability" describes how to use the standard Internet Inter-ORB Protocol (IIOP) which allows invocations between a client and a server object independently of the ORB on which the client and server have been developed.
Orbix extends the CORBA specification by making some of the standard features easier to use, and it also adds some advanced, but easy to use, features which allow programmers to extend the system. When it is clear that there a number of valid approaches to performing some action, such as storing objects to disk or locating servers in the distributed system, Orbix allows system programmers to replace some of the standard components of Orbix with components to be used by their project or system. These mechanisms for extending the system are explained in Part IV, Advanced Orbix Programming, and they are briefly introduced in this subsection.
Orbix allows a programmer to specify that additional code is to be executed before or after the normal code of an operation. This code might perform security checks, provide debugging traps or information, maintain an audit trail, launch a thread to handle an operation call, and so on. Orbix supports two forms of filtering: per-process and per-object filtering.
Per-process filters monitor all incoming and outgoing operation requests to and from an address space. Each process can have a chain of filters, with each element of a chain performing a different task. The following monitoring points are supported: before a request is sent out by a client, when a request arrives at a server, when a reply is sent, when a reply arrives back at the caller and when a preceding monitoring point or operation invocation fails.
A per-process filter can be used to create a lightweight thread when an invocation arrives at a server, and the implementation of this can be customised to suit the threads mechanism of the underlying environment, see Chapter 21, "Orbix-MT: Multi-Thread Orbix" for details. A server will have a single thread to handle requests if it has no filter that creates additional threads. The simplest view of this is that the server will handle one request at a time; although, if a server makes a remote call while handling a request, then that server will see another request if one arrives before the remote call returns.
A second form of filtering, per-object filtering, is supported to allow filters to be associated with either the pre or post monitoring point of a particular object, rather than all objects in the address space as in per-process filtering.1
Chapter 17, "Filters" describes both forms of filtering.
Although, for each IDL interface, Orbix automatically generates the C++ class from which proxies for that interface are generated, it is sometimes beneficial for an application to define a derived class and instruct Orbix to generate proxies from the derived class. Such proxies are called smart proxies (and their classes are called smart proxy classes). Smart proxies may, for example, cache values locally to reduce the number of remote accesses; or they may access objects or resources local to the client object. Apart from an increase in performance, client programmers should not be aware of the differences between smart and default proxies.
Smart proxy support is just one of advanced mechanisms which make Orbix an open system, allowing programmers to override the default behaviour of the system. Chapter 18, "Smart Proxies" explains how to program smart proxies.
In each client and server, Orbix keeps track of what objects and proxies are currently created in its process. If a request is made for an unknown object, then normally an exception is returned back to the client. However, a programmer can choose to intervene and be advised of the failure to find the object. The programmer might choose to handle such "object faults" by re-constructing the required object from a persistent storesuch as a flat file, an RDBMS, or an OODBMS. Orbix can then be asked to continue the invocation transparently to the client. Loaders can be written and installed in both servers and clients.
Chapter 19, "Loaders" explains how to write loaders.
A client program must first obtain an object reference for an object before it can call its operations. The Orbix _bind() function, defined on each IDL C++ class, is one of the mechanisms supported for obtaining object references. It takes information that identifies an Orbix object as parameters, and it returns an object reference. Subsequent function invocations on this object reference will be automatically passed to the target object.
The _bind() call can be given the target object's host name, its server name, and its name within its server (the last of these is known as its marker, see Chapter 5, "Naming and Binding"). Clients can also call _bind() using a subset of that information. In particular the host name is often omitted so that code can be written without knowing at which host in the distributed system a particular server resides. In this case, Orbix uses a location service to find a suitable host; a server with a given name can be supported on any number of hosts in the distributed system. Orbix provides a default location service that uses configuration files to locate servers. This default location service can be overridden if required.
The _bind() function can also be called by specifying only the server name (that is, not specifying the object's name within the server), in which case Orbix will choose, within the specified server, any object that implements the required interface.
Chapter 20, "Locators" describes how to explicitly call the locator and how to write a new locator.
By default, each process has a single thread, which handles incoming requests; that is, Orbix ensures that only one request is active at any time in a process. With Multi-Thread Orbix,2 concurrency can be increased by creating threads to handle incoming operation calls as explained in Chapter 21, "Orbix-MT: Multi-Thread Orbix".
Part V describes some features of Orbix that are currently regarded as experimental but are likely to be fully supported in a later release. However, some details may change when these features are fully supported.
In the CORBA model, references to objects rather than the objects themselves are passed as parameters and return values. Normally, this is what is required; however, some applications may require objects to be passed `by value' rather than `by reference'. Orbix allows objects to be passed by value by providing a type constructor "opaque" which defines a type about which nothing is known at the IDL level except that it is a valid IDL type. It is then the responsibility of the programmer to implement marshalling and unmarshalling operations that define how the object's state is sent from and received into a process over the network.
Chapter 22, "Opaque Types" describes the opaque mechanism and how to use it.
Orbix allows a programmer to modify the data buffer sent in an Orbix operation invocation or operation reply directly preceding its transmission from a process and directly subsequent to its reception by a process. A transformer object may be implemented by the programmer to specify what modifications to the buffer should occur when requests or replies are transmitted to other processes. The ability to modify this data directly preceding its transmission, or directly subsequent to its reception means that additional information (such as information identifying the participants in the communication) may be added to the data stream; the data stream may be encrypted for security purposes and so on.
The functionality provided buffer transformation is at a lower level than that provided by filters since it allows access to the actual data buffer transmitted.