Server Access Kit
以下のトピックでは、Info*Engine Server Access Kit (SAK) について説明し、SAK アプリケーションの例を示します。
サーバーアクセスキットについて
Info*Engine の Service Access Kit (SAK) を使用すると、Java アプリケーションで Info*Engine タスクを実行し、それらのタスクにパラメータを渡し、それらの結果を検査できます。タスクは、Java クラスとしてインスタンス化されます。タスクインスタンスを構築したら、タスクオブジェクト上のメソッドを呼び出し、タスクが呼び出される前に、パラメータを追加して実行オプションを作成できます。パラメータを追加してオプションを作成すると、タスクの invoke メソッドを呼び出してタスクを実行できます。タスクが完了すると、タスクオブジェクト上のメソッドを呼び出して、タスクが生成したグループオブジェクトを取得できます。
SAK から使用可能な Info*Engine API のドキュメントは、Info*Engine がインストールされている「codebase/infoengine/docs/apidocs」ディレクトリの Java ドキュメンテーションファイルにあります。
Info*Engine への接続
タスクインスタンスを作成または実行する場合には、その前にアプリケーションと Info*Engine ネーミングサービスの接続を初期化する必要があります。このネーミングサービスを使用すると、アプリケーションによって実行されるタスクで、エンタープライズネットワーク全体に配置されたアダプタおよびほかのサービスを検索できます。Info*Engine ネーミングサービスの接続は、静的なファクトリメソッドを以下のように呼び出すことによって確立されます。
import com.infoengine.au.NamingService;
:
:
NamingService namingService =
NamingService.newInstance
("com.myCompany.namingService",
"ldap://ldap.mycompany.com/dc=myCompany,dc=com");
この静的ファクトリメソッドは、LDAP ディレクトリにある com.myCompany.namingService (特定のエンタープライズにサービスを提供するネーミングサービス) という名前のネーミングサービスの定義を検索します。このファクトリメソッドは LDAP ディレクトリツリーでこのネーミングサービスの定義を検索します。検索を開始するルートは、識別名 dc=myCompany,dc=com を持つディレクトリエントリによって定義され、LDAP サーバーが常駐するホストは ldap.mycompany.com という名前です。この値には、ie.properties ファイルのパス、またはプロパティの検索先ディレクトリの場所を示す LDAP URL を指定できます。混乱を避けるため、ie.properties を示すように指定することが最適です。
このネーミングサービス名、識別名、および LDAP ホスト名は、実際のネットワークおよび LDAP 構造に適用する名前に置き換える必要があります。LDAP ディレクトリ構造およびネーミングサービスの定義は通常、Info*Engine ソフトウェアが初めてインストールされるときに作成されます。
ネーミングサービスの定義の検索時、SAK は接続パラメータを読み取り、すべての Info*Engine 設定プロパティを LDAP ディレクトリサービスから自動的に読み込み、呼び出しアプリケーションに制御を返します。この時点で、アプリケーションはタスクインスタンスを作成して実行します。
タスクの実行
タスクオブジェクトのインスタンスを作成するには、パラメータとして URL をとるコンストラクタを使用します。以下に例を示します。
import com.infoengine.SAK.Task;
:
:
Task task = new Task ("/com/acme/infoapp/QueryBOM.xml");
この
Task コンストラクタのパラメータは、Info*Engine タスクの URL です。さまざまな URL フォーマットを指定できます。URL の例については、
Info*Engine JSP ページを参照してください。
タスクインスタンスを構築すると、アプリケーションは addParam メソッドを呼び出すことによってパラメータをタスクに追加できます。このメソッドは、追加するパラメータの名前とその値を受け入れます。例:
import com.infoengine.SAK.Task;
:
:
Task task = new Task ("/com/acme/infoapp/QueryBOM.xml");
task.addParam ("class", "wt.part.WTPart");
task.addParam ("where", "name='Engine'");
task.addParam ("group_out", groupOutName);
同じパラメータ名を addParam への複数の呼び出しに指定すると、複数の値をとるパラメータを追加できます。パラメータの値には、どのオブジェクトタイプでも使用できます。パラメータは、@FORM コンテキストグループに対する通常の Info*Engine の置換を使用して、タスク内で参照されます。したがって、addParam メソッドを呼び出すたびに、指定された名前と値を持つ属性が、実行されるタスクの @FORM コンテキストグループに追加されます。
アプリケーションは、パラメータをタスクに追加するだけでなく、タスクを起動する前に、そのタスクに対する実行オプションを作成することもできます。たとえば、タスクを実行するユーザー名を設定できます。さらにこのユーザー名は、タスクが通信する各アダプタに提供される認証 (ユーザー名やパスワードなど) を選択するための認証マッピングキーとして、Info*Engine によって使用されます。タスクのユーザー名は、以下のように設定できます。
task.setUsername ("guest");
これにより、タスクの @SERVER コンテキストグループに auth-user 属性が設定されます。@SERVER コンテキストグループには、ほかの属性も追加できます。このコンテキストグループには通常、タスクが実行される実行時環境についての情報が含まれます。たとえば、Info*Engine サーブレットを使用してタスクを実行する場合、@SERVER コンテキストグループには、すべての HTTP プロトコルヘッダーを含む Web サーバーによって提供される情報から派生する属性を追加できます。タスクインスタンスを作成して実行するアプリケーションは、setServerAttribute メソッドを使用して、@SERVER グループに実行時環境情報を追加できます。例:
task.setServerAttribute ("accept-language", "en-US");
デフォルトでは、Info*Engine は呼び出しアプリケーションの Java 仮想マシン (JVM) 内のタスクを実行します。Info*Engine タスクプロセッサをホストしている非ローカル JVM にあるタスクを実行する方が適切な場合もあります。特に、タスクのソースコードがその非ローカルタスクプロセッサによってのみアクセスできる場合は、この方法が適切です。たとえば、タスクのソースに権限パスワードなどの機密情報が含まれている場合は、そのソースへのアクセスを制限します。非ローカルタスクプロセッサによってタスクを実行しなければならない場合は、アプリケーションから addProcessor メソッドを呼び出して、タスクを実行できる Info*Engine タスクプロセッサの名前を指定できます。例:
task.addProcessor ("com.mycompany.engineering.windchill");
必要なパラメータとサービスオプションをすべて追加したら、invoke メソッドを以下のように呼び出すことによって、タスクを実行します。
task.invoke ();
エラーの検出
タスクの実行中にエラー状態が検出されると、Java の例外が発生します。呼び出しアプリケーションでは、必要に応じて、通常の Java の try/catch ロジックを使用して、例外の検出と検査を行うことができます。もちろん、エラー状態が検出されず、タスクが正常に実行された場合は、例外は発生しません。
addProcessor メソッドを使用してタスクを非ローカルタスクプロセッサで実行するように指定すると、Info*Engine は自動的にタスクプロセッサとの通信を確立し、非ローカルタスク (すべてのパラメータおよびサービスオプションの通信など) を実行するリクエストを送信して、すべての結果を読み込みます。リモート実行されたタスクで例外が発生した場合、その例外は、ローカル JVM に送信され、そこで再び例外が発生します。addProcessor を複数回呼び出すことによって、複数のタスクプロセッサを指定した場合、Info*Engine は、名前が追加された順にタスクプロセッサとの接続を確立します。タスクは、通信の確立に成功した最初のプロセッサで実行されます。
一般的に、タスクの実行中に Info*Engine でエラー状態が検出されると、例外が発生します。Info*Engine で使用する基本的なサービスおよび API で例外が発生すると、Info*Engine はこれらを独自の例外クラスに取り込みます。その結果、すべての Info*Engine 例外クラスには、ネストされた Throwable オブジェクトが含まれることがあります。Info*Engine の例外クラスには、これらのネストされた Throwable オブジェクトを取得するためのメソッドが用意されており、アプリケーションでエラーの根本的原因を調査できます。
com.infoengine.util.IEException クラスおよびそのサブクラスの詳細については、Java ドキュメンテーションを参照してください。
タスクの結果の検査
タスクの実行が完了したら、アプリケーションは制御を再開します。この後、アプリケーションは結果を検査できます。結果は通常、タスクの Virtual Database (VDB) に保存された Info*Engine グループオブジェクトとして返されます。以下のように getGroupNames メソッドを呼び出すことによって、現在 VDB に保存されているすべてのグループの名前をいつでも取得できます。
java.util.Enumeration groupNames = task.getGroupNames ();
Task クラスによって追加された getGroup メソッドを使用すると、VDB のどのグループでも名前で取得できます。以下に例を示します。
import com.infoengine.SAK.Task;
import com.infoengine.object.factory.Group;
:
:
Task task = new Task ("/com/acme/infoapp/QueryBOM.xml");
task.addParam ("class", "wt.part.WTPart");
task.addParam ("where", "name='Engine'");
task.addParam ("group_out", "engine_parts");
task.invoke ();
Group group = task.getGroup ("engine_parts");
グループは、アプリケーションによって VDB に追加することもできます。アプリケーションによって生成されたグループでタスクを操作するように指定されている場合は、この方法が特に有効です。この場合、アプリケーションは invoke メソッドを呼び出す前に、グループをタスクの VDB に追加します。例:
import com.infoengine.object.factory.Group;
import com.infoengine.SAK.Task;
:
:
Group bomGroup = new Group ("product-structure");
:
<bomGroup generated>
:
Task task = new Task ("/com/acme/infoapp/UpdateBOM.xml");
task.addParam ("group_in", bomGroup.getName ());
task.addGroup (bomGroup);
task.invoke ();
結果のデータ
Group オブジェクト (クラス com.infoengine.object.factory.Group) は Element オブジェクト (クラス com.infoengine.object.factory.Element) のコンテナであり、Element オブジェクトは Att オブジェクト (クラス com.infoengine.object.factory.Att) のコンテナです。Element オブジェクトは通常、ビジネスオブジェクトまたはデータベーステーブルの行 (単純なデータベースアダプタの場合) を表します。Att オブジェクトは、1 つのビジネスオブジェクトの 1 つの属性を表します。各 Att オブジェクトには、1 つの名前と 1 つまたは複数の値があります。Att オブジェクトの値には、オブジェクトのいずれかのクラスを使用できます。したがって、Group は 1 つまたは複数のビジネスオブジェクトのコンテナです。各ビジネスオブジェクトは Element オブジェクトとして表され、各 Element オブジェクトには、Att オブジェクトとして表された 1 つまたは複数の名前と値のペアが含まれます。
結果のメタデータ
通常のデータのほかに、Group オブジェクト、Element オブジェクト、および Att オブジェクトには、メタデータが含まれることがあります。アプリケーションは、メタデータを使用してオブジェクトに関する情報をオブジェクト自体に登録できます。Info*Engine 自体も、この処理を行っています。各メタデータアイテムは、名前と値のペアです。Info*Engine で作成および使用されるメタデータアイテムのほとんどの名前は、com.infoengine で始まります。アプリケーションは独自のメタデータアイテムを追加できますが、com.infoengine というネームスペースは Info*Engine によって予約されているので、この文字列で始まる名前は避ける必要があります。すべての情報クラスには、メタデータの検査、作成、および管理をサポートするメソッドがあります。このようなメソッドの詳細については、Java ドキュメンテーションを参照してください。
共通のメソッド
Group クラス、Element クラス、および Att クラスはすべて、コンテンツを検査して管理するためのさまざまなメソッドをサポートしています。このようなメソッドの詳細については、Java ドキュメンテーションを参照してください。これらのクラスに共通して含まれるメソッドは、以下のとおりです。
共通のグループメソッド
getAttributeValue
Group に含まれている特定の Element オブジェクトの特定の属性 (Att) の値を取得します。
addElement
新しい Element オブジェクトを Group に追加します。
getElementCount
Group に含まれている Element オブジェクトの数を返します。
getElements
Group の Element オブジェクトすべてを 1 つの列挙として返します。
getElementAt
特定の Element オブジェクトを Group からインデックスにより読み込みます。
removeElementAt
特定の Element オブジェクトを Group からインデックスにより除去します。
toXML
Group 全体を XML にレンダリングし、結果を文字列として返すか、または出力ストリームに書き込みます。
共通の要素メソッド
addAtt
新規の属性 (Att) を Element に追加するか、または新規の値を Element の既存の属性に追加します。
getAtt
特定の属性 (Att) オブジェクトを Element から名前により読み込みます。
getAtts
Element の属性オブジェクトのすべてを列挙として返します。
getValue
Element の特定の属性 (Att) の値を読み込みます。
getValues
Element の特定の属性 (Att) のすべての値をベクトルとして読み込みます。
removeAtt
特定の属性 (Att) を Element から名前により除去します。
toXML
Element を XML にレンダリングし、出力ストリームに書き込みます。
共通の Att メソッド
addValue
値を属性に追加します。
getValue
属性の値を読み込みます。
getValues
属性のすべての値を 1 つの列挙として読み込みます。
toXML
属性を XML にレンダリングし、出力ストリームに書き込みます。
SAK のメソッドの例
以下のメソッドの例では、Group オブジェクト内を移動して、その Element オブジェクトおよびそれらの属性のすべてを表示します。
private void displayObjects (Group objects) {
//
// xmlDisplay is a boolean instance variable that defines
// whether the Group should be rendered as XML or as plain
// text.
//
if ( xmlDisplay ) {
PrintWriter pw = new PrintWriter (System.out);
objects.toXML (pw, true, true);
}
else {
int n = objects.getElementCount ();
for ( int i = 0; i < n; ++i ) {
//
// Print one empty line between Elements
//
System.out.println ("");
Element object = objects.getElementAt (i);
Enumeration atts = object.getAtts ();
while ( atts.hasMoreElements () ) {
//
// Render each attribute as "name: value"
// If an attribute is multivalued, indent each
// value such that they are vertically aligned.
//
Att att = (Att)atts.nextElement ();
String name = att.getName ();
System.out.print (name + ": ");
Enumeration values = att.getValues ();
int v = 0;
while ( values.hasMoreElements () ) {
Object value = values.nextElement ();
if ( v++ > 0 ) {
System.out.print (" ");
for ( int s = 0; s < name.length (); ++s )
System.out.print (" ");
}
System.out.println (value);
}
}
System.out.println ("");
}
}