[ Java & CORBAページへ戻る ]

Title Logo of Server Side

IDLは、リモートに存在するオブジェクトへメッセージを送る(オペレーションを起動する)ためのインタフェースです。CORBAにおけるORBはリモートへのオペレーションを要求するクライアントと、実際にオペレーションの処理を実行するCORBAオブジェクトとの間を結ぶ仲介人(ブローカ)です。

サーバ側にはCORBAオブジェクトがあります(あるようにクライアントからは見えます)。CORBAオブジェクトは、IDLで定義されオブジェクトリファレンスで識別されます。クライアントからのCORBAオブジェクトに対するオペレーション要求は、ORBを通してサーバへ送られ、POAによってサーバントへ伝送(ディスパッチ)され、サーバントのメソッドが起動されます。また、サーバ上にはPOAマネージャ、サーバント・マネージャといった役者がいます。このようにサーバには、たくさんの登場人物がいるので最初は混乱してしまいます。

ここでは、簡単なIDLのCounterインタフェースを持つCORBAオブジェクトをサーバとして提供するプログラムを作成していきながら、サーバ側のCORBAプログラミングを見ていきましょう。


IDLの作成とコンパイル

IDLインタフェースの記述 - Counter.idl -

簡単なカウンタは、4つのオペレーションを定義します。Javaのパッケージ規約に合わせてmoduleを定義するために、#pragma prefixを利用してモジュールのネストを避けています。

Counter.idl
#pragma prefix "idl.learn.torutk.java_conf.gr.jp"

module counter_ex1
{
    interface Counter
    {
        void increment();
        void decrement();
        void setCount(in long aCount);
        long getCount();
    };
};

このファイルを、開発ディレクトリ(D:\develop\ex1)に置きます。

開発ディレクトリの内容(1)
d:\develop\ex1\
Counter.idl

IDLコンパイラの実行 - Javaソースファイル生成 -

IDLコンパイラを実行し、IDLファイルからJavaのスタブ、スケルトンファイルを生成します。

ここでは、あらかじめidl2java.batを作成したものを実行しています。idl2java.batについては、OpenORB TipsページのIDLコンパイラ項をご覧下さい。

IDLコンパイラ実行
D:\develop\ex1>idl2java Counter.idl
OpenORB IDL Compiler / (c) 2000-2001 Exolab.org
compile : Counter.idl

D:\develop\ex1>

IDLコンパイラ実行後の開発ディレクトリの内容は以下のとおりです。generatedというディレクトリの下に、パッケージ名に対応するディレクトリが作成され、Javaのソースファイルが生成されます。

開発ディレクトリの内容(2)
d:\develop\ex1\
Counter.idl
d:\develop\ex1\generated\jp\gr\java_conf\torutk\learn\idl\counter_ex1\
Counter.java
CounterHelper.java
CounterHolder.java
CounterOperations.java
CounterPOA.java POA継承方式で使用
CounterPOATie.java POA委譲方式で使用
_CounterStub.java

IDLを実装するクラス -サーバント-

POA

IDLを実装(実現)するクラスとしてSimpleCounter.javaを記述します。IDLを実装するには、次の2つの方法があります。

  1. POAの継承方式(Inheritance-Based Implementation)
  2. POAの委譲方式(Delegation-Based Implementation)

POA継承方式 - SimpleCounter.java -

POA継承方式で実装する場合は、CounterPOAクラスを継承し、IDLで定義したオペレーションのJavaマッピングであるinterface CounterOperationsで定義されるメソッドを実装します。

SimpleCounter
package jp.gr.java_conf.torutk.learn.idl.counter_ex1;

public class SimpleCounter extends CounterPOA  {
    private int count = 0;
    
    public void increment() {
        count++;
    }
    public void decrement() {
        count--;
    }
    public void setCount(int aCount) {
        count = aCount;
    }
    public int getCount() {
        return count;
    }   
}// SimpleCounter

SimpleCounter.javaは、開発ディレクトリの下に直接パッケージ名に対応するディレクトリを作成して置くことにします。(srcというディレクトリを作ってもよいでしょう)

