Hitachi

Cosminexus V11 アプリケーションサーバ 機能解説 拡張編


9.4.2 TPBrokerV5を除くORBクライアントアプリケーションの作成手順

TPBrokerV5を除くORBクライアント(CORBA2.1準拠のCORBAクライアントまたはTMS-4V/SP Object Access,TPBrokerV3)からEJBアプリケーション(Cosminexus)のEJBをCORBA通信によって呼び出す方式を次の図に示します。

図9‒4 ORBクライアントからのEJB呼び出し

[図データ]

この方式ではIDLとして次のデータ型/データ定義だけ使用できます。

long,unsigned long,string,sequence<octet>,struct

〈この項の構成〉

(1) インタフェース設計手順

アプリケーションサーバ側の通信インタフェースはEJBのリモートインタフェースとして,ORBクライアント側の通信インタフェースはCORBAのIDLとしてそれぞれ記述する必要があります。

リモートインタフェースおよびIDLの設計手順の概略は次のようになります。

  1. インタフェースのベースとなるIDL定義を作成

  2. IDLに合わせてEJBのリモートインタフェースを作成

  3. ctmjava2idlコマンドの出力によって,IDLの構造体メンバの並びを補正

  4. string,sequence<octet>,structのIDL定義を変更

各手順の詳細について説明します。

(a) インタフェースのベースとなるIDL定義の作成

インタフェースのベースとなるIDL定義は,次の注意事項を考慮して作成してください。

  • out/inout引数は使用できません(戻りデータとしてはリターン値を使用します。戻りデータが複数ある場合はstructにまとめてください)。

  • ユーザ例外は使用しないでください。

  • structのメンバはlong,unsigned long,string,sequence<octet>だけを使用してください。

  • #pragmaは使用しないでください。

(b) リモートインタフェースの作成

ベースとなるIDL定義の作成後,それを基にEJBのリモートインタフェースを作成します。

このとき,対応するメンバ名は,IDLとリモートインタフェースで同じにしてください。

また,IDLのmoduleは,Javaのパッケージに対応します。

サポートするデータ型のマッピングを次の表に示します。

表9‒9 IDLからリモートインタフェースへのデータ型のマッピング

データ型

IDL

リモートインタフェース

整数

long

int

unsigned long※1

文字列

string※3

byte[]※2

バイナリ

sequence<octet>※3

byte[]

構造体

struct

class(Serializableを実装)

注※1

Javaにはunsignedに対応する型が存在しません。そのためIDLのunsigned longはlongと同じ型として扱われます。

注※2

JavaのStringはIDLのWstringに対応するため,リモートインタフェースではbyte[]を使用してください。

注※3

IDL上のstring/sequence<octet>に対して最大長を指定できます。ただしJava側ではすべて可変長データとして扱われます。

IDLの記述例

struct AAA {
  long longData;
  string<4> strData;
  unsigned long ulongData;
  sequence<octet> octseqData;
};

リモートインタフェースの記述例

public class AAA
  implements java.io.Serializable {
  public int longData;
  public byte[] strData;
  public int ulongData;
  public byte[] octSeqData;
};

(c) ctmjava2idlコマンドの出力によって,IDLの構造体メンバの並びを補正

EJBに対するCORBA通信では,IDLのstruct内のメンバの並びをJavaのSerializableの仕様に沿った形で並べ替える必要があります。ここで,IDL上での適正なstructメンバの並びを確認するために,ctmjava2idlコマンドを使用します。

ctmjava2idlコマンドは,EJBのリモートインタフェースをIDL定義へ変換するコマンドです。

<例:表9-9の例で示した構造体AAAを使用した場合の手順>
  1. AAAに対応するJavaソースプログラム(AAA.java)をコンパイルする。

    % javac AAA.java

  2. 生成されたクラスファイル(AAA.class)をctmjava2idlコマンドに適用する。

    % ctmjava2idl AAA.class

  3. 標準出力に出力されたIDL定義を基に,ベースとなるIDLを修正する。

ctmjava2idlコマンドによるIDLの構造体メンバの並びの変更例を,次の図に示します。

図9‒5 ctmjava2idlコマンドによるIDLの構造体メンバの並びの変更の例

[図データ]

参考

structメンバの並べ替えルール

リモートインタフェース上でのデータ型とメンバ名によって順番が決定されます。

  1. intのメンバはbyte[]のメンバより先に並びます。

  2. int型のメンバ同士では,メンバ名によって文字列順に並びます。

  3. byte[]型のメンバ同士では,メンバ名によって文字列順に並びます。

  4. int型のメンバ同士,および,byte[]のメンバ同士はctmjava2idlコマンドで出力したIDL定義のstructに定義されている順番に並べます。

(d) string,sequence<octet>,structのIDL定義を変更

ORBクライアントからのEJB呼び出しではstring,sequence<octet>,structのデータを特定の形式の構造体に変更して扱う必要があります(long/unsigned longはそのまま)。

ORBクライアント側送信データの形式

ORBクライアント側からEJBに対し送信するデータに対しては,次のような形式に変更します。

(例:「図9-6 EJB向けのIDLへの変換例」のinvokeメソッドのin引数StringValue,OctSeqValue,AAARequest)

struct 任意の構造体名 {
  long VALUE_TAG;
  string REPOSITORY_ID;
  データ本体;
}

ただしstruct内のstring,sequence<octet>メンバに対しては,上記構造体を使用する代わりに,次の構造体を各データの直前に配置するようにしてください。

(例:「図9-6 EJB向けのIDLへの変換例」のAAARequestのメンバtag1およびtag2)

struct ValueTag {
  long VALUE_TAG;
  string REPOSITORY_ID;
}

