プロジェクト

全般

プロフィール

Java CORBA Counterプログラム

参考 [#107]

はじめに

JavaでCORBAを使った入門レベルのプログラムとして、カウンターを作ります。
環境は次のとおりです。

JDK Java SE Development Kit 8u241
CORBA JacORB 3.9
開発環境 NetBeans IDE 8.2
実行環境 Windows 10

開発環境の準備

NetBeansのライブラリ管理にJacORBを設定

以下の記述でパスの部分は、JacORB 3.9 のバイナリが、C:\Program Files\Java\jacorb-3.9\ に展開されていた場合の例です。

  • NetBeans IDEの[ツール]メニュー > [ライブラリ]で、「Antライブラリ・マネージャ」画面を開き、[新規ライブラリ]で[JacORB 3.9]の名前を指定、[クラスパス]に次を追加
    C:\Program Files\Java\jacorb-3.9\lib\jacorb-3.9.jar
    C:\Program Files\Java\jacorb-3.9\lib\idl.jar
    C:\Program Files\Java\jacorb-3.9\lib\jacorb-omgapi-3.9.jar
    C:\Program Files\Java\jacorb-3.9\lib\slf4j-api-1.7.14.jar
    C:\Program Files\Java\jacorb-3.9\lib\slf4j-jdk14-1.7.14.jar
  • [Javadoc]に次を追加
    https://jacorb.github.io/JacORB/

AntLibraryManager-1.png

開発の手順

  • IDLファイルの作成
  • サーバー・プログラムの作成
  • クライアント・プログラムの作成
  • 実行

NetBeansでは、3つのプロジェクトを作成します。

  1. IDLから生成されるクラスから成るライブラリプロジェクト
  2. CORBAサーバーのアプリケーションプロジェクト
  3. CORBAクライアントのアプリケーションプロジェクト

Counter分散プログラムの作成

IDLから生成されるクラスから成るライブラリプロジェクト

プロジェクトの作成

IDLファイルは、複数のプログラム(NetBeansプロジェクト)から利用します。ソースコードの一元管理の観点からIDLファイルのコピーを各プロジェクトに持たせるのは不適切です。そこで、IDLファイルを独立したNetBeansプロジェクトで保持し、IDLファイルから生成されるJavaクラス群をライブラリとして各プログラムから利用する構成とします。

  • NetBeansの[ファイル]メニュー > [新規プロジェクト] > [Java] > [Javaクラスライブラリ] で、プロジェクト名を"CounterIdl"として作成

IDLファイルの作成

  • ソースパッケージ(srcフォルダ)の下に、IDLファイルをファイル名"Counter.idl"で作成
    注)NetBeans にはファイル・タイプでIDLがなかったので、[その他] > [空のファイル] で作成
  • Counter.idl
    interface Counter {
        void increment();
        void decrement();
        void setCount(in long count);
        long getCount();
    };
    

IDLでは、型(interface)は名前空間(module)の配下に作成します。IDL to Javaマッピングでは、IDLのmoduleがJavaのpackageに対応します。
例えば、javaのパッケージ com.torutk.count にIDLで定義したインタフェースを配置したい場合、module定義を使うと次のようなIDLファイルになります。

module com {
    module torutk  {
        module count {
            interface Counter {
                void increment();
                // ...
            };
        };
    };
};

このようにmoduleを多段に定義するとmoduleのネストが深くなりコードが読みにくくなるので、JacORBのIDLコンパイラのオプションj2packageを指定してJavaのパッケージに対応させるようにしています。

ただし、CORBAのインタフェースリポジトリを扱う場合、タイプIDが、ネストしたmoduleを定義した場合と、j2packageオプションを指定した場合で若干異なる点があるのに留意が必要となります。(JacORB Programming Guideの10.4節参照)

NetBeans のビルドにIDLコンパイルを追加

IDLコンパイラはJacORBに付属していますが、NetBeansのビルドプロセスにIDLファイルからJavaソースファイルの生成を組み込んでおくと便利なので、AntタスクでIDLコンパイルを実行できるようにします。

  • build.xml に追記
        <target name="-pre-compile" depends="idl-compile"/>
        <target name="idl-compile">
            <taskdef name="idlc" classname="org.jacorb.idl.JacIDL" classpath="${libs.JacORB_3.9.classpath}"/>
            <idlc srcdir="${src.dir}" destdir="${build.generated.sources.dir}/idl">
                <i2jpackage names=":com.torutk.count"/>
            </idlcompile>
        </target>
    

NetBeansでプロジェクトをビルドするときに、IDLファイルからJavaソースファイルの生成を実行します。
Javaのソースファイルを生成するタイミングは、Javaソースファイルのコンパイル前にしたいので、-pre-compileターゲットをオーバーライドします。
IDLコンパイルを実行することを明示するため、新規にターゲットild-compileを定義し、-pre-compileターゲットのdepends属性でidl-compileを指定します。
ターゲットidl-compileでは、JacORBが提供するAntタスク org.jacorb.idl.JacIDL を指定したタスクidlcを定義してこれを実行します。

taskdefのclasspathで指定しているプロパティ(libs.JacORB_3.9.classpath)は、nbproject/build-impl.xmlの-init-userターゲットで読み込むプロパティファイルに定義されています。そのため、project直下にtaskdefを定義すると、まだターゲットが実行される前にtaskdefのclasspathが評価され、未定義のためクラスが見つからないという事象が発生します。

