2. ライフサイクルモジュールの開発

2.1. プログラミング・開発ガイド

ライフサイクルモジュールを開発するためのコーディングの仕方について説明します。

ライフサイクルモジュールは、アプリケーションサーバ環境内で短期、または長期の間、動作させる手段として、Javaベースのタスクを提供します。短い期間のタスクの例としては、シングルトンのインスタンス化があります。また、長い期間のタスク例として、RMIサーバの起動から停止までの管理などがあります。これらのモジュールは、サーバの開始時に自動的に初期化され、それ以降、サーバのライフサイクルの中における様々なフェーズで通知を受けます。

2.1.1. ライフサイクルリスナの開発

2.1.1.1. サーバのライフサイクル・イベント

ライフサイクル・モジュールは、サーバのライフサイクルの中で下記のイベントに応じた受け入れ準備をしており、イベントを受け取るとそのイベントに応じた該当タスクを実行します。
これらのイベントは、LifecycleEventクラスで定義されます。

これらのイベントに受け入れ準備をするライフサイクル・モジュールは、LifecycleListenerインタフェースを実装し、domain.xmlファイルの中で構成化されます。

2.1.1.2. LifecycleListenerインタフェース

ライフサイクル・モジュールを生成することは、com.nec.webotx.appserv.server.LifecycleListenerインタフェースを実装する、カスタマイズされたクラスを構成することです。開発者は、複数のライフサイクル・モジュールを生成して、同時に実行することができます。

LifecycleListenerインタフェースでは、以下のメソッドを定義します。 LifecycleListenerインタフェースのサンプル実装を以下のように、LifecycleListenerImpl.javaファイルとして示します。このソースコードをライフサイクル・イベントのテスト用としても使用できます。
package com.nec.webotx.sample;

import java.util.Properties;
import com.nec.webotx.appserv.server.*;

/**
* LifecycleListenerImplは、LifecycleListenerインタフェースのダミー実装です。
* この実装は、ライフサイクル・インタフェースのメソッドから様々なイベントを
* 確認します。
*/

public class LifecycleListenerImpl implements LifecycleListener {

    /** サーバ・ライフサイクル・イベントを受け取ります。
    * @param event 関連付けられるイベント
    * @throws 例外条件に対応したServerLifecycleException
    *
    * domain.xmlの中にlifecycle-module要素としてこのモジュールを構成します。
    *
    * <applications>
    *     <lifecycle-module name="test"
    *                 class-name="com.nec.webotx.sample.LifecycleListenerImpl"
    *                 is-failure-fatal="false">
    *         <property name="foo" value="fooval"/>
    *     </lifecycle-module>
    * </applications>
    *
    * 致命的な条件に対しては、domain.xmlの中のis-failure-fatalにtrueを
    * 設定してください。
    */
    public void handleEvent(LifecycleEvent event) throws ServerLifecycleException
    {
        LifecycleEventContext context = event.getLifecycleEventContext();

        context.log("got event" + event.getEventType() + " event data: "
            + event.getData());

        Properties props;

        if (LifecycleEvent.INIT_EVENT == event.getEventType()) {
            context.log("LifecycleListener: INIT_EVENT");

            props = (Properties) event.getData();

            // handle INIT_EVENT
            return;
        }

        if (LifecycleEvent.STARTUP_EVENT == event.getEventType()) {
            context.log("LifecycleListener: STARTUP_EVENT");

            // handle STARTUP_EVENT
            return;
        }

        if (LifecycleEvent.READY_EVENT == event.getEventType()) {
            context.log("LifecycleListener: READY_EVENT");

            // handle READY_EVENT
            return;
        }

        if (LifecycleEvent.SHUTDOWN_EVENT== event.getEventType()) {
            context.log("LifecycleListener: SHUTDOWN_EVENT");

            // handle SHUTDOWN_EVENT
            return;
        }

        if (LifecycleEvent.TERMINATION_EVENT == event.getEventType()) {
            context.log("LifecycleListener: TERMINATE_EVENT");

            // handle TERMINATION_EVENT
            return;
        }
    }
}

2.1.1.3. LifecycleEventクラス

com.nec.webotx.appserv.server.LifecycleEventクラスは、サーバ・ライフサイクル・イベントを定義します。イベントに関連するメソッドは下記のとおりです。
LifecycleEventインスタンスは、前の章で説明したLifecycleListener.handleEventメソッドに渡されます。

2.1.1.4. サーバのライフサイクル・イベント・コンテキスト

com.nec.webotx.appserv.server.LifecycleEventContextインタフェースは、サーバに関する実行時情報を提供します。ライフサイクル・イベント・コンテキストは、LifecycleEventクラスがサーバの初期化でインスタンス化される時に生成されます。 LifecycleEventContextインタフェースは、下記のメソッドを定義しています。 ライフサイクル・モジュールのためのネーミング環境は、STARTUP_EVENTイベントの最中にインストールされます。 ライフサイクル・モジュールは、STARTUP_EVENTイベントが完了した後に、そのjndi-name属性により、domain.xmlファイルで定義された任意のリソースをルックアップすることができます。

