# 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:

- The IDL for the persistent "Hello World" program
- A transient server that creates an object, registers it in a naming context, and saves its state in a file.
- An application client.

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:

`cantReadFile.java`
`cantReadFileHelper.java`
`cantReadFileHolder.java`
`cantWriteFile.java`
`cantWriteFileHelper.java`
`cantWriteFileHolder.java`

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 (\).

- Create source files as shown above.
- Run `idlj` on the IDL file to create stubs and skeletons:

      	idltojava -fall Hello.idl

- Compile the `.java` files, including the stubs and skeletons:

      	javac *.java HelloApp/*.java

- Make sure the name server is running:

      	tnameserv -ORBInitialPort 1050&

- Start the Hello server:

      	java HelloServer -ORBInitialPort 1050

- Run the Hello application client from a different shell than the server:

      	java HelloClient "remember this message" -ORBInitialPort 1050

Home

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