RMI-IIOP プログラマーズガイド
|
RMI-IIOP ドキュメント |
このドキュメントでは、Internet Inter-ORB Protocol (IIOP) を使用してリモートオブジェクトにアクセスすることができる、Java Remote Method Invocation (RMI) プログラムの作成方法について説明します。RMI プログラムにごくわずかな制約を課すことによって、任意の言語の CORBA クライアントから RMI-IIOP サーバにアクセスできるようになります。RMI-IIOP によって、RMI を簡単に使用できるようになり、CORBA/IIOP 言語の相互運用性が実現されます。
RMI は通信プロトコルとして CORBA-IIOP を使用しないので、その他の言語との相互運用性に欠けています。
Java(TM) 2 Platform, Standard Edition (J2SE) の CORBA/IIOP 実装は、Java IDL として知られています。idlj コンパイラおよび Java IDL を使用して、Java プログラミング言語から CORBA オブジェクトを定義、実装、およびアクセスを行うことができます。
「Java IDL」の Web ページでは、CORBA/IIOP プログラミングについて Java を中心にしてわかりやすく説明されています。Java IDL プログラムの作成についての概要は、「入門: Hello World」の Web ページを参照してください。
以下は、CORBA/IIOP 機能をサポートする主な rmic フラグです。
-iiop -- IIOP スタブ/Tie を生成する
-iiop -poa -- Portable Object Adapter (POA) で動作する IIOP スタブ/Tie を生成する
-idl -- IDL を生成する
以下のオプションは、-idl オプションと同時に使用されます。
-noValueMethods -- IDL valuetype 内のメソッドおよびコンストラクタの IDL の生成を停止する
-always -- 既存のスタブ、Tie、idl が入力クラスより新しい場合も強制的に再生成を行う。-iiop と -idl の両方またはいずれかのフラグが存在する場合のみ有効
-idlModule <fromJavaPackage<.class>> <toIDLModule> -- IDLEntity パッケージのマッピングを指定する。例: -idlModule foo.bar my::real::idlmod
-idlFile <fromJavaPackage<.class>> <toIDLFile> -- IDLEntity ファイルマッピングを指定する。例: -idlFile test.pkg.X TEST16.idl
rmic コンパイラの詳細については、rmic のドキュメントを参照してください。
スタブクラスは、abstract インタフェースにも生成されます。abstract インタフェースは、java.rmi.Remote を継承したインタフェースではありませんが、そのインタフェースのメソッドはすべて java.rmi.RemoteException か、java.rmi.RemoteException のスーパークラスをスローします。また、java.rmi.Remote を継承せず、メソッドを持たないインタフェースも、abstract インタフェースです。
質問: J2SE 1.3 で動作する RMI-IIOP アプリケーションを持っています。rmic -iiop -poa
を使って新しいスタブおよびスケルトンを生成すると動作しなくなってしまいました。なぜですか。 回答: 以下に挙げるように、RMI-IIOP プログラムのコンパイルおよび実行方法は 2 通りあります。以下の方法を組み合わせるのは避けてください。
- デフォルトの RMI-IIOP の動作。デフォルトの RMI-IIOP の動作を使用するアプリケーションの例は、「チュートリアル: 入門: RMI-IIOP の使用法」で参照できます。
- POA ベースの RMI-IIOP。非標準の POA ベースの RMI-IIOP の動作を使用するアプリケーションの例は、「チュートリアル: 入門: RMI-IIOP の使用法」で参照できます。
今回の J2SE のリリースには、-iiop -poa オプションが追加されています。-iiop フラグに -poa オプションを指定すると、継承が org.omg.CORBA_2_3.portable.ObjectImpl から org.omg.PortableServer.Servant に変わります。この種のマッピングは非標準であり、Java Language to OMG IDL Language Mapping Specification には指定されていません。
Portable Object Adapter (POA) の PortableServer モジュールは、ネイティブの Servant 型を定義します。Java プログラミング言語では、Servant 型は、Java の org.omg.PortableServer.Servant クラスにマッピングされています。これはあらゆる POA サーバント実装の基底クラスとなり多数のメソッドを提供します。これらのメソッドはアプリケーションプログラマが呼び出すだけではなく、POA 自身からも呼び出され、場合によってはサーバントの動作を制御するためにユーザがオーバーライドすることもあります。
注: rmic -idl で OMG IDL が生成されたあと、IDL-to-Java コンパイラではなく、IDL-to-C++ またはその他の言語へのコンパイラで生成された IDL を使用します。「ラウンドトリップ」は非推奨であり、不要です。IDL 生成機能は、C++ などのその他の言語で使用されることになっています。Java クライアントまたはサーバは、元の RMI-IIOP 型を使用できます。
IDL を使用すると、オブジェクトに対して API を指定するときに、プログラミング言語に依存せずに、単に宣言することができます。IDL は、メソッドおよびデータの仕様として使用します。CORBA バインディングを提供する任意の言語で、メソッドおよびデータの作成および呼び出しを行うことができます。これらの言語には、Java および C++ が含まれています。詳細は、Java Language to IDL Mapping (OMG) を参照してください。
注: 生成された IDL は、IDL に対する CORBA 2.3 拡張機能がサポートされている IDL コンパイラを使用しないとコンパイルできません。
rmic についての詳細は、RMIC ツールのページ (Solaris 版/Windows 版) を参照してください。
import javax.naming.*; ... Context ic = new InitialContext();
import java.rmi.*; ... Naming.rebind("MyObject", myObj);次のコードを使用します。
import javax.naming.*; ... ic.rebind("MyObject", myObj);
import java.util.*; import javax.naming.*; ... Hashtable env = new Hashtable(); env.put("java.naming.applet", this); Context ic = new InitialContext(env);
サーバ側では、PortableRemoteObject.toStub() 呼び出しを使用してスタブを取得し、writeObject() を使用してそのスタブを ObjectOutputStream に直列化します。これらの処理を行うコードは、たとえば次のようになります。
クライアント側では、readObject() を使用して、ObjectInputStream から、リモート参照の直列化復元をオブジェクトに対して行います。次のようなコードが使用されます。org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null); Wombat myWombat = new WombatImpl(); javax.rmi.CORBA.Stub myStub = (javax.rmi.CORBA.Stub)PortableRemoteObject.toStub(myWombat); myStub.connect(myORB); // myWombat is now connected to myORB. To connect other objects to the // same ORB, use PortableRemoteObject.connect(nextWombat, myWombat); FileOutputStream myFile = new FileOutputStream("t.tmp"); ObjectOutputStream myStream = new ObjectOutputStream(myFile); myStream.writeObject(myStub);
FileInputStream myFile = new FileInputStream("t.tmp"); ObjectInputStream myStream = new ObjectInputStream(myFile); Wombat myWombat = (Wombat)myStream.readObject(); org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null); ((javax.rmi.CORBA.Stub)myWombat).connect(myORB); // myWombat is now connected to myORB. To connect other objects to the // same ORB, use PortableRemoteObject.connect(nextWombat, myWombat);
_<implementionName>_Tie.class _<interfaceName>_Stub.class
orbd -ORBInitialPort port#ORBD の起動時にポート番号を指定する必要があります。
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://<hostname>:1050 <appl_class>この例では、ネームサービスポート番号 1050 を使用します。ステップ 7 でそれ以外のポートを指定した場合、プロバイダの URL 内のポート番号を使用する必要があります。プロバイダの URL の<ホスト名>は、ステップ 7 で CosNaming サーバを起動したときに使用したホスト名です。
java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory java.naming.provider.url=iiop://<hostname>:1050この例では、ネームサービスポート番号 1050 を使用します。ステップ 7 でそれ以外のポートを指定した場合、プロバイダの URL 内のポート番号を使用する必要があります。プロバイダの URL の<ホスト名>は、ステップ 7 で CosNaming サーバを起動したときに使用したホスト名です。
新しい RMI-IIOP アプリケーションの作成方法に関するチュートリアルは、「入門: RMI-IIOP の使用法 POA ベースのサーバ側モデルの使用例」または「チュートリアル: 入門: RMI-IIOP の使用法」で参照できます。
PortableRemoteObject.exportObject() 呼び出しは、Tie オブジェクトを作成し、将来の使用に備えてキャッシュに格納するだけです。作成された Tie には、委譲や ORB との関連付けがありません。これを「明示的呼び出し」と呼びます。
PortableRemoteObject.exportObject() は、サーバインスタンスの作成時に自動的に生成されます。これは、PortableRemoteObject コンストラクタを基底クラスとして呼び出したときに生成されます。これを「暗黙の呼び出し」と呼びます。
PortableRemoteObject.toStub() は、あとでアプリケーションによって呼び出されたときに対応する Stub オブジェクトを生成し、キャッシュに格納されている Tie オブジェクトと関連付けます。ただし、Tie は接続されておらず、委譲を持たないので、新しく作成されたスタブも委譲や ORB を持ちません。
スタブに委譲が設定されるのは、アプリケーションが Stub.connect(orb) を呼び出すときのみです。このため、ORB 接続が確立される前にスタブを操作しようとしても失敗します。
「Java Language to IDL Mapping Specification」では、Stub.connect() メソッドは次のように既定されています。
connect メソッドにより、スタブは指定された ORB オブジェクト orb を使ってリモート接続を確立できる状態になります。通常、接続は、リモートメソッド呼び出しでスタブが引数として受け渡されるときに暗黙的に確立されます。ただし、明示的な呼び出しによって接続を確立するほうが都合がよい場合もあります (直列化復元後など)。スタブがすでに orb に接続されていて、orb の委譲セットを持っている場合、接続は機能しません。スタブがその他の ORB に接続されている場合、RemoteException がスローされます。それ以外の場合、このスタブと ORB オブジェクト orb の委譲が生成されます。
POA が有効になっていないサーバントの場合、必須設定として Stub.connect(orb) が必要になります。
注: 異なる言語で書かれた ORB 間での通信が可能なはずですが、Java ORB と他のベンダーの ORB との相互運用性はまだテストされていません。
UnicastRemoteObject は、RMI プログラミングでオブジェクト実装のスーパークラスとして使用されます。PortableRemoteObject は RMI-IIOP プログラミングで使用されます。PortableRemoteObject を使用する場合は、実行時にトランスポートプロトコルを JRMP か IIOP に変更できます。
ulimit -n 90