ヘッダーをスキップ
Oracle® Fusion Middleware Timer and Work Manager API (CommonJ) プログラマーズ ガイド
11g リリース 1 (10.3.1)
B55542-01
 


 

Oracle® Fusion Middleware

Timer and Work Manager API (CommonJ) プログラマーズ ガイド

11g リリース 1 (10.3.1)

E13733-01

2009年5月

この節では、Timer and Work Manager API の概要を説明し、これらをアプリケーション内に実装する方法を示します。

Timer and Work Manager API とは

Timer and Work Manager API は、Oracle と IBM が共同作成した仕様で定義されています。この API を使用すると、Java EE アプリケーション内に EJB とサーブレットを同時にプログラミングできます。この API はしばしば CommonJ と呼ばれます。

CommonJ API には、次のコンポーネントが含まれます。

commonj.timercommonj.work は同じ API の一部ですが、それぞれ別の機能を提供します。どちらの API を実装するかは、アプリケーション固有のニーズによって決定します。CommonJ Timer API は、作業を特定の間隔でスケジューリングする場合に理想的です。たとえば、あるジョブを特定の時刻に実行する必要がある場合などです。CommonJ Work Manager API は、作業を優先順位に基づいて処理する場合に理想的です。たとえば、特定のジョブの発生時期をはっきりと予測できないが、発生した場合には高い (または低い) 優先順位を与える場合などです。

以下の節では、CommonJ API を詳細に説明します。

Timer API の概要

Timer API は次の 3 つのインタフェースで構成されています。

TimerManager は、管理対象の環境においてタイマーを作成および使用するためのフレームワークを提供します。TimerListener は、タイマー通知を受信します。TimerManager.schedule() メソッドを使用して、TimerListener を特定の時刻または間隔において実行するようにスケジューリングします。

タイマーの実装方法の詳細については、「Timer API の使用」を参照してください。

TimerManager インタフェース

TimerManager インタフェースは、アプリケーション内の全般的なスケジューリング フレームワークを提供します。管理対象の環境では、複数の TimerManager インスタンスをサポートできます。1 つのアプリケーション内に複数の TimerManager インスタンスを設定できます。

タイマー マネージャの作成およびコンフィグレーション

TimerManager は、デプロイ中にデプロイメント記述子でコンフィグレーションされます。TimerManager の定義には、実装固有の付加的なコンフィグレーション情報が含まれることもあります。

デプロイメント記述子に TimerManager が定義されると、そのインスタンスはローカル Java 環境で JNDI ルックアップを使用してアクセスできるようになります。JNDI lookup()TimerManager を呼び出すたびに、TimerManager の新しい論理インスタンスが返されます。

TimerManager インタフェースはスレッドセーフです。

JNDI の詳細については、『Oracle Fusion Middleware WebLogic JNDI プログラマーズ ガイド』を参照してください。

TimerManager の中断

TimerManager は、suspend() メソッドおよび resume() メソッドを使用して中断および再開できます。TimerManager を中断すると、未処理のタイマーはすべて TimerManager が再開されるまで保留されます。

TimerManager の停止

TimerManager は、stop() メソッドを使用すると停止できます。stop() が呼び出されると、アクティブなタイマーはすべて停止され、TimerManager インスタンスはすべての TimerListener インスタンスのモニタを停止します。

TimerListener インタフェース

commonj.timers パッケージを使用するすべてのアプリケーションは、TimerListener インタフェースを実装する必要があります。

Timer インタフェース

Timer インタフェースのインスタンスは、TimerManager を介してタイマーがスケジューリングされたときに返されます。

Timer API の使用

この節では、アプリケーション内で Timer API を使用するために必要な手順を簡単に示します。

アプリケーションをデプロイする前に、タイマー マネージャへのリソース参照を含むデプロイメント記述子が作成済みであることを確認してください。

これにより、TimerManager が JNDI を介してアクセス可能になります。JNDI ルックアップの詳細については、『Oracle Fusion Middleware WebLogic JNDI プログラマーズ ガイド』を参照してください。

Timer API の実装

