プログラム例 2: 持続性を備えた Hello World


Java IDL は、一時オブジェクトだけをサポートしています。したがって、オブジェクトのサーバプロセスが停止するか再起動されると、オブジェクト参照は無効になります。このプログラム例 2 では、一時オブジェクトの状態を保存し、サーバが再起動されるたびにその状態から一時オブジェクトを初期化し直す方法を説明します。

プログラム例 2 のサーバは、文字列をファイルに保存する Hello オブジェクトを提供します。文字列は、コマンド行引数としてクライアントプログラムに渡します。サーバの Hello オブジェクトはこの文字列を「記憶」し、クライアントが次に実行されたとき、サーバが停止または再起動していても、この文字列をクライアントに返します。

プログラム例 2 は、持続性を持たせるための拡張が行われていることを除いて、プログラム例 1 と同じです。このページでは、拡張部分のコードについてだけ説明します。

このページでは、次の内容について説明します。

このプログラム例のコンパイル方法と実行方法については、「Hello World の構築方法と実行方法」を参照してください。

インタフェース定義 (Hello.idl)

module HelloApp
{

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

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

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

  • Hello オブジェクトではファイルを読み書きするため、Java 言語の例外をスローする必要があります (次の「サーバの実装」を参照)。Hello インタフェースでは、適切なスケルトン定義が生成されるように、例外を定義し発生させる必要があります。

  • sayHello メソッドは、文字列引数をとるように変更されています。この文字列は、実行時にファイルに保存されます。また、ファイルに保存した文字列をクライアントに返すため、lastMessage メソッドが追加されています。

  • IDL コンパイラは、次の例外クラスファイルが含まれる HelloApp/HelloPackage ディレクトリを生成します。
    これらのクラスの使い方については、次の「サーバの実装」を参照してください。

    サーバの実装 (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);
    	}
        }
    }
     
  • sayHello メソッドと lastMessage メソッドでは、IDL ファイルで定義されている例外をスローしています。これらのメソッドでは、ファイル入出力例外をスローしなければなりません。ファイル入出力例外をスローしない場合、Java 言語コンパイラは警告とエラーを発します。

  • 実行時、HelloServant オブジェクトは非同期にメソッド要求を受け取り、場合によっては同時に複数のメソッド要求を受け取ることがあります。このため、ファイル入出力コード全体を synchronized 節で囲むようにします。

  • HelloServer.main は何も変更する必要はありません。

    クライアントの実装 (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);
    	}
        }
    }
    
     
  • このクライアントは、保存されたメッセージを lastMessage により取り出し、新しいメッセージを sayHello への引数を使って保存します。

    Hello World の構築方法と実行方法

    以下の説明では、Java IDL ネームサーバ用にポート 1050 を使用できることを前提としています。必要であれば、別のポートに変更してください。なお、1024 以下のポートを使用する場合は、UNIX マシンであればスーパーユーザの権限が、Windows95 および NT であれば管理者の権限が必要です。また、以下の説明ではパス名でスラッシュ (/) を使用していますが、Windows95 および NT ではバックスラッシュ (\) に置き換える必要があります。


    ホーム

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