Java IDL:「Hello World」の例


POA、持続サーバ、および持続ネームサービスの使用


このドキュメントは、インタフェースを定義する IDL (Interface Definiton Language) とスタブおよびスケルトンを生成する Java IDL コンパイラを使い、完全な CORBA (Common Object Request Broker Architecture) アプリケーションを作成する方法について、高レベルの概要を説明したものです。開発プロセスと、IDL を使って CORBA アプリケーションを作成するチュートリアルの詳細は、「Java IDL 入門:「Hello World」のチュートリアル」を参照してください。また、Java プログラミング言語でインタフェースを定義して CORBA アプリケーションを作成することもできます。この開発プロセスの詳細とチュートリアルについては、「Java RMI-IIOP ドキュメント」を参照してください。

一時サーバと持続サーバの比較の詳細については、「サーバの開発」を参照してください。

このドキュメントでは、次の内容について説明します。

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

CORBA アプリケーション作成の第一段階は、OMG のインタフェース定義言語 (IDL) を使って、オブジェクトとインタフェースをすべて記述することです。IDL には C++ に似た構文があり、これを使ってモジュール、インタフェース、データ構造などを定義することができます。IDL はさまざまなプログラミング言語にマッピングできます。IDL を Java にマッピングする方法は「IDL と Java 言語のマッピングの概要」で説明しています。

次のコードは OMG IDL で記述されたもので、CORBA オブジェクトの sayHello() 操作が文字列 (string) を返し shutdown() メソッドが ORB を停止させています。OMG IDL の構文とセマンティクスの詳細は、OMG の Web サイトで CORBA Specification の第 3 章を参照してください。

PersistentHello.idl

注: OMG IDL でコードを記述する場合、モジュール名にインタフェース名を使用しないでください。モジュール名にインスタンス名を使用すると、異なるベンダーのツールを使ったコンパイル実行時に、結果の整合性が維持されなくなる危険があります。その結果、コードの移植性が損なわれます。たとえば、同じ名前を含むコードを Sun Microsystems の IDL-to-Java コンパイラを使ってコンパイルすると、1 つの結果が得られます。同じコードを別のベンダーの IDL-to-Java コンパイラを使ってコンパイルすると、別の結果になる場合があります。

アプリケーションを完成させるには、サーバ (PersistentServer.java)、サーバント (PersistentHelloServant.java)、およびクライアント (PersistentClient.java) を実装します。

サーバの実装 (PersistentServer.java)

このサーバ例 (PersistentServer) にはサーバの main() メソッドが含まれます。 この main() メソッドでは、次の処理を行います。

この例では、持続オブジェクトサーバの例を示します。一時オブジェクトサーバを使用する「Hello World」プログラムの例については、「一時サーバを使った Hello World の例」を参照してください。CORBA サーバの詳細については、「サーバの開発」を参照してください。

PersistentServer.java

サーバントの実装 (PersistentHelloServant.java)

サーバント例 PersistentHelloServant は、IDL インタフェース Hello の実装です。つまり、Hello の各インスタンスは、 PersistentHelloServant のインスタンスにより実装されます。このサーバントは HelloPOA のサブクラスで、 例題 IDL から idlj コンパイラにより生成されます。 サーバントには、IDL の操作ごとに 1 つのメソッドが含まれます。 この例では sayHello() メソッドと shutdown() メソッドが含まれます。サーバントメソッドは、 Java の通常のメソッドと変わりません。ORB 関連処理を行うコードは 引数や結果の整列化などを行い、 スケルトンで提供されます。

PersistentHelloServant.java

注: この例では、説明のために、shutdown() メソッドをサーバントの一部として含めています。このメソッドが含まれるのは、この例のサーバの持続性を示すためです。この方法は、次の理由により、プログラミング方法としては推奨されません。

クライアント アプリケーションの実装 (PersistentClient.java)

このアプリケーションクライアントでは、次の処理を行います。

PersistentClient.java

// Copyright and License 
 