開発ディレクトリの内容(3)
d:\develop\ex1\
Counter.idl
d:\develop\ex1\jp\gr\java_conf\torutk\learn\idl\counter_ex1\
SimpleCounter.java IDLを実装するクラス
d:\develop\ex1\generated\jp\gr\java_conf\torutk\learn\idl\counter_ex1\
Counter.java IDLコンパイラで生成されたファイル
CounterHelper.java
CounterHolder.java
CounterOperations.java
CounterPOA.java
CounterPOATie.java
_CounterStub.java

CORBAオブジェクトを起動するサーバプログラムの記述

CORBAオブジェクトを生成し、クライアントからのリクエストに応答できるようにセットアップを行うサーバ・プログラムを記述します。サーバは以下の作業を実行します。

  1. ORBの起動
  2. RootPOAの取得
  3. サーバントの生成
  4. サーバントをPOAに結び付け
  5. ネーミングサービスの取得
  6. ネーミングサービスにサーバントを登録
  7. POAマネージャの取得と活性化
  8. クライアントからのリクエストを待つイベントループ実行
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;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManager;

public class Server {
  public static void main(String[] args) {
    ORB orb = ORB.init(args, null);
ORBの起動
    org.omg.CORBA.Object objPoa = null;
    POA rootPoa = null;
    try {
      objPoa = orb.resolve_initial_references("RootPOA");
      rootPoa = POAHelper.narrow(objPoa);
    } catch (org.omg.CORBA.ORBPackage.InvalidName e) {
      System.out.println("RootPOAの名前が正しくありません");
      System.exit(1);
    }

    if (rootPoa == null) {
      System.out.println("POAのオブジェクト参照が取得できません");
      System.exit(1);
    }
RootPOAの取得(注1)
    // Servantの作成
    SimpleCounter counter = new SimpleCounter();
    org.omg.CORBA.Object counterRef = null;
    try {
      rootPoa.activate_object(counter);
      counterRef = rootPoa.servant_to_reference(counter);
    } catch (Exception e) {
      System.out.println("Counterオブジェクト作成でエラー");
      e.printStackTrace();
      System.exit(1);
    }
サーバントの生成
サーバントをRootPOAに結び付け
サーバントのオブジェクトリファレンス作成
    // ルートネーミングコンテクストオブジェクトの取得
    org.omg.CORBA.Object objNs = null;
    try {
      objNs = orb.resolve_initial_references("NameService");
    } catch (org.omg.CORBA.ORBPackage.InvalidName e) {
      System.out.println("ネームサービスの名前が正しくありません");
      e.printStackTrace();
      System.exit(1);
    }
    NamingContext rootNameContext =
      NamingContextHelper.narrow(objNs);
    if (rootNameContext == null) {
      System.out.println("ルートネーミングコンテクストが空です");
      System.exit(1);
    }
ネーミングサービスの取得
    // NamingServiceへの登録
    // カウンタアオブジェクトのネームコンポーネント作成
    NameComponent[] counterNameComponent = new NameComponent[1];
    counterNameComponent[0] =
        new NameComponent("TheCounter", "Object");

    try {
      rootNameContext.rebind(counterNameComponent, counterRef);
    } catch (Exception e) {
      System.out.println("ネームサービス登録でエラー発生");
      e.printStackTrace();
      System.exit(1);
    }  
ネーミングサービスへの登録
    // POAマネージャの活性化
    POAManager poaManager = rootPoa.the_POAManager();
    try {
      poaManager.activate();
      System.out.println("activated POA Manager");
    } catch (org.omg.PortableServer.POAManagerPackage.
             AdapterInactive e) {
      System.out.println("POAマネージャの活性化に失敗");
      e.printStackTrace();
      System.exit(1);
    }
POAマネージャの取得と活性化
    // クライアントからの要求の待ち合わせ
    System.out.println("Waiting request from client");
    try {
      orb.run();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
} // Server
クライアントからの要求待ちイベントループ

ORBの起動

ORBの起動ページを参照。

RootPOAの取得

POA(Portable Object Adapter)は、オブジェクトアダプタの一種です。オブジェクトアダプタは、ORBからリクエストを受け、リクエストを処理するメソッドを呼びだします。
POAは複数用意することができます。RootPOAと呼ばれるPOAをルートとした階層構造を取ります。POAごとにポリシーと呼ばれる様々な挙動を指定できます。ただし、RootPOAだけは既にポリシーが決められています。

注1) SunのJDK1.4標準搭載CORBAであるJavaIDLでは、POAHelperが含まれていません。そこで、

