Hitachi

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


20.4.4 WorkManagerを使用したアプリケーションの開発

ここでは,WorkManagerを使用したアプリケーションの開発について説明します。

WorkManagerを使用する場合の,アプリケーションを構成するコンポーネントの使用可否を次の表に示します。

表20‒15 WorkManagerを使用する場合のアプリケーションを構成するコンポーネントの使用可否

コンポーネント

使用可否

EJBクライアント

×

リソースアダプタ

×

JavaBeansリソース

×

サーブレット/JSP

EJB

Stateless Session Bean

EJB2.1以前

CMT

BMT

EJB3.0

×

Stateful Session Bean

×

Entity Bean

×

Message-driven Bean

×

(凡例)

○:使用できる

×:使用できない

注※ サーブレットリスナやフィルタでも使用できます。

WorkManagerを使用するアプリケーションの開発の流れは次のとおりです。

  1. スケジュール元となるEJBまたはサーブレットの属性を定義する

  2. Workおよびリスナに実行する処理を実装する

  3. スケジュール元となるEJBまたはサーブレットを作成する

  4. WorkManagerを使用するJ2EEアプリケーションをコンパイルする

それぞれの作業の詳細を次に示します。

〈この項の構成〉

(1) スケジュール元となるEJBまたはサーブレットの属性を定義する

WorkManagerを使用するEJBまたはサーブレットの属性をDDに定義します。属性は,EJBまたはサーブレットの属性定義ファイルで定義します。アノテーションで定義することはできません。

WorkManagerを使用するために定義する必要がある属性を次の表に示します。

表20‒16 WorkManagerを使用するために定義する必要がある属性

タグ名

説明

<ルートタグ>

<description>

任意で設定してください。

<res-ref-name>

JNDI ENC名(JNDIルックアップに使用する名前)を指定してください。

<res-type>

次の内容を設定してください。

「commonj.work.WorkManager」

<res-auth>

設定した値は無視されます。

<res-sharing-scope>

「Shareable」を設定してください。ただし,「Unshareable」を設定しても,「Shareable」設定時と同様に動作します(WorkManagerはアプリケーション開始時に作成されて,ルックアップ時には同じWorkManagerが返ります)。

<mapped-name>

設定した値は無視されます。

<injection-target>

設定した値は無視されます。

<linked-to>

設定した値は無視されます。

サーブレットでWorkManagerを使用する場合のweb.xmlの定義例を次に示します。

<web-app>
  <display-name>WorkManagerSample</display-name>
  <servlet> 
    <servlet-name>SampleServlet</servlet-name>
    <display-name>SampleServlet</display-name>
    <servlet-class>SampleServlet</servlet-class> 
  </servlet>
  <resource-ref>
    <res-ref-name>wm/MyWorkManager</res-ref-name>
    <res-type>commonj.work.WorkManager</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
  </resource-ref>
</web-app>

WorkManagerは,アプリケーションの開始時に,属性の定義に従って自動で作成されます。属性で定義した数のWorkManagerが作成されます。

(2) Workおよびリスナに実行する処理を実装する

WorkManagerを使用するには,実行する処理を実装したWorkおよびリスナを作成する必要があります。インタフェースには,処理の実体であるrunメソッドを持ったWorkインタフェースと,処理の受付,開始,終了などのタイミングで処理を実行するためのWorkListenerインタフェースがあります。このうち,Workは必ず実装してください。APIの詳細については,Timer and Work Manager for Application ServersのAPIの仕様を参照してください。

WorkListenerインタフェースのAPIが呼び出される流れとステータスの遷移を次に示します。

図20‒10 WorkListenerインタフェースのAPIが呼び出される流れとステータスの遷移

[図データ]

WorkListenerのメソッドおよびWork.runメソッドは,同一スレッド内で呼び出されます。そのため,それぞれのメソッドは,共通のJava EEコンテキストを使用できます。

デーモンWorkと非デーモンWorkに実装する処理の流れと実装例,およびWorkListenerの実装例を次に示します。

デーモンWorkに実装する処理の流れと実装例

デーモンWorkを使用するには,isDaemonメソッドがtrueを返すようにWorkを実装します。

WorkManagerが終了すると,コンテナはデーモンWorkを停止するために,releaseメソッドを実行します。そのため,releaseメソッドが実行されたらrunメソッドの処理が終了するように実装してください。releaseメソッドが適切に実装されていない場合,WorkManager停止時にデーモンWorkが停止しないで,無限待ちになることがあるので注意してください。

