[ Java & CORBAページへ戻る ]


クライアント側のプログラム手順

クライアント側のプログラム手順は次のとおりです。

  1. ORBの起動
  2. ネーミングサービスの取得
  3. ネーミングサービスからリモートオブジェクトリファレンスを獲得
  4. リモートオブジェクトのメソッドを呼び出し

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の起動ページを参照。

ネーミングサービスの取得

ネーミングサービスの取得には、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型
  2. NamingContextExt型
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オブジェクトについて、以下のように規定しています。また、名前情報は、ネーミングサービスの直下(ルート)に直接置いています。

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();

corbaname URLを使用したプログラム手順

前項の手順では、目的のリモートオブジェクトリファレンスを獲得するために、いったんネーミングサービスのリファレンスを獲得していました。

  1. ネーミングサービスの取得
  2. ネーミングサービスからリモートオブジェクトリファレンスを獲得

獲得したい目的のリファレンスがネーミングサービス中に格納されているコンテクストが分かっている場合、次のサンプルコードのように一発でリモートオブジェクトリファレンスを獲得するコードを記述することができます。

    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
-ORBInitRef NameService=corbaloc:iiop:1.2@nameserver:5555/NameService


オブジェクトリファレンスの獲得方法

CORBAでは、リモートオブジェクトのリファレンスを獲得する方法として以下のものがあります。

  1. CORBAネーミングサービス
    オブジェクトに抽象的な別名を与え、検索・取得を行う。実装の規定が弱く、異なるCORBA製品間で接続不能な場合がある。
  2. インターオペラブル・ネーミングサービス
    1.の問題点を解消する新しいネーミングサービス。異なるCORBA製品間で接続できるようになった。
  3. ベンダー独自の方法
    例えばVisiBroker for Javaにおけるスマートエージェント。他のCORBA製品からは当然利用できない。
  4. IOR(Interoperable Object Reference)を使用する
    分散したORBシステム内で、オブジェクトを一意に特定するために必要な情報(名前or識別子)。様々な種類のORB製品間でオブジェクトリファレンスを受け渡す共通のフォーマット。文字列で表記され、主としてファイルを介して受け渡される。
  5. リモートオブジェクトのメソッドパラメータで転送する
    オブジェクトリファレンスは、引数や戻り値で受け渡すことができる。あらかじめリモートオブジェクトのリファレンスを一つだけ知っていれば、そのオブジェクトから芋づる式にリファレンスを取得可能。
  6. CORBAトレーディングサービス

[ Java & CORBAページへ戻る ]


This page is written by Toru TAKAHASHI.(torutk@02.246.ne.jp)