import java.util.Properties;
import org.omg.CORBA.ORB;
import org.omg.CORBA.OBJ_ADAPTER;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.CosNaming.NameComponent;
import org.omg.PortableServer.POA;

import Persistent.HelloHelper;
import Persistent.Hello;

public class PersistentClient {

    public static void main(String args[]) {

        try {
            // Step 1: Instantiate the ORB
            ORB orb = ORB.init(args, null);

            // Step 2: Resolve the PersistentHelloServant by using INS's
            // corbaname url. The URL locates the NameService running on
            // localhost and listening on 1050 and resolve 
            // 'PersistentServerTutorial' from that NameService
            org.omg.CORBA.Object obj = orb.string_to_object( 
                "corbaname::localhost:1050#PersistentServerTutorial");
 
            Hello hello = HelloHelper.narrow( obj );

            // Step 3: Call the sayHello() method every 60 seconds and shutdown
            // the server. Next call from the client will restart the server,
            // because it is persistent in nature.
            while( true ) {
                System.out.println( "Calling Persistent Server.." );
                String helloFromServer = hello.sayHello();
                System.out.println("Message From Persistent Server: " +
                    helloFromServer );
                System.out.println( "Shutting down Persistent Server.." );
                hello.shutdown( );
                Thread.sleep( 60000 );
            }
        } catch ( Exception e ) {
            System.err.println( "Exception in PersistentClient.java..." + e );
            e.printStackTrace( );
        }
    }
}

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

「Hello World」プログラムは単純ですが、このプログラムを通して、「静的呼び出し」を使用する CORBA プログラムの開発に必要な作業のすべてを学び、経験することができます。

この例ではネームサービスが必要です。ネームサービスとは、オブジェクト参照に名前をバインドして CORBA オブジェクトに命名することができる CORBA サービスです。「ネームバインディング」はネームサービスに格納され、クライアントは名前を与えて目的のオブジェクト参照を取得できます。この例では、持続ネームサービスとサーバマネージャを含む orbd を使用します。

この例を実行するにあたって、Solaris ソフトウェアの使用時は、ポート 1024 未満でプロセスを開始する場合、root ユーザになる必要があります。このため、1024 以上のポートを使用することをお勧めします。以下の説明では、-ORBInitialPort オプションを使って、Java IDL Object Request Broker Daemon (orbd) 用にポート 1050 を使用するように設定できることを前提としています。必要であれば別のポートに変更してください。