デーモンWorkの実装例を次に示します。

public class MyWork implements Work {
  private String name;
  private boolean isLoopContinue = true;
  public MyWork() {}
  
  public void release() {
    isLoopContinue = false;
  }
 
  public boolean isDaemon() {
    return true;
  }
 
  public void run() {
    while (isLoopContinue) {
      System.out.println("DaemonWork is executed");
   try {
     Thread.sleep(10000);
   } catch(InterruptedException e) {}
 }
  }
  public String toString() {
    return name;
  }
}
非デーモンWorkに実装する処理の流れと実装例

非デーモンWorkを使用するには,isDaemonメソッドがfalseを返すようにWorkを実装します。

非デーモンWorkの処理は,スケジューリングしたEJBやサーブレットの処理中に終了する必要があります。そのため,スケジュールしたWorkが終了するのを待って,EJBまたはサーブレットの処理を終了するように実装してください。スケジュールしたWorkの終了を待つには,waitForAllメソッドまたはwaitForAnyメソッドを使用します。スケジュールしたWorkが終了しないうちにEJBやサーブレットの処理を終了した場合,スケジュールしたEJBやサーブレットのライフサイクルを超えてWorkの処理が実行されてしまいます。非デーモンWorkがスケジュールしたリクエストのライフサイクルを超えて実行されないように,必ずwaitForAllメソッドなどを使用してユーザプログラム中で処理を終了してください。

非デーモンWorkの実装例を次に示します。

public class MyWork implements Work {
         private String name;
         private String data;
         public MyWork(String name) {
                  this.name = name;
}
 
         public void release() {}
 
         public boolean isDaemon() {
                  return false;
         }
 
         public void run() {
                  data = "Hello, World. name=" + name;
         }
 
         public String getData() {
                  return data;
         }
 
         public String toString() {
                  return name;
         }
}
WorkListenerの実装例

WorkListenerの実装例を次に示します。

public class ExampleListener implements WorkListener {
    public void workAccepted(WorkEvent we) {
        System.out.println("Work Accepted");
    }
 
    public void workRejected(WorkEvent we) {
        System.out.println("Work Rejected");
    }
 
    public void workStarted(WorkEvent we) {
        System.out.println("Work Started");
    }
 
    public void workCompleted(WorkEvent we) {
        System.out.println("Work Completed");
    }
}

(3) スケジュール元となるEJBまたはサーブレットを作成する

WorkManagerを使用するには,スケジュール元となるEJBまたはサーブレットに,属性に定義したWorkManagerのJNDI名のルックアップ,およびWorkManagerの処理のスケジューリングを実装します。

属性に定義したWorkManagerのJNDI名

属性に定義したWorkManagerのJNDI名をルックアップしてWorkManagerを取得します。ルックアップにはjava:comp/envを使用します。WorkManagerを取得する例を次に示します。

   InitialContext ic = new InitialContext();
   WorkManager tm = (WorkManager)ic.lookup
                        ("java:comp/env/wm/MyWorkManager");
WorkManagerの処理のスケジューリング

WorkManagerの処理のスケジューリングは,WorkManagerのscheduleメソッドを呼び出して実行します。

複数の非デーモンWorkをスケジューリングしたあと,すべてのWorkの終了を待つプログラムの例を次に示します。

MyWork work1 = new MyWork();
MyWork work2 = new MyWork();
InitialContext ctx = new InitialContext();
WorkManager mgr = (WorkManager) ctx.lookup("java:comp/env/wm/MyWorkManager");
WorkItem wi1 = mgr.schedule(work1, new ExampleListener());
WorkItem wi2 = mgr.schedule(work2);
Collection coll = new ArrayList();
coll.add(wi1);
coll.add(wi2);
mgr.waitForAll(coll, WorkManager.INDEFINITE);
 
System.out.println("work1 data: " + work1.getData());
System.out.println("work2 data: " + work2.getData());

(4) WorkManagerを使用するJ2EEアプリケーションをコンパイルする

WorkManagerを使用するJ2EEアプリケーションをコンパイルする場合は,次のJARファイルを含めてください。

<Application Serverのインストールディレクトリ>\CC\lib\ejbserver.jar