Next: 3.4 Writing the ``Hello Up: 3. Getting Started with Previous: 3.2 Generating the Stub

# 3.3 Writing the ``Hello World'' Client

Now lets take a look at the code for the "Hello World" client as found in the file ```Fnorb/examples/hello-world/client.py`''. In typical Python fashion, we start by importing the modules and packages required by the application. All Fnorb programs, both clients and servers, must import the CORBA module from the package `Fnorb.orb`. The client must also import the stub code for any CORBA interfaces that it wants to use. Stub code is generated by Fnorb's IDL compiler `fnidl` (see Section ), and in this example, the code we require is found in the package `HelloWorld`. For the full description of the mapping from OMG IDL to Python see Chapter .

    #!/usr/bin/env python

    """ Client for the "Hello World" example. """

    # Standard/built-in modules.
    import sys

    # Fnorb modules.
    from Fnorb.orb import CORBA

    # Stubs generated by `fnidl'.
    import HelloWorld

The first thing that all Fnorb programs must do is initialise the ORB. This is achieved by calling the method `ORB_init()` found in the `CORBA` module. `ORB_init()` takes two parameters. The first is a list of command line options that can be used to configure the ORB (see Section for more details), and the second is the vendor specific identity of the ORB, which in Fnorb must always be the value of the variable `CORBA.ORB_ID`. The `ORB_init()` method can be called as many times as you like and always returns a reference to the previously initialised ORB (although you should be aware that command line arguments are only processed on the first call). For convenience, `ORB_init()` can also be called with no parameters at all.

    def main(argv):
        """ Do it! """

        print 'Initialising the ORB...'

        # Initialise the ORB.
        orb = CORBA.ORB_init(argv, CORBA.ORB_ID)

Having initialised the ORB, the client must now locate the server object. In this case when the server starts up it will write a `stringified' version of its object reference to the file ```server.ref`''. Obviously, this is not an ideal solution as it requires that the client and server share the same file system, but it will do for now! In practice the client would locate the server using more a flexible mechanism such as the CORBA naming and/or trading services.

        # Read the server's stringified IOR from a file (this is just a
        # 'cheap and cheerful' way of locating the server - in practise
        # the client would use the naming or trader services).
        stringified_ior = open('server.ref', 'r').read()

Unfortunately, the `stringified' version of the object reference is not much use other than for passing around to your friends, and writing to databases etc, and so the client's next call is to the ORB method `string_to_object()`. The `string_to_object()` method creates a `proxy' object that has the same methods as the server object itself. When methods are invoked on the proxy, it forwards the request onto the server object in whatever process, on whatever machine it happens to be running at the time! In this way the client is insulated from the details of where the server object is physically located, and how operation requests are delivered to it.

        # Convert the stringified IOR into an active object reference.
        server = orb.string_to_object(stringified_ior)

Just because `string_to_object` succeeds, it doesn't mean that we can use the server straight away. First of all, the reference could be a `nil object reference'. Nil object references are how CORBA represents references to nothing at all a pointer into space (cf. `NULL` pointer references in languages such as C and C++). In Fnorb, nil object references are represented as the Python value `None`, and so the first check we have to make is as follows:

        # Make sure that the server is not a 'nil object reference'
        # (represented in Python by the value 'None').
        if server is None:
            raise 'Nil object reference!'

Although, we now know that the object reference is not `nil`, it still doesn't mean that the server is actually up and running. The only way to make sure that this is the case is to attempt to invoke an operation on it (via the proxy object). A good choice is the `_is_a()` operation which is available on every CORBA object. The `_is_a()` method takes a CORBA interface repository identifier and asks the object if it implements an interface of that type. If the call succeeds then the client can be sure that a) the server object is alive and kicking, and b) the server object really does implement the expected interface. For a detailed description of interface repository identifiers see the CORBA 2.0 specification [1].

        # Make sure that the object implements the expected interface.
        if not server._is_a('IDL:dstc.edu.au/HelloWorld/HelloWorldIF:1.0'):
            raise 'This is not a "HelloWorldIF" server!'

Now that the client is sure that the server is what it says it is (i.e. an implementation of our `HelloWorldIF` interface) it can make that all-important `hello_world()` call just as it would on a local Python instance!

        # Call the server!
        print server.hello_world()

        return 0

    if __name__ == '__main__':
        # Do it!
        sys.exit(main(sys.argv))

Next: 3.4 Writing the ``Hello Up: 3. Getting Started with Previous: 3.2 Generating the Stub