POA、持続サーバ、および持続ネームサービスの使用
このドキュメントは、インタフェースを定義する IDL (Interface Definition 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
module Persistent { interface Hello { string sayHello(); oneway void shutdown(); }; };注: 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
// PersistentServer.java // Copyright and License import java.util.Properties; import org.omg.CORBA.Object; import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper; import org.omg.CORBA.Policy; import org.omg.PortableServer.POA; import org.omg.PortableServer.*; import org.omg.PortableServer.Servant; public class PersistentServer { public static void main(String args[]) { Properties properties = System.getProperties(); properties.put( "org.omg.CORBA.ORBInitialHost", "localhost" ); properties.put( "org.omg.CORBA.ORBInitialPort", "1050" ); try { // STEP 1: Instantiate the ORB ORB orb = ORB.init(args, properties); // STEP 2: Instantiate the servant PersistentHelloServant servant = new PersistentHelloServant(orb); // STEP 3: Create a POA with Persistent Policy // ******************* // STEP 3-1: Get the rootPOA POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); // STEP 3-2: Create the Persistent Policy Policy[] persistentPolicy = new Policy[1]; persistentPolicy[0] = rootPOA.create_lifespan_policy( LifespanPolicyValue.PERSISTENT); // STEP 3-3: Create a POA by passing the Persistent Policy POA persistentPOA = rootPOA.create_POA("childPOA", null, persistentPolicy ); // STEP 3-4: Activate PersistentPOA's POAManager, Without this // All calls to Persistent Server will hang because POAManager // will be in the 'HOLD' state. persistentPOA.the_POAManager().activate( ); // *********************** // STEP 4: Associate the servant with PersistentPOA persistentPOA.activate_object( servant ); // STEP 5: Resolve RootNaming context and bind a name for the // servant. // NOTE: If the Server is persistent in nature then using Persistent // Name Service is a good choice. Even if ORBD is restarted the Name // Bindings will be intact. To use Persistent Name Service use // 'NameService' as the key for resolve_initial_references() when // ORBD is running. org.omg.CORBA.Object obj = orb.resolve_initial_references( "NameService" ); NamingContextExt rootContext = NamingContextExtHelper.narrow( obj ); NameComponent[] nc = rootContext.to_name( "PersistentServerTutorial" ); rootContext.rebind( nc, persistentPOA.servant_to_reference( servant ) ); // STEP 6: We are ready to receive client requests orb.run(); } catch ( Exception e ) { System.err.println( "Exception in Persistent Server Startup " + e ); } } }
PersistentHelloServant.java
)サーバント例 PersistentHelloServant は、IDL インタフェース Hello の実装です。つまり、Hello の各インスタンスは、 PersistentHelloServant のインスタンスにより実装されます。 このサーバントは HelloPOA のサブクラスで、 例題 IDL から idlj コンパイラにより生成されます。 サーバントには、IDL のオペレーションごとに 1 つのメソッドが含まれます。 この例では sayHello() メソッドと shutdown() メソッドが含まれます。 サーバントメソッドは、 Java の通常のメソッドと変わりません。ORB 関連処理を行うコードは 引数や結果の整列化などを行い、 スケルトンで提供されます。
PersistentHelloServant.java
// PersistentHelloServant.java // Copyright and License import org.omg.CORBA.ORB; public class PersistentHelloServant extends Persistent.HelloPOA { private ORB orb; public PersistentHelloServant( ORB orb ) { this.orb = orb; } /** * sayHello() method implementation returns a simple message. */ public String sayHello( ) { return "Hello From Persistent Server..."; } /** * shutdown() method shuts down the Persistent Server. * See NOTE below. */ public void shutdown( ) { orb.shutdown( false ); } }
注: この例では、説明のために、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」プログラムは単純ですが、このプログラムを通して、「静的呼び出し」を使用する CORBA プログラムの開発に必要な作業すべてを学び、経験することができます。
この例ではネームサービスが必要です。ネームサービスとは、オブジェクト参照に名前をバインドして CORBA オブジェクトに命名することができる CORBA サービスです。 「ネームバインディング」はネームサービスに格納され、クライアントは名前を与えて目的のオブジェクト参照を取得できます。 この例では、持続ネームサービスとサーバマネージャを含む orbd を使用します。
この例を実行するにあたって、Solaris ソフトウェアの使用時は、ポート 1024 未満でプロセスを開始する場合、root ユーザになる必要があります。このため、1024 以上のポートを使用することをお勧めします。以下の説明では、-ORBInitialPort オプションを使って、Java IDL Object Request Broker Daemon (orbd) 用にポート 1050 を使用するように設定できることを前提としています。 必要であれば別のポートに変更してください。
開発マシンでこのクライアントサーバアプリケーションを実行するには、次のようにします。
idlj -fall -td . -verbose PersistentHello.idl
idlj コンパイラの -fall オプションを使って、クライアントとサーバ側のバインディングの両方を生成する必要があります。 このコマンド行でデフォルトのサーバ側バインディングが生成されます。これは POA 継承サーバ側モデルであることを前提にしています。 idlj オプションの内容については、「IDL-to-Java コンパイラのオプション」を参照してください。
idlj コンパイラでは多数のファイルが生成されます。 実際に生成されるファイルの数は、IDL ファイルのコンパイル時に選択されたオプションによって異なります。 生成されたファイルには標準の機能があるので、プログラムを配置して実行するまでは無視してもかまいません。 PersistentHello.idl の idlj コンパイラで、コマンド行の -fall オプションを使って生成されるファイルは次のとおりです。
この抽象クラスは、ストリームベースの「サーバスケルトン」で、サーバ用に基本的な CORBA 機能を提供します。 これは org.omg.PortableServer.Servant を継承し、InvokeHandler インタフェースおよび HelloOperations インタフェースを実装します。 サーバクラス PersistentHelloServant は HelloPOA を継承します。
このクラスは「クライアントスタブ」で、クライアント用に基本的な CORBA 機能を提供します。 これは org.omg.CORBA.portable.ObjectImpl を継承し、Hello.java インタフェースを実装します。
このインタフェースには作成した IDL インタフェースの Java 版が含まれます。 Hello.java インタフェースは標準的な CORBA オブジェクト機能を与える org.omg.CORBA.Object インタフェースを継承します。 また HelloOperations インタフェースおよび org.omg.CORBA.portable.IDLEntity も継承します。
このクラスは補助機能、特に CORBA 「オブジェクト参照」を適切な型にキャストする narrow() メソッドを提供します。Helper クラスは CORBA ストリームへのデータ型の入出力と、Any のデータ型の挿入と抽出を扱います。Holder クラスは、Helper クラスのメソッドに入出力を委譲します。
この 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 を実装します。
このインタフェースには sayHello() メソッドおよび shutdown() メソッドが含まれます。 IDL-to-Java マッピングは、IDL インタフェースで定義されたオペレーションをすべてこのファイルに組み込み、スタブとスケルトンで共有します。
javac *.java Persistent/*.java
orbd を起動するには、次のコマンドを入力します。
orbd -ORBInitialPort 1050 -serverPollingTime 200
1050 はネームサーバを実行するポートです。 -ORBInitialPort は必要なコマンド行の引数です。 Solaris ソフトウェアの使用時は、1024 より小さいポートでプロセスを開始する場合は、root ユーザになる必要があります。このため、1024 以上のポートを使用することをお勧めします。
-serverPollingTime 200 引数は、servertool を使用して登録された持続サーバが正常に動作していることを ORBD が確認する回数を指定します。 デフォルト値は 1,000 ミリ秒です。この例では、頻繁に障害を監視できるように、このパラメータを 200 ミリ秒に設定します。 サーバの障害が検出された場合は、適切な状態になるようにサーバが再起動されます。
持続サーバを ORBD に登録するには、servertool を使用してサーバを起動する必要があります。servertool は、アプリケーションプログラマが、持続サーバの登録、登録解除、起動、および停止を行うためのコマンド行インタフェースです。 servertool を起動したら、orbd が実行されているポートとホスト (異なる場合) を指定する必要があります。
Hello サーバを起動するには
servertool -ORBInitialPort 1050
前回の手順と同様にネームサーバ (orbd) のポートを指定します。たとえば -ORBInitialPort 1050 のようになります。 servertool は、ネームサーバと同じポート上で起動する必要があります。
servertool コマンド行インタフェースが表示されます。
servertool > register -server PersistentServer -applicationName s1 -classpath path_to_server_class_files
servertool によってサーバが登録されて、「s1」という名前がサーバに割り当てられ、サーバ ID が表示されます。
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 台のマシンで簡単なアプリケーションを分散させる方法の一例を示します。
以下のコードは、この例を実行するために使用できる Makefile の例を示しています。 JDK のインストール場所は、実際に JDK をインストールした場所に変更してください。 クラスパスは、サンプルアプリケーションを作成したディレクトリに変更してください。
#Change to location of your JDK installation. JAVA_HOME=/usr/local/java/jdk1.4/solsparc 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 を使用してアプリケーションを実行するには、以下のコマンドを入力します。
Java IDL トップへ |