以下の手順で、Timer API の実装方法を説明します。

  1. commonj.timers.* パッケージをインポートします。

  2. InitialContext を作成します。これにより TimerManager が JNDI でルックアップ可能になります。

    InitialContext inctxt = new InitialContext(); 
    

    JNDI ルックアップの詳細については、『Oracle Fusion Middleware WebLogic JNDI プログラマーズ ガイド』を参照してください。

  3. TimerManager の JNDI ルックアップに基づいて新しい TimerManager を作成します。

    TimerManager mgr = (TimerManager)ctx.lookup('java:comp/env/timer/MyTimer');
    

    この文では JNDI ルックアップの結果が TimerManager にキャストされています。

  4. タイマー通知を受信するために TimerListener を実装します。

    TimerListener listener = new StockQuoteTimerListener('abc', 'example');
    
  5. TimerManager.schedule() を呼び出します。

    mgr.schedule(listener, 0, 1000*60)
    

    schedule() メソッドは Timer オブジェクトを返します。

  6. timerExpired() メソッドを実装します。

    public void timerExpired(Timer timer) {
         //このメソッド内で
         //ビジネス ロジックが実行される
    }
    

クラスタワイド タイマーの Timer API の実装では、要件が追加されます (「タイマーのライフ サイクル」を参照)。

タイマー マネージャのサンプル

package examples.servlets;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import commonj.timers.*;

/**
* TimerServlet は commonj タイマーの簡単な使用法を示す
*/
public class TimerServlet extends HttpServlet {

/**
  * commonj タイマーをスケジューリングするサービス メソッドの
  * とても単純な実装
  */
  public void service(HttpServletRequest req, HttpServletResponse res)
    throws IOException
  {
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    try {
      InitialContext ic = new InitialContext();
      TimerManager tm = (TimerManager)ic.lookup
        ("java:comp/env/tm/default");
      // すぐに開始する 10 秒ごとのタイマーを実行
      tm.schedule (new MyTimerListener(), 0, 10*1000);
      out.println("<h4>Timer scheduled!</h4>");
    } catch (NamingException ne) {
      ne.printStackTrace();
      out.println("<h4>Timer schedule failed!</h4>");
    }
  }

  private static class MyTimerListener implements TimerListener {
    public void timerExpired(Timer timer) {
      System.out.println("timer expired called on " + timer);
      // ここに有用な処理を記述
      // タイマーはキャンセルすること
      System.out.println("cancelling timer ...");
      timer.cancel();
    }
  }
}

ジョブ スケジューラの使用

この節では、ジョブ スケジューラ機能の使用方法について説明します。ジョブ スケジューラを使用すると、クラスタ化環境内に commonj.timer API を実装できます。

ジョブ スケジューラは、基本的には commonj.timer API パッケージの実装であり、クラスタ内で使用できます。ここではジョブは commonj.timers.TimerListener インスタンスとして定義され、ジョブ スケジューラに送信されて実行されます。

この節では、以下のトピックを取り上げます。

タイマーのライフ サイクル

アプリケーション内に commonj.timer API を実装する場合、タイマーにコンフィグレーションできるライフ サイクルには 2 種類あります。

  • ローカル タイマー

    ローカル タイマーは単一のサーバ JVM 内でスケジューリングされ、ライフ サイクル全体にわたってこの JVM 内で処理されます。ローカル タイマーはこの JVM が動作している限り動作し続け、JVM が終了すると失敗します。サーバ起動後のタイマーの再スケジューリングはアプリケーションが行います。

    これは commonj.timers の基本実装であり、これについては「Timer API の概要」で説明しています。

  • クラスタワイド タイマー

    クラスタワイド タイマーはクラスタ内の各サーバを含む他の JVM を認識し、そのため、ロード バランシングとフェイルオーバが可能です。クラスタワイド タイマーのライフ サイクルは作成したサーバにとらわれず、クラスタのライフ サイクルにわたって機能し続けます。クラスタ メンバーの少なくとも 1 つが有効である限り、このタイマーは機能を続けます。この機能はジョブ スケジューラと呼ばれます。

    ジョブ スケジューラの Timer API の実装では、「Timer API の実装」にリストされている要件の他に、以下の要件が追加されます。

    • タイマー リスナ クラスはシリアライズ可能でなければならない。

    • タイマー リスナー クラスはサーバ システム クラスパスに指定されていなければならない。

    • タイマーの再試行の最小時間は 30 秒。これは、ジョブ スケジューラが 30 秒ごとに実行するタイマーを取得するためです。「ジョブ スケジューラの使用」を参照してください。

各タイマーにはそれぞれメリットとデメリットがあります。ローカル タイマーでは、複数のジョブをより短い時間間隔で処理できます。ジョブ スケジューラでは、クラスタ内の永続性要件のために同様の精度ではジョブを処理できません。一方で、初めにタスクを作成したサーバが失敗した場合にもそのタスクを実行する必要がある場合には、ジョブ スケジューラの方が適しています。