i2jpackageは、IDLのmodule定義(名前空間)をJavaのパッケージに置き換えるパターンを定義します。コロン(:)の左が置き換え前のIDL module名で右が置き換え後のjavaパッケージ名です。左側を空にすると、moduleを定義していないIDLをjavaでパッケージを付けることができます。

続いて、idlファイルがビルド出力ディレクトリにコピーされないよう次の修正をします。
  • project.properties
    - build.classes.excludes=**/*.java,**/*.form
    + build.classes.excludes=**/*.java,**/*.form,**/*.idl
    

ビルド

プロジェクトをビルドすると、次のようにIDLコンパイルされたソースファイル、クラスファイル、JARファイルが生成されます。

CounterIdl
  +-- build
  |     +-- classes
  |     |     +-- com
  |     |           +-- torutk
  |     |                 +-- count
  |     |                       +-- Counter.class, CounterHelper.class, CounterHolder.class, CounterOperations.class,
  |     |                           CounterPOA.class, CounterPOATie.class, _CounterStub.class
  |     +-- generated-sources
  |           +-- idl
  |                 +-- com
  |                       +-- torutk
  |                             +-- count
  |                                   +-- Counter.java, CounterHelper.java, CounterHolder.java, CounterOperations.java,
  |                                       CounterPOA.java, CounterPOATie.java, _CounterStub.java
  +-- dist
  |     +-- CounterIdl.jar
  +-- src
        +-- Counter.idl

CORBAサーバーのアプリケーションプロジェクト

  • [ファイル]メニュー > [新規プロジェクト] > [Java] > [Javaアプリケーション]を選択し[次>]ボタン
    プロジェクト名を[CounterServer]として作成
  • プロジェクトのプロパティを開き[ライブラリ]で、JacORB 3.9ライブラリとCounterIdlプロジェクトを追加

ソースファイルの作成

IDLで定義したインタフェースを実装するCORBAオブジェクトを実装します。
ソースパッケージ(srcフォルダ)の下に パッケージ com.torutk.count.serverを作成し、SimpleCounter.javaを作成します。

  • SimpleCounter.java

CORBAを初期化し、CORBAオブジェクトを生成し、ネーミングサービスに登録するサーバープログラムを作成します。
ソースパッケージ(srcフォルダ)の下にMain.javaを作成します。

  • Main.java

実行設定

  • プロジェクトのプロパティを開き[実行]で次を設定
    • 引数: -ORBInitRef NameService=corbaloc::localhost:3626/NameService
    • VMオプション:
      -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB
      -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton

引数には、ネーミングサービスへ接続するための情報を指定します。ここでは、同じマシン上(localhost)に、ポート番号3626でネーミングサービスを起動しているものとし、そのネーミングサービスに接続する設定です。

VMオプションには、Javaの標準APIで提供するCORBAではなく、サードパーティライブラリのCORBAを使用するための設定を記述します。

CORBAクライアントのアプリケーションプロジェクト

  • [ファイル]メニュー > [新規プロジェクト] > [Java] > [Javaアプリケーション]を選択し[次>]ボタン
    プロジェクト名を[CounterClient]として作成
  • プロジェクトのプロパティを開き[ライブラリ]で、JacORB 3.9ライブラリとCounterIdlプロジェクトを追加

ソースファイルの作成

CORBAを初期化し、ネーミングサービスからCORBA参照を取得し、サーバーのCORBAオブジェクトのメソッドを呼び出すクライアントプログラムを作成します。
ソースパッケージ(srcフォルダ)の下に パッケージ com.torutk.count.client を作成し、その下にMain.javaを作成します。

  • Main.java

実行設定

  • プロジェクトのプロパティを開き[実行]で次を設定
    • 引数: -ORBInitRef NameService=corbaloc::localhost:3626/NameService
    • VMオプション:
      -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB
      -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton

実行

ネーミングサービスの実行

JacORBの実行ディレクトリには、ネーミングサービスを実行するバッチファイル・スクリプトファイルが用意されています。
サーバーやクライアントプログラムから接続するポート番号を明示的に指定して実行します。

D:\work\counter> ns -DOAPort=3626
WARNING Warning - unknown codeset (MS932) - defaulting to ISO-8859-1
WARNING Warning - unknown codeset (MS932) - defaulting to ISO-8859-1
INFO Initialising ORB with ID:
INFO InterceptorManager started with 0 Server Interceptors, 0 Client Interceptors and 1 IOR Interceptors
INFO NS up

サーバーの実行

NetBeans上から実行します。

出力ウィンドウに次が表示されます。

run:
INFO Initialising ORB with ID: 
INFO InterceptorManager started with 0 Server Interceptors, 0 Client Interceptors and 1 IOR Interceptors
INFO oid: 00 01 24 48 4D 05 15 02 32 36 10 06 30 46 38 14 14 1B 48 4C ..$HM...26..0F8...HL1B                                                          .object is activated
INFO Using server ID (1160238886) for transient POA
INFO ClientConnectionManager: created new ClientGIOPConnection to 127.0.0.1:3626 (de0a01f)
INFO Connected to 127.0.0.1:3626 from local port 51483
Waiting request from client

クライアントの実行

NetBeans上から実行します。

出力ウィンドウに次が表示されます。

run:
Server Counter = 0
Server Counter = 1
ビルド成功(合計時間: 1秒)

クリップボードから画像を追加 (サイズの上限: 1 GB)