Example 2: Hello World with Persistent State


Java IDL only supports transient objects - if an object's server process halts and restarts, the object reference becomes invalid. However, Example 2 illustrates how a transient object can store its state and re-initialize itself from this state each time the server is restarted.

The Example 2 server hosts a Hello object that stores a string in a file. You provide the string as a command line argument to the client program. The server Hello object "remembers" the string and returns it to the client the next time that the client is run, even if the server has been stopped and restarted.

Example 2 is identical to Example 1 except for the persistence enhancements. This page only discusses the code neccessary to these enhancements.

This page contains:

Instructions for compiling and running the example are provided.

Interface Definition (Hello.idl)

module HelloApp
{

    interface Hello
    {
        exception cantWriteFile{};
        exception cantReadFile{};

        string sayHello(in string message)
                raises (cantWriteFile);

        string lastMessage()
                raises (cantReadFile);
    };
};

  • Because the Hello object reads from and writes to a file, you will need to throw Java language exceptions. (See Implementing the Server below). The Hello interface must define and raise exceptions in order to generate the appropriate skeleton definitions.

  • The sayHello method has been modified to take a string argument, which will be stored in a file at runtime. A lastMessage method has been added to return this stored string to the client.

  • The IDL compiler generates a directory HelloApp/ HelloPackage that contains the following exception class files:
    Use of these classes is illustrated in the implementation below.

    Implementing the Server (HelloServer.java)

    // Copyright and License 
    
    import HelloApp.*;
    import org.omg.CosNaming.*;
    import org.omg.CosNaming.NamingContextPackage.*;
    import org.omg.CORBA.*;
     
    class HelloServant extends _HelloImplBase
    {
        public String sayHello(String msg)
            throws HelloApp.HelloPackage.cantWriteFile
        {
            try {
                    synchronized(this) {
                       File helloFile = new File("helloStorage.txt");
                       FileOutputStream fos = new FileOutputStream(helloFile);
                       byte[] buf = new byte[msg.length()];
                       msg.getBytes(0, msg.length(), buf, 0);
                       fos.write(buf);
                       fos.close();
                    }
            } catch(Exception e) {
                    throw new HelloApp.HelloPackage.cantWriteFile();
            }
            return "\nHello world !!\n";
        }
           
        public String lastMessage()
            throws HelloApp.HelloPackage.cantReadFile
        {
            try {
                    synchronized(this) {
                       File helloFile = new File("helloStorage.txt");
                       FileInputStream fis = new FileInputStream(helloFile);
                       byte[] buf = new byte[1000];
                       int n = fis.read(buf);
                       String lastmsg = new String(buf);
                       fis.close();
                       return lastmsg;
                    }
            } catch(Exception e) {
                    throw new HelloApp.HelloPackage.cantReadFile();
            }
        }
    }
    
     
    public class HelloServer {
     
        public static void main(String args[])
        {
    	try{
    	    // create and initialize the ORB
    	    ORB orb = ORB.init(args, null);
     
    	    // create servant and register it with the ORB
    	    HelloServant helloRef = new HelloServant();
    	    orb.connect(helloRef);
     
    	    // get the root naming context
    	    org.omg.CORBA.Object objRef = 
    		orb.resolve_initial_references("NameService");
    	    NamingContext ncRef = NamingContextHelper.narrow(objRef);
     
    	    // bind the Object Reference in Naming
    	    NameComponent nc = new NameComponent("Hello", "");
    	    NameComponent path[] = {nc};
    	    ncRef.rebind(path, helloRef);
     
    	    // wait for invocations from clients
                java.lang.Object sync = new java.lang.Object();
                synchronized (sync) {
                    sync.wait();
                }
     
    	} catch (Exception e) {
    	    System.err.println("ERROR: " + e);
    	    e.printStackTrace(System.out);
    	}
        }
    }
     
  • The sayHello and lastMessage method implementations throw the exceptions defined in the IDL file. These methods must throw file IO exceptions or the Java language compiler issues warnings and errors.

  • The HelloServant object receives ansychronous and possibly simultaneous method requests at runtime. Therefore, you should enclose all file IO code in a synchronized clause.

  • No changes are required to HelloServer.main.

    Implementing the Client (HelloClient.java)

    // Copyright and License 
     
    import HelloApp.*;
    import org.omg.CosNaming.*;
    import org.omg.CORBA.*;
     
    public class HelloClient 
    {
        public static void main(String args[])
        {
    	try{
    	    // create and initialize the ORB
    	    ORB orb = ORB.init(args, null);
     
                // get the root naming context
                org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
                NamingContext ncRef = NamingContextHelper.narrow(objRef);
    
                // resolve the Object Reference in Naming
                NameComponent nc = new NameComponent("Hello", "");
                NameComponent path[] = {nc};
                Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));
     
    	    // call the Hello server object and print results
    	
    	    String oldhello = helloRef.lastMessage();
                System.out.println(oldhello);
                String hello = helloRef.sayHello(args[0]);
                System.out.println(hello);
     
    	} catch (Exception e) {
    	    System.out.println("ERROR : " + e) ;
    	    e.printStackTrace(System.out);
    	}
        }
    }
    
     
  • This client retrieves the stored message via lastMessage and stores the new message via an argument to sayHello.

    Building and Running Hello World

    The following instructions assume you can use port 1050 for the Java IDL name server. Substitute a different port if necessary. Note that for ports below 1024, you need root access on UNIX machines, and administrator privileges on Windows95 and NT. Note also that the instructions use a slash (/) for path names. Windows95 and NT users should subtitute a backslash (\).


    Home

    Copyright © 1995-98 Sun Microsystems, Inc. All Rights Reserved.