RDiの拡張:メッセージ・キューをモニターするツールの作成
この記事は、PDF、SDA、SEU を置換する IBM ツールキットである Rational Developer for i (RDi) の調整、微調整、および拡張方法を学習したシリーズ記事の最終記事です。私はバージョン 7.5 (最新版) を使用しています。IBM が Remote System Explorer (RSE) に変更を加えたため、私の提供するコードでは旧版のワークベンチでは動作しないのです。現在のワークベンチのバージョンを確認するには、Help/About メニューを選択します。2 回にわたる前回の記事と同様、コードをお見せする前にまず理論から説明します。ここでは、基本事項について説明します。
前回の記事では、RDi インストレーションにビューを追加する方法をお話しました。この記事では、System i のメッセージ・キューをモニターするツールをお伝えして、このプロジェクトを終わりにします。このツールは、ビューにあるすべてのメッセージを表示し、指定した重大度と同じかそれを超える重大度のメッセージがキューに送信された場合に警告を出します。自分のメッセージ・キューをモニターするか、QSYSOPR メッセージ・キューをモニターするか選択できます。
実践: はじめに
まず RDi を起動し、「File/Switch Workspace/Other...」または「File/Switch Workspace.」を選択します。ワークスペース・ディレクトリーを選択するようプロンプトが表示されます。このプロジェクトのワークスペース・ディレクトリーがすでに作成されている場合は、そのディレクトリーを選択して OK を押します。
あるいは、次の手順を行います。RDi を起動します。Select a workspace ダイアログボックスが表示されずに起動する場合は、File/Switch Workspace/Other...を選択します。新しいワークスペース・ディレクトリーを作成するようプロンプトが表示されます。ワークスペースはすべてまとめておくのが良いでしょう。私は、自分のホーム・ディレクトリーに「Workspaces」というわかりやすい名前を付けたディレクトリーに、すべてのワークスペースを保存しています。私と同じようにするのが良いでしょう。ワークスペース・ディレクトリーを作成したら、ワークスペース・ディレクトリーの場所を作成できます。ホーム・ディレクトリーまたは選択した任意のディレクトリーに「Workspaces\RDi Article\」を作成します。
理論: RSE とのリンク
前回の記事では、SWT コンテンツが多少入った新しいビューを作成しました。ユーザーが RDi で何かを選択するたびに通知される通知メカニズムを設定しました。
変更に対応する方法はわかっていますので、ビューを System i のメッセージ・キューにリンクできます。ユーザーが RSE ツリーで成果物の 1 つを選択するまで待ちます。このツリー・エレメントの「root」が求めているクラス (例えば、AS400 クラス) の場合、このマシンのメッセージ・キューからメッセージを抽出し、ビューにこれを表示します。また、忙しい中でも、「Alert ...」チェックボックスをチェックすると、表示したい新規着信メッセージが記録されるリスナーをインストールします。
RSE から Java クラスをいくつか使用できるようにするには、それらのクラスをライブラリー・リストに載せる必要があります。このリストは Java Classpath と呼ばれています。これにより「プラグイン依存関係」というエレガントなメカニズムが動作します。System i ライブラリー・リストとは異なり、すべての依存関係が満たされるまで Eclipse のプログラムは使用できません。したがって、プラグインに他の多数のプラグインに依存していることを告げると、RDi 起動エンジンはすべての要件が満たされたことを確認するまで、アプリケーションを起動しません。アプリケーションが期待通りに動作するようにするには、プラグインを他の多数のプラグインに依存させる必要があります。
実践: RSE とのリンク
MANIFEST.MF ファイル・エディターを閉じている場合は、プロジェクトの「META-INF」ディレクトリーにあるこのファイルをダブルクリックして、エディターを開きます。エディター下部の 2 つ目のタブに「Dependencies」とあります (図 1)。それを開き、依存関係のリストを見ます。 org.eclipse.ui と org.eclipse.core.runtime という 2 つのプラグインに依存関係があるのがわかります。
Eclipse 対応アプリケーションにビューなどの基本的な機能を追加するには、これら 2 つのプラグインが必要です。しかし、さらに依存関係が必要になります。RSE をいじりたくなると、それらの依存関係にアクセスしなければならないためです。「Add...」ボタンを選択して、次の依存関係を追加します。
- com.ibm.etools.iseries.toolbox
- org.eclipse.rse.ui
- org.eclipse.rse.core
- com.ibm.etools.iseries.subsystem.qsys
- com.ibm.etools.iseries.connectorservice
プラグイン名を入力すると、リストがフィルタリングを開始します。例えば、'*toolbox' と入力すると、名前に 'toolbox' が含まれるすべてのプラグインが見えるようになります。
理論: 使用するプラグインの判断方法
自分のアプリケーションで使用できるプラグインを見つけるには、3 つのものを使用する必要があります。それらは、論拠、資料、そしてプラグイン・スパイです。
- まず論拠からはじめましょう。プラグインは RSE および System i を処理するため、プラグイン・リストでこれらの名前を探すのが論理的です。したがって、「Add...」ボタンを選択すると、リストをフィルタリングできます。「*rse*」、「*as400*」、および「*iseries*」などのフィルタを使用して、該当するプラグインのリストを表示しました。これらのプラグインをリストに追加し、「Required Plug-ins」ツリー上のこれらの項目をダブルクリックして、その特定のプラグインのマニフェスト・エディターを表示し、それら自体が依存していたプラグインを調査しました。
- そして、ここで資料です。必ず「Help/Help Contents」メニューから始めます。RSE をベースにしたアプリケーションの構築に使用できる技術資料がほとんどないことがわかります。したがって、Eclipse Web サイトの外に連れ出されます。RSE プロジェクトは現在、「dsdp」プロジェクトのサブプロジェクトで「Target Management」と呼ばれています。Eclipse Web サイト (http://www.eclipse.org/dsdp/tm/) の FAQ を読んだ後、別の Web サイトに導かれ、そこには RSE に関する多数の資料がありました (http://dsdp.eclipse.org/help/latest/index.jsp)。ただし、我々のプラグインは大したことはないので、これらの資料がすべて必要なわけではありません。
最後に使用したのが図 2 に示すようなプラグイン・スパイでした。プラグイン・スパイは Eclipse 3.4.1 で導入されました。ここでは RDi がベースになっていました (プロジェクトに最新版の Eclipse を使用している IBM に栄光あらんことを)。RSEの (または RDi のどこかにある) 任意のオブジェクトを選択し、ALT-SHIFT-F1 を押します。すぐにウィンドウが現れ、手元にあるクラスの情報が表示されます。
この例では、Host という名前の Java オブジェクトがリストで選択されました。RDi がオブジェクトの場所を探し出し、ハイパーリンクを作成します。そのリンクをクリックすると、エディターが開きます。ソースは入っていませんが、パッケージ名など極めて重要な情報が表示されています。ポップアップ・ウィンドウで、ツリーを保持しているビューが org.eclipse.rse.ui プラグインに定義されていることがわかると思います。今後の調査に向けて幸先がよいスタートです。
経験とこだわりをもって論拠、資料、そしてプラグイン・スパイを組み合わせると、正真正銘の RDi ウィザードに近づいていくことでしょう。
実践: アプリケーションの終了
アプリケーションに必要な準備がすべて整ったので、アプリケーションを終了しましょう。コードをすべて入力する代わりに、http://www.remainsoftware.com/en/rdi にあるソースの完全版をご覧ください。Source3 を選択してください。
まず、プロジェクトの「src」ディレクトリーにあるソースを見つけるか、エディター領域の正しいタブをクリックして MessageMonitorView のソースを開きます。ソースがまだ開いている場合は、タブのみ表示されます。クラスで必要なすべての変数への参照ができるか確認してください。エディターのソースを Web のソースを置き換えてください。Web にアクセスできない場合は、図 3 に示す Import ステートメントに入力できます。これらの行により既存の「Import」行が置き換えられます。
また、グローバル変数 (図 4) が必要です。この変数セットをクラス定義のすぐ下にあるソースにコピーします。次の変数を使用します。テキストには変数を表示できるようメッセージが記載されており、キューは AS400 メッセージ・キュー・オブジェクトへの参照で、lastMessage はキューからの最後のメッセージです。
currentHost 変数は選択した RSE ホストを保持し、monitorThread は着信メッセージのキューを監視するために実行依頼するバッチ・プログラムへの参照です。user、alert、および severityInt の各フィールドはモニター動作の微調整に使用する値を格納しています。oldPart および oldSelection は、属性をいじり回した後のビューの再構築に使用します。
テキスト・フィールドに System i からのメッセージを入力するため、いくつかヘルパー・メソッドを作成しましょう。次のメソッドで、確実に我々のテキスト・ウィジェットにアクセスできるようになります。これは SWT 固有のものです。これについては今心配する必要はありません。2009 年 9 月号に掲載されたこのシリーズの前の記事で SWT について簡単にお話ししました。
private void setText(final String message) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
text.setText(message);
}
});
}
以下のヘルパー・メソッドで、停止させたいときにメッセージ・キュー・モニターを停止します。このメソッドをソースのどこかにコピーします。
private void stopMonitor() { C
// Stop the monitor thread
if (monitorThread != null && monitorThread.isAlive()) {
monitorThread.interrupt();
}
}
その間に、ビューを閉じた後にモニターが動作しないよう、dispose() メソッド(以下) にあるこのメソッドを呼び出します。
@Override
public void dispose() {
getSite().getWorkbenchWindow().getSelectionService()
.removePostSelectionListener(this);
stopMonitor();
super.dispose();
}
createPartControl(..) メソッドにはまた、何らかのクリーンアップと小規模な追加が必要です。このメソッドの最終的なコードを図 5 に示します。1、2、および 3 にある選択リスナーが変更されています。テキスト・フィールドのメッセージを印刷するのではなく、変更した属性を保存し、そのメソッドに保存する部分と選択リスナーとともに selectionChanged(..) メソッドを呼び出します。
では、選択する System i オブジェクトに反応するよう selectionChanged() メソッドを完成させましょう (図 6)。1 では、このメソッドに渡される部分と選択オブジェクトが保存されます。メッセージ・モニターの属性を変更する場合、このメソッドを再起動するために、これが後で必要になります。2 では、その部分が空でないことを確認するためさらにチェックが行われます。3 では、ツリーから選択されているか確認するためその選択オブジェクトを確認します。ツリーから選択されている場合、ツリー・パスの最初のセグメントを取得し、Host のインスタンスであるかどうか確認します。firstSegment 変数が現在のホストではないという基準を満たしている場合、ユーザーは新しいホストを選択しています。つまり、前述の stopMonitor() メソッド (5) を呼び出して、モニター・スレッドを停止する必要があります。6 にあるコードは興味深いです。Java から System i にアクセスする場合に重要なクラスである、JTOpen AS400 オブジェクトの入手方法を示しているためです。AS400 オブジェクトがあるため、そのオブジェクトを loadMessageQueue(..) メソッドに渡すことができます。このメソッドは指定したキューから最新の 50 個以下のメッセージを検索し、テキスト・フィールドに配置します。8 で、新着メッセージのメッセージ・キューをモニターするジョブを実行依頼します。
これに Java スレッドを使用していますが、まず、キューからメッセージを読み取り、それらをテキスト・フィールドに配置するメッセージを作成しましょう (図 7)。このメソッドは、メッセージ・キューからメッセージを検索する方法を示しています。1 では、選択した内容を確認し、それにしたがって MessageQueue オブジェクトを作成しています。次に、その setListDirection(..) メソッドを使用して、最新メッセージを最初に送るようキューに指示します。2 では、メッセージがキューにあるかどうか確認しています。メッセージがキューにない場合、これをテキストとして設定し、終了します。3 では、まず load() メソッドにこれらのメッセージを読み込むよう指示するメッセージを取得してから、実際に配列にある結果を取り出すことができます。4 では、取り出されたすべてのメッセージは一時変数に連結されます。最初のメッセージ (setListDirection(..) メソッドを思い出せば実際には最後のメッセージ) が 5 で保存され、新着メッセージがキューに追加された場合に後で調査されます。6 では、結果を示すためテキスト・フィールドが記入されます。何か問題がある場合は、これが 7 で捕そく (MONMSG) され、メッセージ情報の代わりにテキスト・フィールドに入力されます。
大丈夫ですか、ついてきていますか? waitForMessages(..) メソッド (図 8) は最後のメソッドです。このメソッドは、新着メッセージがないかどうかキューをモニターします。これは Java スレッドで行いますが、おおまかにジョブの実行依頼と比較されます (実行対象ジョブが実行可能ジョブ内にラップされているなど)。1 では実行可能インターフェースの必須メソッド (run() メソッド) を実装する内部クラスを作成します。新着メッセージを待機するため、2 つのメソッドを使用できます。メソッド A は MessageQueue クラスの receive(..) メソッドのいずれかを使用します。このメソッドは新着メッセージを待機できますが、メッセージ・キューが:対話式ジョブでロックされていない場合しか使用できないという欠点があります。したがって、代わりにメソッド B を使用することにします。これは以前使用したことがある getMessages(..) メソッドを使用します。システムへの不要なストレスを避けるため、2 で 10 秒間スリープしてから、キューから新着メッセージを読み取ろうとしています。好みで遅延を高い値に設定できますが、モニターの反応が遅くなります。メッセージがキューにある場合、最新のメッセージを取り出します (3)。このメッセージのタイムスタンプが最後に保存したメッセージのものと異なっていると、この新着メッセージ の第 1 レベル・メッセージ・テキストを取得します (4)。
5 で、第 1 レベル・テキストにテキストがある場合、まずビューをリロードします (6)。次に、アラートを受信する場合、このメッセージの重大度が指定の重大度より高いかどうか確認します (7)。前者と後者が両方とも真の場合、新着メッセージを通知するメッセージ・ボックスが表示されます。
作業が完了したら、8 でジョブを終了できますが、この実行可能ジョブをラップするメソッドを再帰的に呼び出し、新しいジョブを作成できます。キャッチャーは、発生するおそれがあるエラーを捕そくし、9 のビューで通知します。この実行可能ジョブの定義は何もしません。最初に実行依頼しなければならないためです。これは 10 で行います。
アプリケーションをテストするには、マニフェスト・エディターから Eclipse アプリケーションを起動して RSE パースペクティブを開きます。次に我々のビュー (Window/Show View/Other..) を開き、「Other」ツリー項目を開きます。我々のビューはここにあるはずです。ビューを開きます。これは非常に重要ですが、RSE ビューからいずれかの System i ノードを選択します。我々のビューは RSE ビューの選択に反応します。
アプリケーションのデプロイ
最後のステップ (であるとお約束します) は、どの RDi 7.5 インストレーションにもインストールできるデプロイ可能なコンポーネントを作成することです。Package Explorer ビューに移動し、プロジェクト名を右クリックします。図 9 に示すように「Export」を選択します。表示されるウィザードで、「Plug-in Development/Deployable Plug-ins and Fragments」を選択し、Next を押します。
「Directory」フィールドで、ディレクトリーを入力し「Finish」 (図 10) を押します。これにより、いとしい我々の製品が入った jar ファイルを含む「Plugins」というディレクトリーが作成されます。
このアプリケーションをインストールするには、RDi をインストールし、eclipse.exe ファイルがある場所に移動します。まだフォルダーがない場合は、このディレクトリーで「dropins」フォルダーを作成し、このフォルダーに jar ファイルを格納します。RDi を再起動し、RSE を開き、Message ビューを開きます。RSE ビューから System i を選択します。ビューが落ち着くまでしばし待って、グリーン・スクリーンに移動して、自分にメッセージを送信します (図 11)。
RDi 拡張の重要性
このシリーズの今回の記事では、RDi の拡張方法をお話ししました。RDi を拡張することは大切です。今日の System i ショップの開発ツールであるからです。また、RDi には多数の逸品が入っていますが、開発努力を緩和するために作った洒落たものすべてを保持できるわけではありません。開発ツールを RDi に組み込むことができるためには、すこぶる有益です。
Eclipse またそれに従う RDi の拡張は簡単ではありません。多くの企業が Eclipse RCP に関する教育を実施しています。4 日間で基本的なことを学習します。Java と Eclipse/RDi の使用経験が多少必要です。2009 年秋には、Industrial-TSI および Eclipse 財団法人がこのトピックに関する一連の教育を運営しています。詳しくは www.eclipse.org をご覧ください。