開発マシンでこのクライアントサーバアプリケーションを実行するには、次のようにします。

  1. この例の IDL ファイルと Java ファイルを作成するか、ダウンロードします。
  2. PersistentHello.idl ファイルが置かれているディレクトリに移動します。

  3. IDL ファイルから IDL-to-Java コンパイラ idlj を実行して、スタブとスケルトンを作成します。この手順は、java/bin ディレクトリのパスを、使用するパスに含めていることを前提にしています。
      idlj  -fall -td . -verbose  PersistentHello.idl
    

    idlj コンパイラの -fall オプションを使って、クライアントとサーバ側のバインディングの両方を生成する必要があります。このコマンド行でデフォルトのサーバ側バインディングが生成されます。これは POA 継承サーバ側モデルであることを前提にしています。idlj オプションの内容については、「IDL-to-Java コンパイラのオプション」を参照してください。

    idlj コンパイラでは多数のファイルが生成されます。実際に生成されるファイルの数は、IDL ファイルのコンパイル時に選択されたオプションによって異なります。生成されたファイルには標準の機能があるので、プログラムを配置して実行するまでは無視してもかまいません。PersistentHello.idlidlj コンパイラで、コマンド行の -fall オプションを使って生成されるファイルは次のとおりです。

    • HelloPOA.java

      この abstract クラスは、ストリームベースのサーバスケルトンで、サーバに対して基本的な CORBA 機能を提供します。これは org.omg.PortableServer.Servant を継承し、InvokeHandler インタフェースと HelloOperations インタフェースを実装します。サーバクラス PersistentHelloServantHelloPOA を継承します。

    • _HelloStub.java

      このクラスは「クライアントスタブ」で、クライアント用に基本的な CORBA 機能を提供します。これは org.omg.CORBA.portable.ObjectImpl を継承し、Hello インタフェースを実装します。

    • Hello.java

      このインタフェースには作成した IDL インタフェースの Java 版が含まれます。Hello.java インタフェースは標準的な CORBA オブジェクト機能を与える org.omg.CORBA.Object インタフェースを継承します。また HelloOperations インタフェースおよび org.omg.CORBA.portable.IDLEntity も継承します。

    • HelloHelper.java

      このクラスは補助機能、特に CORBA 「オブジェクト参照」を適切な型にキャストする narrow() メソッドを提供します。Helper クラスは CORBA ストリームへのデータ型の入出力と、Any のデータ型の挿入と抽出を扱います。Holder クラスは、Helper クラスのメソッドに入出力を委譲します。

    • HelloHolder.java

      この final クラスには、Hello 型のパブリックインスタンスメンバが入ります。IDL 型のパラメータが out または inout であれば Holder クラスが使用されます。ここでは、org.omg.CORBA.portable.OutputStream および org.omg.CORBA.portable.InputStream 引数に対する操作が規定されます。これらの引数は CORBA には存在しますが、Java のセマンティクスには簡単にマッピングできません。Holder クラスは Helper クラスのメソッドに入出力を委譲します。Holder クラスは org.omg.CORBA.portable.Streamable を実装します。

    • HelloOperations.java

      このインタフェースには sayHello() メソッドおよび shutdown() メソッドが含まれます。IDL-to-Java マッピングは、IDL インタフェースで定義された操作をすべてこのファイルに組み込み、スタブとスケルトンで共有します。

  4. Persistent ディレクトリにあるスタブとスケルトンも含め、.java ファイルをコンパイルします。この手順は、java/bin ディレクトリが実行パスに含まれていることを前提にしています。
       javac *.java Persistent/*.java
    
  5. orbd を起動します。

    orbd を起動するには、次のコマンドを入力します。

      orbd -ORBInitialPort 1050 -serverPollingTime 200&          (UNIX オペレーティングシステム)
    
      start orbd  -ORBInitialPort 1050 -serverPollingTime 200&   (Windows オペレーティングシステム)
    
    

    1050 はネームサーバを実行するポートです。-ORBInitialPort は必要なコマンド行の引数です。Solaris ソフトウェアの使用時は、1024 より小さいポートでプロセスを開始する場合は、root ユーザになる必要があります。このため、1024 以上のポートを使用することをお勧めします。

    -serverPollingTime 200 引数は、servertool を使用して登録された持続サーバが正常に動作していることを ORBD が確認する回数を指定します。デフォルト値は 1,000 ミリ秒です。この例では、頻繁に障害を監視できるように、このパラメータを 200 ミリ秒に設定します。サーバの障害が検出された場合は、適切な状態になるようにサーバが再起動されます。

  6. Hello サーバを起動します。

    持続サーバを ORBD に登録するには、servertool を使用してサーバを起動する必要があります。servertool は、アプリケーションプログラマが、持続サーバの登録、登録解除、起動、および停止を行うためのコマンド行インタフェースです。servertool を起動したら、orbd が実行されているポートとホスト (異なる場合) を指定する必要があります。

    Hello サーバを起動するには

    • 次のように、別の端末ウィンドウのコマンド行またはコマンドプロンプトから servertool を起動します。

        servertool -ORBInitialPort 1050        (UNIX オペレーティングシステム)
        
        start servertool -ORBInitialPort 1050  (Windows オペレーティングシステム) 
      

      前回の手順と同様にネームサーバ (orbd) のポートを指定します。たとえば -ORBInitialPort 1050 のようになります。servertool は、ネームサーバと同じポート上で起動する必要があります。

      servertool コマンド行インタフェースが表示されます。

      Server Tool

    • 以下に示すように、servertool のプロンプトから PersistentServer を登録します。次の情報は、改行しないで 1 つの長い文字列として入力します。

        servertool  > register -server PersistentServer -applicationName s1 
                      -classpath path_to_server_class_files 
      

      servertool によってサーバが登録されて、「s1」という名前がサーバに割り当てられ、サーバ ID が表示されます。

  7. 次のように、別の端末ウィンドウのコマンド行またはコマンドプロンプトからクライアントアプリケーションを実行します。

      java -classpath . PersistentClient 
      

    端末ウィンドウまたは DOS プロンプトに以下のメッセージが表示されます。

    Calling Persistent Server..
    Message From Persistent Server:Hello From Persistent Server...
    Shutting down Persistent Server..
    Calling Persistent Server..
    Message From Persistent Server:Hello From Persistent Server...
    Shutting down Persistent Server..
    

この例では、クライアントが 1 分間に 1 度 sayHello() メソッドを起動し、持続サーバを終了します。持続サーバは、次にクライアントが sayHello() メソッドを起動したときに自動的に再起動されます。

このチュートリアルを終了したら、ネームサーバ (orbd) を停止するか終了してください。DOS プロンプトでは、サーバを実行しているウィンドウを選択して Ctrl+C と入力すると停止します。UNIX シェルでは、端末ウィンドウから pkill ordb と入力します。サーバを明示的に停止するまでは、呼び出し待機状態が続きます。

「2 台のマシンで実行する Hello World プログラム」では、クライアントとサーバという 2 台のマシンで簡単なアプリケーションを分散させる方法の一例を示します。

UNIX 上での Makefile を使用した例の実行

以下のコードは、この例を実行するために使用できる Makefile の例を示しています。JAVA_HOME の場所は、実際に J2SE 5.0 をインストールした場所に変更してください。CLASSPATH 変数は、サンプルアプリケーションを作成したディレクトリに変更してください。 この例は、UNIX オペレーティングシステムを想定して作成されています。Windows オペレーティングシステムを使用している場合は、適宜変更を加えてください。

#Change to location of your J2SE installation.
JAVA_HOME=/home/user_name/j2sdk1.5.0/

CLASSPATH=.

JAVAC=$(JAVA_HOME)/bin/javac
JAVA=$(JAVA_HOME)/bin/java

ORB_INITIAL_PORT=1050
ORB_INITIAL_HOST=localhost
ORB_ACTIVATION_PORT=1049

#Change ClassPath based on where your PersistentServer is located.
export CLASSPATH=<path to server class files>
IDLJ :=$(JAVA_HOME)/bin/idlj 

ORB_PROPS=-Dorg.omg.CORBA.ORBInitialHost=$(ORB_INITIAL_HOST) 
-Dorg.omg.CORBA.ORBInitialPort=$(ORB_INITIAL_PORT)

IDLJ_FLAGS=-fall -td . -verbose 

ORBD=${JAVA_HOME}/bin/orbd -ORBInitialPort ${ORB_INITIAL_PORT} 
-port ${ORB_ACTIVATION_PORT} -serverPollingTime 200 
-serverStartupDelay 1000 

SERVERTOOL=${JAVA_HOME}/bin/servertool

all: clean build run

build: stubs

stubs:
	$(IDLJ) $(IDLJ_FLAGS) PersistentHello.idl
	$(JAVAC) *.java
	$(JAVAC) Persistent/*.java

runc:
	$(JAVA) -classpath . PersistentClient 
        
runorbd:
	$(ORBD) 

# Enter the following command in servertool to register server:
# (without the # sign)
# register -server PersistentServer -applicationName s1 
-classpath path_to_server_class_files

servertool:
	$(SERVERTOOL) -ORBInitialPort $(ORB_INITIAL_PORT) 

clean: 
	rm -rf Persistent 
	rm -rf *.class 

Makefile を使用してアプリケーションを実行するには、以下のコマンドを入力します。

  1. gnumake build
  2. gnumake runorbd
  3. gnumake runservertool
  4. servertool で、上記のコマンドを入力します。
  5. gnumake runc


Java IDL トップへ