ネームサービス


ここでは、以下の項目について説明します。

COS ネームサービスの概要

CORBA の COS (Common Object Services) ネームサービスは、ファイルシステムがファイルに対してディレクトリ構造を提供しているのと同じように、オブジェクト参照に対してツリー構造のディレクトリを提供します。Java IDL のネームサービスは、COS ネームサービスの仕様の実装です。以下にこのドキュメントから抜粋した概要を示します。

名前とオブジェクトの関連付けは、「ネームバインディング」と呼ばれます。ネームバインディングは、常に「ネーミングコンテキスト」に対して相対的に定義されます。ネーミングコンテキストは、それぞれが固有の名前をもつ一連のネームバインディングを含むオブジェクトです。複数の名前を、同一のまたは異なるコンテキスト内のオブジェクトに同時にバインドすることができます。

名前の解決とは、特定のコンテキスト内でその名前に関連付けられているオブジェクトを判別することです。名前のバインドとは、特定のコンテキスト内でネームバインディングを作成することです。名前は、常にコンテキストに対して相対的に解決され、絶対名は存在しません。

コンテキストはほかのオブジェクトと同様に、コンテキスト自体もネーミングコンテキスト内で名前にバインドできます。ほかのコンテキスト内でコンテキストをバインディングすると、「ネーミンググラフ」が作成されます。ネーミンググラフは、ノードとラベルの付いた境界を含む有向グラフで、各コンテキストがノードになります。ネーミンググラフを使用すると、複雑な名前を使ってオブジェクトを参照できるようになります。ネーミンググラフ内のコンテキストが指定された場合、名前のシーケンスでオブジェクトを参照できます。この名前のシーケンス (「複合名」と呼ばれる) は、解決処理をナビゲートするための、ネーミンググラフ内のパスです。

次の図にネーミンググラフの例を示します。名前空間に名前を追加する方法を示すサンプルプログラムでもこれと同じモデルを使用しています。

アプリケーションから COS ネームサービスを使用するためには、その ORB はネームサービスが動作しているホストのポートを知っているか、そのネームサービスの文字列化された初期ネーミングコンテキストにアクセスできなければなりません。ネームサービスは、Java IDL のネームサービスでも、その他の COS 準拠のネームサービスでもかまいません。

ORBD は、クライアントまたはサーバを実行する前に起動します。ORBD には、持続ネームサービスおよび一時ネームサービスが組み込まれています。これらはどちらも COS ネームサービスの実装です。

クライアントとサーバの両方が、使用するルートネーミングコンテキストについて同意する必要があります。ルートネーミングコンテキストを取得するには、orb.resolve_initial_references(String name_of_service) メソッドを使用します。"NameService" によって提供されるネームサービスのハンドルを name_of_service として取得すると、持続ネームサービスが取得されます。つまり、そのネーミングコンテキストのグラフは、サーバに障害が発生しても復元されます。「TnameService」 を使用してハンドルを取得すると、一時ネームサービスが取得されます。つまり、サービスが中断された場合は、orb.resolve_initial_references(String name_of_service) を使用してルートネーミングコンテキストを再取得する必要があります。

次に例を示します。

      // get the root naming context
      org.omg.CORBA.Object objRef =
          orb.resolve_initial_references("NameService");
      NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

文字列 「NameService」 は、すべての CORBA ORB に対して定義されています。この文字列を渡すと、ORB は、次のネームサービスのオブジェクト参照であるネーミングコンテキストオブジェクトを返します。

ORBD とともに一時ネームサービスを使用することを指定するには、文字列「TnameService」を渡します。文字列「TnameService」は、固有の名前です。この文字列を渡すと、ORB は、ORBD の一時ネームサービスへのオブジェクト参照であるネーミングコンテキストオブジェクトを返します。

CORBA のどのオブジェクト参照とも同様に、objRef は汎用の CORBA オブジェクトです。これを NamingContextExt オブジェクトとして使うには、適切な型にナロー変換する必要があります。

NamingContextExtHelper は、idlj により生成されるヘルパークラスです。このクラスの機能は HelloHelper の機能に類似しています。ここで ncRef オブジェクトは org.omg.CosNaming.NamingContextExt になったので、これを使ってネームサービスにアクセスし、サーバを登録することができます。

NamingContextExt および NamingContextExtHelper は、J2SE のこのリリースで新しく追加されました。NamingContextExt は、NamingContext を拡張したものです。NamingContextExt は、Interoperable Naming Service の一部であり、各名前が固有になっている一連のネームバインディングを含んでいます。複数の名前を、同一のまたは異なるコンテキスト内のオブジェクトに同時にバインドすることができます。NamingContextExt を使用すると、URL ベースの名前を使用してバインドと解決を行うことができます。NamingContextExtHelper は、narrow() などの、型固有でビジネスロジックを処理しない追加のヘルパーメソッドを提供します。

