クライアント側のプログラム手順は次のとおりです。
ORBを起動した後は、ネーミングサービスを利用してリモートオブジェクトのオブジェクトリファレンスを獲得します。いったんリファレンスを取得すれば、以降はリモートオブジェクトのメソッドを、あたかも同じVM上のオブジェクトのメソッドを呼ぶかのように、呼び出すことが可能になります。オブジェクトリファレンスとは、分散ORBシステム上でオブジェクトを一意に指定する情報を提供するもので、このリファレンスを取得すれば、オブジェクトが実際にどのマシン上にあるか意識せずに利用できます。(位置透過性)
注意点)
分散オブジェクト技術を使えば、確かにリモートオブジェクトへのメソッド呼び出しがあたかも同一メモリ空間上のオブジェクト呼び出しと同じかのように記述できます。しかし、実際にはネットワーク通信が介在するため、呼び出しが失敗する可能性を無視することはできません。
IDLインタフェースCounterで定義されるCORBAオブジェクトを利用するクライアントプログラムの記述を次に示します。
package jp.gr.java_conf.torutk.learn.idl.counter_ex1; import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; public class Client { public static void main(String[] args) { Counter counter = null; try { |
|
ORB orb = ORB.init(args, null); |
ORBの起動 |
org.omg.CORBA.Object objNs = orb.resolve_initial_references("NameService"); NamingContext rootNameContext = NamingContextHelper.narrow(objNs); |
ネーミングサービスの取得 |
NameComponent nc = new NameComponent("TheCounter", "Object"); NameComponent[] path = {nc}; counter = CounterHelper.narrow( rootNameContext.resolve(path)); |
オブジェクトリファレンス獲得 |
} catch (Exception e) { e.printStackTrace(); System.exit(1); } try { int num = counter.getCount(); System.out.println("Server Counter = " + num); counter.increment(); num = counter.getCount(); System.out.println("Server Counter = " + num); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } } // Client |
リモートオブジェクトの呼び出し |
例外の処理を少々さぼってException型でcatchしています。これはよくないコーディングです。
ORBの起動ページを参照。
ネーミングサービスの取得には、ORBクラスのメソッドresolve_initial_referencesを使用します。引数には、ネーミングサービスを示す文字列"NameService"を与えます。このAPIは、ネーミングサービス以外にもRootPOAの取得などに使われます。
org.omg.CORBA.Object objNs = orb.resolve_initial_references("NameService");
resolve_initial_referencesメソッドは戻り値の型がorg.omg.CORBA.Objectなので、ネーミングサービスを表すクラスの型に変換しなくてはなりません。ネーミングサービスもCORBAオブジェクトなので、Java言語のキャストを使うのではなく、そのHelperクラスのnarrowメソッドを使ってナロー(CORBAにおけるキャスト)する必要があります。
ここで、ネーミングサービスを表す型は次の2種類あります。
1.の場合のコーディング NamingContext rootNameContext = NamingContextHelper.narrow(objNs);
2.の場合のコーディング NamingContextExt rootNameContext = NamingContextExtHelper.narrow(objNs);
1.は、元々のネーミングサービス(COS Naming Service)で規定されているものです。2.はInteroperable Naming Serviceにおいて追加されました。2.は1.を継承し、4つのオペレーションが追加され、これを利用すると次のネーミングサービスからオブジェクトリファレンスを獲得するコーディングが楽になります。
ネーミングサービスが取得できたら、次にクライアント側が利用するCORBAオブジェクトのオブジェクトリファレンスを獲得します。ネーミングサービスは、CORBAオブジェクトに付けられた名前情報からオブジェクトリファレンスを取り出すので、まず利用するCORBAオブジェクトの名前情報を生成します。
名前情報は、1.の場合はNameComponent型のオブジェクトとして生成します。2.の場合は単なる文字列です。個々の名前情報は、idとkindの2つの識別子から構成されます。前者は名前、後者はその名前情報の種類を指定します。CORBAにおけるネーミングサービスは、何千何万ものオブジェクト群を管理する大規模なものまで想定したスケーラビリティを持たせるため、ディレクトリ構造(木構造)を持ちます。コンピュータのファイルシステムにおけるディレクトリとファイルの関係のように、名前といってもディレクトリ自身を示すものとオブジェクトリファレンスを保持するものとがあります。そこで、id(名前)とkind(種類)と2つの識別子を持っています。また、kindはネーミングサービスの構造を設計する人が自由に種類を決めれるように任意の文字列を使用できます。
今回の例では、リモートのCounterオブジェクトについて、以下のように規定しています。また、名前情報は、ネーミングサービスの直下(ルート)に直接置いています。
識別種類 | 識別情報(名前) |
id | TheCounter |
kind | Object |
1.の場合のコーディング NameComponent nc = new NameComponent("TheCounter", "Object"); NameComponent[] path = {nc};
2.の場合のコーディング String name = "TheCounter.Object";
ネーミングサービスから名前情報を元にオブジェクトリファレンスを取り出すには、(1) NamingContext 型の resolve メソッド、(2) NamingContextExt 型の resolve_str メソッド を使います。どちらも org.omg.CORBA.Object 型が得られるので、Helper 型のnarrowを使ってナローします。
1.の場合のコーディング org.omg.CORBA.Object objRef = rootNameContext.resolve(path) Counter counter = CounterHelper.narrow(objRef);
2.の場合のコーディング org.omg.CORBA.Object objRef = rootNameContext.resolve_str(name) Counter counter = CounterHelper.narrow(objRef);
普通のオブジェクトに対するメソッドと同じように呼び出します。
int num = counter.getCount();
前項の手順では、目的のリモートオブジェクトリファレンスを獲得するために、いったんネーミングサービスのリファレンスを獲得していました。
獲得したい目的のリファレンスがネーミングサービス中に格納されているコンテクストが分かっている場合、次のサンプルコードのように一発でリモートオブジェクトリファレンスを獲得するコードを記述することができます。
String corbaUrl = "corbaname:iiop:nameserver:5555#TheCounter.Object"; org.omg.CORBA.Object obj = orb.string_to_object(corbaUrl); counter = CounterHelper.narrow(obj); |
corbaUrl変数には、corbaname URLという文字列形式でネーミングサービスが存在するホスト名・ポート番号、およびネーミングサービス中に格納されているオブジェクトリファレンスのコンテクスト情報を指定します。
org.omg.CORBA.ORBクラスのstring_to_objectメソッドを使用して、corbaname
URL文字列からリモートオブジェクトリファレンスを取り出します。
CORBA側でやっていることは前項の手順と同じなのですが、アプリケーションを書くときに楽をすることができます。
クライアントプログラムを実行するには、先にネーミングサービスおよびサーバプログラムを実行している必要があります。クライアントプログラムを実行する際、既に起動されているネーミングサービスのオブジェクトリファレンス情報をコマンドラインオプションで指定します。
ネーミングサービスの指定 | -ORBInitRef NameService=<オブジェクトURL> |
ネーミングサービスの起動については、使用しているCORBA製品によって異なります。OpenORBの提供するネーミングサービスについては、OpenORB TipsページのNaming Service項を参照。
D:\develop\ex1\classes>java jp.gr.java_conf.torutk.learn.idl.counter_ex1.Client |
CORBAでは、リモートオブジェクトのリファレンスを獲得する方法として以下のものがあります。