ジョブ スケジューラの実装とコンフィグレーション

この節では、アプリケーション内にジョブ スケジューラを実装し、それを利用するように WebLogic Server 環境をコンフィグレーションするための基本的な手順を簡単に示します。

データベースのコンフィグレーション

永続性を保持し、タイマーがクラスタを認識できるようにするため、ジョブ スケジューラにはデータベース接続が必要です。ジョブ スケジューラ機能では、サーバの移行でサポートされるのと同じデータベース ベンダおよびバージョンがサポートされます。

便宜上、セッション永続性、サーバの移行などに使用されているのと同じデータベースを使用できます。たとえば、サーバの移行におけるソース データの選択および作成の手順については、『Oracle Fusion Middleware Oracle WebLogic Server Administration Console ヘルプ』の「クラスタ内のサーバの移行のコンフィグレーション」を参照してください。

データベースには、WEBLOGIC_TIMERS というテーブルを作成する必要があります。サポートされるデータベースにこのテーブルを作成するためのスキーマは、以下にあります。

WL_HOME/server/db/dbname/scheduler.ddl

dbname はデータベース ベンダの名前です。 

データ ソースのコンフィグレーション

必要なスキーマでテーブルを作成した後には、クラスタ コンフィグレーション内で参照されるデータ ソースを定義する必要があります。ジョブ スケジューラ機能は、ClusterMBeanDataSourceForJobScheduler 属性に有効なデータ ソースが定義されている場合にのみ利用できます。これは、WebLogic Server Administration Console でコンフィグレーション可能です。『Oracle Fusion Middleware Oracle WebLogic Server Administration Console ヘルプ』の「ジョブ スケジューラのデータ ソースのコンフィグレーション」を参照してください。

この定義の仕方について、以下の config.xml からの抜粋に示します。

<domain>
...
 <cluster>
  <name>Cluster-0</name>
  <multicast-address>239.192.0.0</multicast-address>
  <multicast-port>7466</multicast-port>
  <data-source-for-job-scheduler>JDBC Data     Source-0</data-source-for-job-scheduler>
 </cluster>
...
 <jdbc-system-resource>
  <name>JDBC Data Source-0</name>
  <target>myserver,server-0</target>
  <descriptor-file-name>jdbc/JDBC_Data_Source-0-3407-jdbc.xml</descriptor-file-name>
 </jdbc-system-resource>
</domain>

リース

ジョブ スケジューラでは、リースが有効になっている必要があります。リースは、高可用性データベース リースまたは非データベース コンセンサス リースのいずれかを使用できます。

リースの詳細については、『Oracle Fusion Middleware Oracle WebLogic Server クラスタの使い方』の「リーズ」を参照してください。

高可用性データベース リースを使用する場合、データベースにリース テーブルを作成する必要があります。サポートされるデータベースにこのテーブルを作成するためのスキーマは、以下にあります。

WL_HOME/server/db/dbname/leasing.ddl

dbname はデータベース ベンダの名前です。

ジョブ スケジューラ内で JNDI アクセス

クラスタ化されたタイマー内で JNDI ルックアップを実行する手順は、一般的な commonj.timer API における手順とは異なります。JNDI ルックアップを TimerManager にキャストする方法を以下の抜粋コードに示します。

InitialContext ic = new InitialContext(); 
commonj.timers.TimerManager jobScheduler =(common.timers.TimerManager)ic.lookup
   ("weblogic.JobScheduler");
commonj.timers.TimerListener timerListener = new MySerializableTimerListener();
jobScheduler.schedule(timerListener, 0, 30*1000); 
// 30 秒ごとにこのジョブを実行

ジョブのキャンセル

ジョブは、プログラムまたは Administration Console を使用してキャンセルできます。

プログラムを使用してジョブをキャンセルするには、そのジョブの対応する JobRuntimeMBeancancel() メソッドを呼び出します。JobRuntimeMBeans には、以下のいずれかの方法でアクセスできます。

  • スケジュールされたジョブの ID を使用して JobSchedulerRuntimeMBean.getJob(id) を呼び出す。ID は、JobScheduler.schedule() メソッドを呼び出して取得した Timer オブジェクトの toString() メソッドから取得します。

  • JobSchedulerRuntimeMBean.getExecutedJobs() を呼び出して、少なくとも 1 回は実行したすべてのジョブの JobRunTimes の配列を取得する。