Interoperable Naming Service

Interoperable Naming Service (INS) は CORBA ネームサービスの上にある URL ベースのネーミングシステムで、アプリケーションに共通の初期ネーミングコンテキストを共有させる共通のブートストラップ機構でもあります。

Interoperable Naming Service (INS) には次の機能があります。

INS の使用方法を示すアプリケーションの例については、Interoperable Naming Service Exampleを参照してください。

次の図は、INS がどのように ORBD に適合するかを示しています。

ORBD



オブジェクト参照は、少なくとも、アドレス、オブジェクト参照を作成した POA の名前、およびオブジェクト ID という 3 つの情報を含んでいます。

INS を使用すると、文字列化された IOR よりも読みやすい、CORBA オブジェクトにアクセスするための URL を提供できます。次のような文字列化されたオブジェクト参照形式を使用できます。

ORB のブートストラップオプション

INS は、ブートストラップ用の ORB オプションを提供します。CORBA システムをブートストラップするには、CORBA システムにオブジェクト参照を渡す必要があります。ORBInitRef または ORBDefaultInitRef を使用して、resolve_initial_references() からカスタマイズされた CORBA サービスのハンドルを返すように ORB を構成することができます。次に例を示します。

これらのオプションを使用した場合、解決の順番は次のようになります。

  1. register_initial_references を使用して登録されたオブジェクト
  2. -ORBInitRef
  3. -ORBDefaultInitRef
  4. 独自のブートストラップ (Sun ORB のみ)

INS の詳細については、OMG 仕様 (ptc/00-08-07) を参照してください。

ネームサービスの使用

ネームサービスを使用するには、初めに、名前空間や名前空間内のオブジェクトを検出または作成するサーバとクライアントのコードを記述する必要があります。クライアントとサーバを実行する前に、ネームサービスを起動し、クライアントとサーバに対してネームサービスを探す場所を指定する必要があります。クライアントとサーバがネームサービスへのアクセスを試行したときに、実行されるステップの概要を次に示します。

ここでは、次の項目について説明します。

サンプルクライアント: 名前空間へのオブジェクトの追加

以下に示すサンプルプログラムは、名前を名前空間に追加する方法を示すものです。このサンプルプログラムは、このままの状態で完全に動作するネームサービスクライアントで、次のような単純なツリーを作成するものです。ネーミングコンテキストはイタリックフォントで示し、オブジェクト参照は通常のフォントで示します。