Caution
JNDIの中における他のエンタープラズ・リソースの名前と衝突を回避し、ポータビリティ問題を回避するために、WebOTXアプリケーションサーバでのライフサイクル・モジュール中の名前は全て、文字列「java:comp/env」から始まらなければなりません。

 ライフサイクル・モジュールがリソースをルックアップする必要がある場合、それはREADY_EVENTイベントの中で行うことができます。 そのモジュールは、全てのリソースがバインドされている初期コンテキストを得るために、getInitialContext()メソッドを使用することができます。

2.1.2. ライフサイクル・モジュールの作成

2.1.2.1. ライフサイクル・モジュールの作成

ライフサイクル・モジュールを作成するためには、下記に示すステップで組み立てていきます。
  1. 作業用ディレクトリを作成し、その中にモジュールのコンテンツをコピーします。
  2. JARファイルを生成するために、次のコマンドを実行します。
    [foo@webotx ~]$ jar -cvf moudle_name.jar * 

2.1.2.2. ライフサイクル・モジュールの配備

ライフサイクル・モジュールは、下記のツールを使って配備することができます。
otxadminコマンド

ライフサイクル・モジュールを配備するためには、otxadmin create-lifecycle-moduleコマンドを用います。その構文は次のとおりです。一部のオプショナル・パラメータには既定値を示しています。
otxadmin> create-lifecycle-module --user user --classname classname [--classpath classpath] 
[--loadorder load_order_number] [--failurefatal=false] [--enabled=true] [--description 
text_description] [--property (name=value)[:name=value]*] modulename 
		
otxadminコマンドの一般的なオプショナルのパラメータ (--password、--passwordfile、--host、--port、--terse、--echo、--interactive) に関しては、[ リファレンス集 運用管理・設定編 > 4. 運用管理コマンドリファレンス ] を参照してください。

 (例)
otxadmin> create-lifecycle-module --user admin --classname RMIServer MyRMIServer
ライフサイクル・モジュールを配備解除するためには、otxadmin delete-lifecycle-moduleコマンドを用います。その構文は次のとおりです。一部のオプショナル・パラメータには既定値が適用されます。  
otxadmin> delete-lifecycle-module --user user modulename 
 (例)
otxadmin> delete-lifecycle-module --user admin MyRMIServer
配備済みライフサイクル・モジュールに一覧を得るためには、otxadmin list-lifecycle-modulesコマンドを用います。その構文は次のとおりです。一部のオプショナル・パラメータには既定値が適用されます。  
otxadmin> list-lifecycle-module --user user
 (例)
otxadmin> list-lifecycle-module --user admin

2.1.2.3. ライフサイクル・モジュールの構成情報

ライフサイクル・モジュール配備中に、lifecycle-module要素がdomain.xmlファイルに生成されます。管理者は、その構成を変更するために、このファイルを編集することができます。 propertyサブ要素は、入力パラメータを指定することを可能にします。以下に例を示します。
<lifecycle-module name="customStartup"
        enabled="true"
        class-name="com.acme.CustomStartup"
        classpath="/apps/customStartup"
        load-order="200"
        is-failure-fatal="true">
    <description>custom startup module to do my tasks</description>
    <property name="rmiServer" value="acme1:7070" />
    <property name="timeout" value="30" />
</lifecycle-module> 
is-failure-fatalがtrue(既定値はfalse)に設定される場合、ライフサイクル・モジュールの動作に失敗すると、シャットダウン時か終了時ではなく、サーバの初期化時か開始時に、サーバ動作を停止に働かせることに注意してください。

ライフサイクル・モジュールを配備した後、それを活性化するためにはサーバを再起動しなければなりません。サーバはモジュールをインスタンス化し、サーバの初期化でライフサイクル・イベント・リスナとしてモジュールを登録します。

2.1.2.4. サーバのライフサイクル・モジュールで考慮する点

初期化または開始の中で割り当てられたリソースは、シャットダウンまたは終了の中で解放されるべきです。ライフサイクル・モジュール・クラスは、メイン・サーバ・スレッドから同期して呼ばれます。したがって、これらのクラスがサーバをブロックしないことを保証することが重要です。それに適合するならば、ライフサイクル・モジュールはスレッドを生成してもよいです。しかし、これらのスレッドはシャットダウンと終了の段階の中でスレッド処理を中止しなければなりません。

LifeCycleModule Classloaderは、ライフサイクル・モジュール用の親クラスローダです。各ライフサイクル・モジュールのdomain.xml内におけるclasspath値は、そのクラスローダを構築するために使用されます。 classloaderを構築するために使用される。ライフサイクル・モジュールによって必要とされる全ての支援クラスは、LifeCycleModule Classloader、あるいはその親やConnector Classloaderで利用可能でなければなりません。

 運用者、またはモジュール開発者は、server.policyファイルを適切に設定することを保証しなければなりません。また、System.exec()を実行しようとするライフサイクル・モジュールは、セキュリティ・アクセス妨害を引き起こすかもしれません。

ライフサイクル・モジュールへの構成済みプロパティは、INIT_EVENTイベント内でプロパティとして渡されます。 JNDIネーミング・コンテキストは、INIT_EVENTイベント内においては利用できません。ライフサイクル・モジュールがネーミング・コンテキストを必要とする場合、それはSTARTUP_EVENT、READY_EVENT、SHUTDOWN_EVENTイベントの中で得ることができます。

2.1.2.5. APIリファレンス

ライフサイクル・リスナ API 仕様