cancel() メソッドを使用して、1 回も実行していないスケジュールされたジョブをキャンセルすることはできません。

Administration Console を使用してジョブをキャンセルする方法については、Administration Console オンライン ヘルプの「ジョブの取り消し」を参照してください。

デバッグ

以下のデバッグ フラグを使用すると、より冗長な出力が可能になります。

-Dweblogic.debug.DebugSingletonServices=true -Dweblogic.JobScheduler=true

サポートされていないメソッドおよびインタフェース

commonj.timer API のメソッドおよびインタフェースの中には、ジョブ スケジューラ環境でサポートされていないものもあります。以下のメソッドおよびインタフェースはサポートの対象外です。

  • CancelTimerListener インタフェース

  • StopTimerListener インタフェース

  • TimerManager インタフェースの以下のメソッド

    • suspend()

    • resume()

    • scheduleAtFixedRate()

    • stop()

    • waitForStop()

    • waitForSuspend()

Work Manager API とは

Work Manager (commonj.work) API は、アプリケーションがコンテナ内で複数の作業項目を同時に実行できるようにするインタフェースを提供します。

基本的に、この API は java.lang.Thread API のコンテナ管理の代替機能を提供します。java.lang.Thread API は、管理対象の Java EE 環境でホストされるアプリケーション内では使用しないようにする必要があります。Work Manager API を使用するとコンテナが実行中のすべてのスレッドを認識および制御できるので、そうした環境では代わりに Work Manager API を使用するようお勧めします。


注意 :

Work Manager API では、フェイルオーバや永続性メカニズムは提供されません。管理対象サーバ環境が失敗または停止した場合、現在の作業はすべて失われます。

ワーク マネージャのインタフェース

この節では、Work Manager API に定義されているインタフェースの全般的な概要を説明します。これらのインタフェースの詳細な使用方法については、commonj.work パッケージの javadoc を参照してください。

Work Manager API には以下のインタフェースがあります。

  • WorkManager - このインタフェースは、実行する作業のスケジューリングに使用するスケジューリング メソッド群を提供します。

    WorkManager はサーバ レベルでシステム管理者が定義します。WorkManager インスタンスは JNDI ルックアップを実行して取得します。管理対象の環境では、複数の WorkManager インスタンスをサポートできます。『Oracle Fusion Middleware WebLogic JNDI プログラマーズ ガイド』を参照してください。WorkManager はデプロイ中に resource-ref としてコンフィグレーションします。「ワーク マネージャのデプロイメント」を参照してください。

    アプリケーション レベルでは、WorkManager の各インスタンスが WorkItem を返します。アプリケーション内に WorkManager を実装する方法の詳細については、WorkManager の javadoc を参照してください。

  • Work - このインタフェースを使用すると、アプリケーション コードを非同期的に実行できます。このインタフェースを実装するクラスを作成することで、コード ブロックを作成して特定の時刻または定義した間隔で実行するようにスケジューリングできます。これがすなわち、Work Manager API 内で処理される「作業」です。

  • WorkItem - Work インスタンスが WorkManager に送信された後で、WorkManagerWorkItem を返します。WorkItem は完了した Work インスタンスの状態の判断に使用されます。

  • WorkListener - WorkListener インタフェースは、Work インスタンス内に定義されたスケジューリング済み作業と WorkManager との通信機能を提供するコールバック インタフェースです。

    WorkListener を使用すると Work 項目の現在の状態を判断できます。詳細については、WorkListener の javadoc を参照してください。


    注意 :

    WorkListener インスタンスは、WorkManager 経由で Work をスケジューリングするのに使用した元のスレッドと常に同じ JVM で実行されます。

  • WorkEvent - WorkEvent は、WorkManager によって Work が処理されたときに WorkListener に送信されます。

  • RemoteWorkItem - RemoteWorkItem インタフェースは WorkItem インタフェースの拡張で、作業をリモートに実行できるようにします。このインタフェースを使用すると、クラスタの任意のメンバーで実行される作業をシリアライズできます。

ワーク マネージャのデプロイメント

ワーク マネージャは、サーバレベルで、適切なデプロイメント記述子の resource-ref を使用して定義します。さまざまな記述子がありますが、特に web.xml または ejb-jar.xml が定義場所になります。

以下のデプロイメント記述子からの抜粋に、WorkManager のコンフィグレーション方法を示します。

...
<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>
...