ORBクライアント側のプログラム実装では,VALUE_TAG/REPOSITORY_IDに値を設定する必要があります。

ORBクライアント側受信データの形式

戻り値としてのstructそのものに対しては,送信データと同様の形式に変更します。

(例:「図9-6 EJB向けのIDLへの変換例」のAAAReply)

struct 任意の構造体名 {
  long VALUE_TAG;
  string REPOSITORY_ID;
  データ本体;
}

struct内のメンバの内,最初に出現したstring,sequence<octet>に対して次の構造体をデータの直前に配置してください。

(例:「図9-6 EJB向けのIDLへの変換例」のAAAReplyのメンバtag1)

struct ValueTag {
  long VALUE_TAG;
  string REPOSITORY_ID;
}

二つ目以降に出現したstring,sequence<octet>メンバに対しては,次の構造体を各データの直前に配置してください。

(例:「図9-6 EJB向けのIDLへの変換例」のAAAReplyのメンバtag2 。手前にsequence<octet>のメンバがあるため,ValueTagでなくReplyTagになる。)

struct ReplyTag {
  long VALUE_TAG;
  long INDIRECTION_TAG;
  long INDIRECTION;
}

受信データとしては,VALUE_TAG/REPOSITORY_ID/ INDIRECTION_TAG/INDIRECTIONの値は無視してください。

IDLの変更例

IDLの変更例を次の図に示します(対応するリモートインタフェースも示します)。

図9‒6 EJB向けのIDLへの変換例

[図データ]

(2) 通信処理に関するプログラム実装

プログラム実装として追加すべき処理について説明します。

(a) ORBクライアント送信データでのVALUE_TAG,REPOSITORY_ID設定

string/sequence<octet>/structに関しては,ORBクライアント側からEJBに対し送信する場合には,送信前にデータ本体以外に,VALUE_TAG,REPOSITORY_IDにも値を設定してください。

VALUE_TAG

常に固定値(0x7fffff02)を設定してください。

REPOSITORY_ID
string/sequence<octet>の場合

固定値(“RMI:[B:0000000000000000”)を設定してください。

structの場合

リポジトリIDはstructの名称・構造により異なってくるため,ctmjava2idlコマンドの出力結果からリポジトリIDを取得してください。ctmjava2idlコマンド出力結果の「#pragma ID クラス名」の行,“RMI:〜”部分がリポジトリIDです。次の図の場合,"RMI:AAA:D7A0D1FA6D5A19A3:86B2BC1FA4F5362A"がAAAのリポジトリIDになります。

図9‒7 リポジトリIDの例

[図データ]

また,COBOLのマップファイルでREPOSITORY_ID部の長さを指定する場合,次の値を指定してください。

string/sequence<octet>の場合

23文字以上

(固定値(“RMI:[B:0000000000000000”)の文字数以上)

structの場合

ctmjava2idlコマンドの出力結果から取得したリポジトリIDの文字数以上

ORBクライアント側受信データに関しては,データ本体以外の情報(VALUE_TAGなど)は無視してください。

図9-6 EJB向けのIDLへの変換例」のXXX::invoke()に対応したVALUE_TAG,REPOSITORY_IDの設定例を次に示します。

図9‒8 VALUE_TAG,REPOSITORY_IDの設定例(COBOL)

[図データ]

図9‒9 VALUE_TAG,REPOSITORY_IDの設定例(Java)

[図データ]

図9‒10 VALUE_TAG,REPOSITORY_IDの設定例(C++)

[図データ]

(b) IDLのstringに対するEJB上での取り扱い

EJB側では文字列をbyte[]として送受信するため,必要に応じてJavaのStringとの相互変換をしてください。

受信したbyte[]をそのままJavaのStringに変換した場合,終端に’¥0’が付加された状態になるため,文字列長を取得すると,文字数が1文字分多い値が得られます。必要であれば終端の’¥0’を削除してください。

byte[]に文字列を設定する場合は,文字列の終端としてプログラムで明示的に’¥0’を付加してください。’¥0’で終了していないデータをIDLのstringとして返した場合,受信側でエラーになるおそれがあります。

IDLでstringの最大長を指定している場合,終端文字’¥0’はその最大長に含まれないため,byte[]のサイズとしては最大長+1を確保してください。

(c) EJBでのNULL

Javaからの戻り値のclass/byte[]に,nullオブジェクトを使用しないでください。

(3) 文字列化オブジェクトリファレンスの生成

ORBクライアントからORBゲートウェイに接続するIOR文字列ファイルの取得手順について説明します。

  1. ctmstartgwコマンドに-CTMIDLConnectオプションを指定してORBゲートウェイを開始します。

  2. ORBクライアントから呼び出すJ2EEアプリケーションをデプロイしてから開始します。

  3. ctmgetiorコマンドを実行し,IOR文字列ファイルを取得します。

なお,IOR文字列が記述されたファイルの再生成については,次の点に注意してください。

EJBのリモートインタフェースとCORBAネーミングサービスの登録名称,サーバのIPアドレス,または,ORBゲートウェイの受信ポート番号を変更しない場合

再生成する必要はありません。

ctmstartgwコマンドに「-CTMIDLConnect 0」を指定してORBゲートウェイを開始すると,ctmgetiorコマンドによってIOR文字列は取得できませんが,アプリケーションやORBゲートウェイの開始時間を短縮できます。

EJBのリモートインタフェース,CORBAネーミングサービスの登録名称,サーバのIPアドレス,または,ORBゲートウェイの受信ポート番号を変更する場合

文字列化オブジェクトリファレンスの生成手順1からやり直す必要があります。