この例で、plans はオブジェクト参照、Personalcalendarschedule の 2 つのオブジェクト参照が含むネーミングコンテキストです。

  1. NameClient.java ファイルを作成し、適切なライブラリをインポートします。

    import java.util.Properties;
    import org.omg.CORBA.*;
    import org.omg.CosNaming.*;
    
    public class NameClient
    {
       public static void main(String args[])
       {
          try {
    

  2. ポートとホストのプロパティを設定します。

    「ネームサービスの起動」の節では、ネームサーバは、ホスト localhost のポート 1050 上で起動されます。次のコードによって、クライアントプログラムにこのポート番号とホスト名を認識させます。

            Properties props = new Properties();
            props.put("org.omg.CORBA.ORBInitialPort", "1050");
            props.put("org.omg.CORBA.ORBInitialHost", "localhost");
            ORB orb = ORB.init(args, props);
    

  3. 初期ネーミングコンテキストを取得します。

    次のコードでは、初期ネーミングコンテキストを取得し、それを ctx に代入します。2 行目では、ctx をダミーのオブジェクト参照 objref にコピーします。 この objref には、あとでさまざまな名前を割り当てて名前空間に追加します。

     
            NamingContextExt ctx =
              NamingContextExtHelper.narrow(orb.resolve_initial_references(
                "NameService"));
            org.omg.CORBA.Object objref = ctx;
    

  4. 名前「plans」をオブジェクト参照にバインドします。

    次のコードでは、名前「plans」をダミーのオブジェクト参照にバインドします。その後、rebind を使用して初期ネーミングコンテキストの下にオブジェクト参照「plans」を追加しています。rebind メソッドを使用すれば、bind を使用した場合に発生する例外を発生させずに、このプログラムを何度も繰り返し実行できます。

            NameComponent name1[] = ctx.to_name("plans");
            ctx.rebind(name1, objref);
            System.out.println("plans rebind successful!");
    

  5. 「Personal」という名前の新しいネーミングコンテキストを作成します。

    次のコードでは、「Personal」という名前の新しいネーミングコンテキストを作成します。その結果得られるオブジェクト参照 ctx2 をこの名前にバインドし、初期ネーミングコンテキストに追加します。

            NameComponent name2[] = ctx.to_name("Personal");
            NamingContextExt ctx2 = (NamingContextExt)ctx.bind_new_context(name2);
            System.out.println("New naming context, Personal, added!");
    

  6. 「schedule」と「calendar」をダミーのオブジェクト参照にバインドします。「名前のバインド」とは、特定のコンテキスト内でネームバインディングを作成することです。名前は、常にコンテキストに対して相対的に解決され、絶対名は存在しません。

    次のコードでは、ダミーのオブジェクト参照を「schedule」と「calendar」という名前で、ネーミングコンテキスト「Personal」(ctx2) にバインドします。

            NameComponent name3[] = ctx.to_name("schedule");
            ctx2.rebind(name3, objref);
            System.out.println("schedule rebind successful!");
    
            NameComponent name4[] = ctx.to_name("calendar");
            ctx2.rebind(name4, objref);
            System.out.println("calendar rebind successful!");
    
    
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
      }  
    }
    

  7. NameClient.java を保存し、そのファイルを次のようにコンパイルします。

         javac NameClient.java
    

    続行する前に構文エラーを修正します。

  8. 「ネームサービスの起動」に示す手順に従って Object Request Broker Daemon を実行します。

  9. 次のように NameClient を実行します。

         java NameClient -ORBInitialPort 1050
    

端末ウィンドウの出力は次のようになります。

これで、ネームサービスに対して上の図のように認識される名前空間が作成できました。

サンプルクライアント: 名前空間からのオブジェクトの解決

以下に示すサンプルプログラムは、名前を名前空間から解決する方法を示すものです。「名前の解決」とは、特定のコンテキスト内でその名前に関連付けられているオブジェクトを判別することです。持続ネームサービスを使用する場合は、ネームサービスが停止したときでも、再び解決する必要はありません。一時ネームサービスを使用する場合は、ネームサービスが停止したときに、再び解決する必要があります。

この例で、plans はオブジェクト参照、Personalcalendarschedule の 2 つのオブジェクト参照が含むネーミングコンテキストです。

  1. NameClientResolve.java ファイルを作成し、適切なライブラリをインポートします。

    import java.util.Properties;
    import org.omg.CORBA.*;
    import org.omg.CosNaming.*;
    
    public class NameClientResolve
    {
       public static void main(String args[])
       {
          try {
    

  2. ポートとホストのプロパティを設定します。

    「ネームサービスの起動」の節では、ネームサーバは、ホスト localhost のポート 1050 上で起動されます。次のコードによって、クライアントプログラムにこのポート番号とホスト名を認識させます。

            Properties props = new Properties();
            props.put("org.omg.CORBA.ORBInitialPort", "1050");
            props.put("org.omg.CORBA.ORBInitialHost", "localhost");
            ORB orb = ORB.init(args, props);
    
    

  3. 初期ネーミングコンテキストを取得します。

    次のコードでは、初期ネーミングコンテキストを取得し、それを nc に代入します。

     
            NamingContextExt nc =
              NamingContextExtHelper.narrow(orb.resolve_initial_references(
                "NameService"));
    

  4. 各名前空間を解決します。

    次のコードでは、各名前空間を解決します。

       org.omg.CORBA.Object sched = nc.resolve_str("Personal/schedule");
            org.omg.CORBA.Object cal = nc.resolve_str("Personal/calendar");
            org.omg.CORBA.Object plan = nc.resolve_str("plans");
    
          //finish the try-catch block
          } catch (Exception e) {
            e.printStackTrace(System.err);
            } 
    }
    

  5. NameClientResolve.java を保存し、そのファイルを次のようにコンパイルします。

         javac NameClientResolve.java
    

    続行する前に構文エラーを修正します。

  6. Object Request Broker Daemon が実行され、「サンプルクライアント: 名前空間へのオブジェクトの追加」で説明したクライアントアプリケーションが実行されていることを確認します。

  7. 次のように NameClientResolve を実行します。

         java NameClientResolve -ORBInitialPort 1050
    

このクライアントアプリケーションを実行したときに端末ウィンドウには何も表示されません。オブジェクト参照が解決されたことを確認する必要がある場合は、次のようなテスト用のコードを追加します。

	if (sched == null){
	  System.out.println("Schedule is null");
	}
		
	if (cal == null){
	  System.out.println("Calendar is null");
	}
	 
	if (plan == null){
	  System.out.println("Plans is null");
	}

サンプルクライアント: 名前空間のブラウズ

次のサンプルプログラムでは、名前空間をブラウズする方法を示します。

  1. NameClientList.java ファイルを作成し、適切なライブラリをインポートします。

    import java.util.Properties;
    import org.omg.CORBA.*;
    import org.omg.CosNaming.*;
    
    public class NameClientList
    {
       public static void main(String args[])
       {
          try {
    

  2. 「ネームサービスの起動」の節では、ネームサーバは、ホスト localhost のポート 1050 上で起動されます。次のコードによって、クライアントプログラムにこのポート番号とホスト名を認識させます。

    
            Properties props = new Properties();
            props.put("org.omg.CORBA.ORBInitialPort", "1050");
            props.put("org.omg.CORBA.ORBInitialHost", "localhost");
            ORB orb = ORB.init(args, props);
    
    
    

  3. 初期ネーミングコンテキストを取得します。

            NamingContextExt nc = 
              NamingContextExtHelper.narrow(orb.resolve_initial_references(
                "NameService"));
    
    

  4. ネーミングコンテキスト内のすべてのバインディングを一覧表示します。

    list メソッドは、ネーミングコンテキストに追加されているバインディングをリストします。この場合、最大 1000 個までのバインディングが初期ネーミングコンテキストから BindingListHolder に返されます。残りのバインディングは、BindingIteratorHolder に返されます。

     
            BindingListHolder bl = new BindingListHolder();
            BindingIteratorHolder blIt= new BindingIteratorHolder();
            nc.list(1000, bl, blIt);
    
    

  5. バインディングの配列を取得します。

    次のコードでは、返された BindingListHolder からバインディングの配列を取得します。

            Binding bindings[] = bl.value;
    
    
    

  6. 次のコードでは、バインディングに対してループ処理を行い、名前を出力します。
            for (int i=0; i < bindings.length; i++) {
    
                int lastIx = bindings[i].binding_name.length-1;
    
                // check to see if this is a naming context
                if (bindings[i].binding_type == BindingType.ncontext) {
                  System.out.println( "Context: " + 
                    bindings[i].binding_name[lastIx].id);
                } else {
                    System.out.println("Object: " + 
                      bindings[i].binding_name[lastIx].id);
                }
            }
    
           } catch (Exception e) {
            e.printStackTrace(System.err);
           } 
       }
    }
    

  7. NameClientList.java を保存し、そのファイルを次のようにコンパイルします。

         javac NameClientList.java
    

    続行する前に構文エラーを修正します。

  8. Object Request Broker Daemon が実行され、「サンプルクライアント: 名前空間へのオブジェクトの追加」で説明したクライアントアプリケーションと、「サンプルクライアント: 名前空間からのオブジェクトの解決」で説明したクライアントアプリケーションが実行されていることを確認します。

  9. 次のように NameClientList を実行します。

         java NameClientList -ORBInitialPort 1050
    

端末ウィンドウの出力は次のようになります。

ネームサービスの起動

すべてのチュートリアルで、Object Request Broker Daemon (orbd) を使用します。これには、持続ネームサービスと一時ネームサービスの両方が組み込まれており、J2SE 1.4 以降をダウンロードすれば入手できます。

呼び出し側 (クライアント、ピア、またはクライアントアプリケーション) がリモートオブジェクトのメソッドを呼び出すには、呼び出し側はまずリモートオブジェクトへの参照を取得する必要があります。

リモートオブジェクトがサーバに登録されると、呼び出し側は、そのオブジェクトを名前によって検索して、リモートオブジェクトへの参照を取得できます。これにより、そのオブジェクトのメソッドをリモートから呼び出せます。

ネームサービスの起動方法については、ORBD ドキュメントの 「ネームサービスの起動」を参照してください。

ネームサービスの停止

ネームサービスを停止するには、適切なオペレーティングシステムコマンドを使用します。たとえば、Solaris では kill を使用し、orbd が実行されている DOS ウィンドウでは Ctrl+C キーを使用します。一時ネームサービスの場合は、サービスが終了されると、ネームサービスに登録された名前が消去される場合があります。Java IDL ネームサービスは、明示的に停止されるまで実行されます。

ネームサービスの FAQ

Sun の ORB からサードパーティ製のネームサービスに接続する方法を教えてください。

サードパーティ製のネームサービスが、Interoperable Naming Service (INS) をサポートしている場合は、INS オプションを使用する方法をお勧めします。

Sun ORB をほかのベンダーのネームサービスとともに使用するには、

  1. ホストおよびポート上でサードパーティ製のネームサーバを起動します。

  2. 次の引数を ORB.init() に渡します。
            -ORBInitRef NameService=corbaloc:iiop:1.2@:

    /NameService

orb.resolve_initial_references( "NameService" ) を実行すると、サードパーティ製のネームサービスに接続できるようになります。接続できない場合は、以下のトラブルシューティングに関するヒントを試してください。


Java IDL トップへ