20.4.4 WorkManagerを使用したアプリケーションの開発
ここでは,WorkManagerを使用したアプリケーションの開発について説明します。
WorkManagerを使用する場合の,アプリケーションを構成するコンポーネントの使用可否を次の表に示します。
コンポーネント |
使用可否 |
|||
---|---|---|---|---|
EJBクライアント |
× |
|||
リソースアダプタ |
× |
|||
JavaBeansリソース |
× |
|||
サーブレット/JSP※ |
○ |
|||
EJB |
Stateless Session Bean |
EJB2.1以前 |
CMT |
○ |
BMT |
○ |
|||
EJB3.0 |
× |
|||
Stateful Session Bean |
× |
|||
Entity Bean |
× |
|||
Message-driven Bean |
× |
WorkManagerを使用するアプリケーションの開発の流れは次のとおりです。
-
スケジュール元となるEJBまたはサーブレットの属性を定義する
-
Workおよびリスナに実行する処理を実装する
-
スケジュール元となるEJBまたはサーブレットを作成する
-
WorkManagerを使用するJ2EEアプリケーションをコンパイルする
それぞれの作業の詳細を次に示します。
- 〈この項の構成〉
(1) スケジュール元となるEJBまたはサーブレットの属性を定義する
WorkManagerを使用するEJBまたはサーブレットの属性をDDに定義します。属性は,EJBまたはサーブレットの属性定義ファイルで定義します。アノテーションで定義することはできません。
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が呼び出される流れとステータスの遷移を次に示します。
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