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: 3.5 Running the ``Hello Up: 3. Getting Started with Previous: 3.3 Writing the ``Hello