next up previous contents
Next: 3.5 Running the ``Hello Up: 3. Getting Started with Previous: 3.3 Writing the ``Hello

3.4 Writing the ``Hello World'' Server

Writing the server for our example requires a little more work, but only a little! In this section we will discuss the server code as found in the file ``Fnorb/examples/hello-world/server.py''. As mentioned in the previous section all Fnorb programs, both clients and servers, must import the CORBA module from the package Fnorb.orb. Fnorb servers must also import the basic object adapter module BOA. The BOA is an implementation of the basic object adapter interface defined in the CORBA 2.0 specification [1] and it is used to connect interface implementations to the ORB. Unfortunately, the specification was hazy enough to allow every ORB vendor to implement the BOA in their own special way, and to address this problem, the OMG has approved the specification of a well defined and more portable object adapter known (not surprisingly) as the POA. Future releases of Fnorb will contain an implementation of the POA, and that use of the Fnorb BOA may eventually be deprecated. Just as in the client, the server imports the generated stub code from the HelloWorld package. Strictly speaking this is not necessary, iff the server does not use any user defined IDL types. However, in practice, all but the most trivial interfaces will use user-defined types, and it is therefore probably good practice to import stub packages at the outset (in our example the server uses the constant string HelloWorld.Message and so the stub module is required). More importantly, the server must also include skeleton code for every interface that it implements. Just like the stub code in the client, the skeleton code is generated by Fnorb's IDL compiler fnidl, and in this case, is found in the HelloWorld_skel package.

#!/usr/bin/env python
""" Implementation of the HelloWorldIF interface. """

# Standard/built-in modules.
import sys

# Fnorb modules.
from Fnorb.orb import BOA, CORBA

# Stubs and skeletons generated by `fnidl'.
import HelloWorld_skel
Now we come to the Python class that implements the interface we defined in the IDL. The only difference between defining a Fnorb server class as opposed to a standard Python class is that it must inherit from the skeleton generated by the IDL compiler. The skeleton class is found in the skeleton package and has the same name as the IDL interface with the suffix ``_skel''. The server class must contain implementations for all of the operations defined in the IDL, which in this case means that we have to implement the single operation hello_world(). Note that in IDL the operation is defined as taking no parameters, but in its Python implementation we have to explicitly add the current instance parameter traditionally known as self.

class HelloWorldServer(HelloWorld_skel.HelloWorldIF_skel):
    """ Implementation of the 'HelloWorldIF' interface. """

    def hello_world(self):
        print HelloWorld.Message
        return HelloWorld.Message

###########################################################
Now let's look at how we create an instance of the server, and make it available to prospective clients. As in the client, the first thing that a Fnorb server must do is initialise the ORB using the ORBinit() method.

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

    print 'Initialising the ORB...'

    # Initialise the ORB.
    orb = CORBA.ORB_init(argv, CORBA.ORB_ID)
Next comes an additional step only required by Fnorb servers: the initialisation of the BOA that will be used to `connect' interface implementations to the ORB. The BOA initialisation method is (not surprisingly) called BOA_init(), and just like the ORB_init() method it can be called multiple times with the second and subsequent calls simply returning a reference to the initial BOA instance (for more details on using the BOA see Chapter [*]).

    print 'Initialising the BOA...'

    # Initialise the BOA.
    boa = BOA.BOA_init(argv, BOA.BOA_ID)
In the CORBA world, objects are identified by opaque data structures known as object references. To create an object reference for our implementation we use the create() method on the BOA. The create() method takes two arguments, the object key (chosen by the server implementer i.e. you!), and the type of the interface.

    print 'Creating object reference...'

    # Create an object reference ('fred' is the object key).
    obj = boa.create('fred', HelloWorldServer._FNORB_ID)
Next we simply create an instance of our implementation class, as we would any other Python class.

    print 'Creating implementation...'

    # Create an instance of the implementation class.
    impl = HelloWorldServer()
Before the ORB can route any operation requests to our implementation, we have to `connect' it to the object reference that we created previously. Note that even after this step is complete the implementation will not receive any requests until we start Fnorb's event loop.

    print 'Activating the implementation...'

    # Activate the implementation (i.e. connect the generated object
    # reference to the implementation).  Note that the implementation
    # will not receive any operation requests until we start the event
    # loop (see below).
    boa.obj_is_ready(obj, impl)
As mentioned when we created the client, this example uses a file to advertise the server's object reference. Here we use the ORB method string_to_object() to turn the object reference into a `stringified' format and then write it to the file ``server.ref''.

    # Write the stringified object reference to a file (this is just a
    # 'cheap and cheerful' way of making the object reference
    # available to the client!).
    open('server.ref', 'w').write(orb.object_to_string(obj))

    print 'Server created and accepting requests...'
The final step is to start the BOA's event loop. This tells the BOA to listen for operation requests and to pass them on to the appropriate object implementation. Note that the _fnorb_mainloop() method will never return unless an exception is raised, or the method _fnorb_quit() is called from within an operation implementation.

    # Start the event loop.
    boa._fnorb_mainloop()

    return 0

############################

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

############################


next up previous contents
Next: 3.5 Running the ``Hello Up: 3. Getting Started with Previous: 3.3 Writing the ``Hello
http://www.fnorb.com/
March 2000