注意 :

WorkManager オブジェクトの JNDI ネームスペースに推奨されるプレフィックスは java:comp/env/wm です。

ワーク マネージャのサンプル

この節には、HTTP サーブレット内で CommonJ ワーク マネージャを使用する作業コードのサンプルを示します。

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import weblogic.work.ExecuteThread;
import commonj.work.WorkManager;
import commonj.work.Work;
import commonj.work.WorkException;

public class HelloWorldServlet extends HttpServlet {

   public void service(HttpServletRequest req, HttpServletResponse res)
      throws IOException
   {
      res.setContentType("text/html");
      PrintWriter out = res.getWriter();


      try {
         InitialContext ic = new InitialContext();
         System.out.println("## [servlet] executing in: " +
            ((ExecuteThread)Thread.currentThread()).getWorkManager()
            .getName());
         WorkManager wm = (WorkManager)ic.lookup
            ("java:comp/env/foo-servlet");
         System.out.println("## got Java EE work manager !!!!");
         wm.schedule(new Work(){
         public void run() {
         ExecuteThread th = (ExecuteThread) Thread.currentThread();
         System.out.println("## [servlet] self-tuning workmanager: " +
           th.getWorkManager().getName());
         }
         public void release() {}

         public boolean isDaemon() {return false;}
         });
} 
catch (NamingException ne) {
         ne.printStackTrace();} 

catch (WorkException e) {
         e.printStackTrace();
}

out.println("<h4>Hello World!</h4>");
// 出力ストリームを閉じないこと - 出力ストリームはサーブレット エンジンが閉じられるようにする
// これはパフォーマンス向上のため
System.out.println("finished execution");}

}

ドキュメントのアクセシビリティについて

Oracle は、障害のあるお客様を含む、すべてのお客様に Oracle の製品、サービスおよびサポート ドキュメントをご利用いただけることを目標としています。Oracle のドキュメントには、ユーザが障害支援技術を使用して情報を利用できる機能が組み込まれています。HTML 形式のドキュメントで用意されており、障害のあるお客様が簡単にアクセスできるようにマークアップされています。標準規格は改善されつつあります。Oracle はドキュメントをすべてのお客様がご利用できるように、市場をリードする他の技術ベンダと積極的に連携して技術的な問題に対応しています。Oracle のアクセシビリティについての詳細情報は、Oracle Accessibility Program の Web サイト http://www.oracle.com/accessibility/ を参照してください。

ドキュメント内のサンプル コードのアクセシビリティについて

スクリーン リーダーは、ドキュメント内のサンプル コードを正確に読めない場合があります。コード表記規則では閉じ括弧だけを行に記述する必要があります。しかし一部のスクリーン リーダーは括弧だけの行を読まない場合があります。

外部 Web サイトのドキュメントのアクセシビリティについて

このドキュメントには Oracle およびその関連会社が所有または管理しない Web サイトへのリンクが含まれている場合があります。Oracle およびその関連会社は、それらの Web サイトのアクセシビリティに関しての評価や言及は行っておりません。

ヒアリング アクセスが困難な聴覚障害者の Oracle サポート サービス

Oracle サポート サービスへ telecommunications relay service (TRS) アクセスが提供されています。Oracle サポートについては、1.800.223.1711 にお電話ください。Oracle サポート サービス エンジニアは、技術的な問題に対応し、Oracle サービス リクエスト処理に従ってお客様にサポートを提供します。TRS の詳細については、http://www.fcc.gov/cgb/consumerfacts/trs.html を参照し、電話番号の一覧については、http://www.fcc.gov/cgb/dro/trsphonebk.html を参照してください。


Oracle Fusion Middleware Timer and Work Manager API (Commonj) プログラマーズ ガイド 11g リリース 1 (10.3.1)

E13733-01

Copyright © 2007, 2009, Oracle and/or its affiliates. All rights reserved.

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、Oracle までご連絡ください。

このソフトウェアおよび関連ドキュメントが米国政府機関、もしくは米国政府機関に代わってこのソフトウェアをライセンスまたは使用する者に提供される場合は、次の注意が適用されます。

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

このソフトウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアを危険が伴うアプリケーションで使用する際、このソフトウェアを安全に使用するために、適切な安全装置、バックアップ、冗長性 (redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、Oracle およびその関連会社は一切の責任を負いかねます。

Oracle は Oracle Corporation およびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

このソフトウェアおよびドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。Oracle およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。Oracle およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。