      objPoa = orb.resolve_initial_references("RootPOA");
      rootPoa = (POA)objPoa;

と単にキャストします。

CORBAオブジェクト

CORBAオブジェクトとは、IDLで定義されたインタフェースを持つ仮想的なオブジェクトです。IDLで定義されたインタフェースへの要求は、実際にはサーバントと呼ばれるプログラミング言語で記述されたコードによって実行されます。

サーバントの生成

サーバントはIDLで定義されたインタフェースを持つCORBAオブジェクトの実体(実装)で、Javaの場合はPOA継承方式の場合はPOAを継承したクラスのインスタンスを生成します。

CORBAオブジェクトとサーバントの対応付け

ORBは、CORBAオブジェクトに対するオペレーション要求を受け取ると、POAにディスパッチします。POAは、サーバントを管理しているので、どのサーバントを起動すればよいかを調べて呼び出します。そこで、サーバントを生成した後はサーバントをPOAに登録します。

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

オブジェクトをクライアントから呼び出すためには、クライアントがそのオブジェクトリファレンスを何らかの方法で獲得できるようにする必要があります。ここでは、ネーミングサービスを使用する場合のサーバ側のコーディングを示しています。他の方法については、Client Sideページのオブジェクトリファレンスの獲得の項を参照。

ネーミングサービスにサーバントを登録

ネーミングサービスにサーバントを登録します。ネーミングサービスは、名前情報とCORBAオブジェクトのリファレンスを対応付けて管理しています。名前情報は木構造となっており、大量の名前情報を管理できる構造となっています。名前情報を表すのにNameComponentクラスが使われます。

NamingContextExtを使った場合

Interoperable Naming Serviceで追加されたNamingContextExt型を使うとコーディングが簡単になります。

NamingContext型を使用 NamingContextExt型使用
NamingContext rootNameContext =
  NamingContextHelper.narrow(objNs);
NamingContextExt rootNameContext =
  NamingContextExtHelper.narrow(objNs);
NameComponent[] counterNameComponent =
  new NameComponent[1];
counterNameComponent[0] =
  new NameComponent("TheCounter", "Object");
NameComponent[] counterNameComponent = 
  rootNameContext.to_name("TheCounter.Object");

POAマネージャの取得と活性化

POAマネージャは、クライアントからの要求をPOAへ結びつける役割を持ち、クライアントからの要求をキューイングしたり転送したり破棄したりします。POAマネージャ自体は、POAの作成時に暗黙的に作成されます。POAマネージャjの初期状態は、クライアントからの要求をPOAには転送せずにキューイングするHOLDING状態なので、activateメソッドを呼ぶことによってクライアントからの要求をPOAに転送するACTIVE状態へ遷移させます。

クライアントからのリクエストを待つイベントループ実行

クライアントからの要求を受け付けるためのイベントループを実行します。


サーバプログラムの実行

サーバプログラムを実行するには、先にネーミングサービスを実行している必要があります。サーバプログラムを実行する際に、先に起動したネーミングサービスのオブジェクトリファレンス情報をコマンドラインオプションで指定します。

ネーミングサービスの指定 -ORBInitRef NameService=<オブジェクトURL>

ネーミングサービスの起動については、使用しているCORBA製品によって異なります。OpenORBの提供するネーミングサービスについては、OpenORB TipsページのNaming Service項を参照。

サーバプログラム実行
D:\develop\ex1\classes>java jp.gr.java_conf.torutk.learn.idl.counter_ex1.Ser
ver -ORBInitRef NameService=corbaloc:iiop:1.2@nameserver:5555/NameService 

[ Java & CORBAページへ戻る ]


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