Last-modified: 2007-09-08 (土) 23:19:29 (6067d)

 「ASP.NET/定期的にTaskを実行する」の内容を、QuizMLに試験的に実装し、ASP.NETで非同期実行ができることがわかりました。じゃぁ、J2EEではどうなんだ? ということで、やってみました。

java.util.TimerをServletで使う

  1. まず、java.util.TimerTaskクラスを継承、runメソッドを実装したクラスを作成し、runメソッド内に実行したいタスクを記述します。
  2. Servlet内でTimerインスタンスを生成し、上で作成したTaskを登録するだけです。
    Timer timer1 = new Timer();
    timer1.scheduleAtFixedRate(new Task01(config.getServletContext()), firstTime, peroid); 
    • サンプルサーブレット fileTimerTestServlet01.java
    • ※1 開始時刻として過去の時刻を設定すると、その時刻から現在時刻までの実行されたはずの回数分が、スケジュール登録時に一気に実行されてしまいます。開始時刻は、未来時刻になるようにするのが好いでしょうね。
  • http://jomora.net/picture/ (18+) のサムネイル一覧とファイルシステムの同期を、毎日04:10に実行するように設定してみました。

問題点

  • J2EEでjava.util.Timerを利用することは、問題があるようです。
    1. J2EE 1.4仕様では、サーブレットのサービス・メソッド(service(), doPost(), doGet()等)から新たに別のスレッドを生成し、その新スレッドでJTA(Java Transaction API)を利用したトランザクションを開始することを禁じている
      • J2EE 1.4仕様の「J2EE.4.2.3 Transactions and Threads」の節を参照
    2. EJB 2.1仕様では、Enterprise Beanが開始、終了、中断、再開を含むスレッドの管理を行うことを禁じている。スレッドの管理はEJBコンテナの役割なのです。
      • EJB 2.1仕様の「25.1.2 Programming Restrictions」の節を参照
    3. 開発者がクラスThreadのインスタンスを生成して新たなスレッドを開始した場合には、その新たなスレッドにJava EEコンテキストを渡すことができないため、そのスレッドは認証済みユーザーとは別のSecurity Identityを持つものとして稼働する可能性がある。また、トランザクションの開始や終了といった制御が行えない可能性がある。
  • その解決策が、BEAとIBMが共同策定した「JSR 236:Timer for Application Servers」と「JSR 237:Work Manager for Application Servers」であり、その実行が「commonj」というプロジェクトらしい。
    • commonjはWebLogicとWebSphereで利用可能。オープン実装としては、Globus Toolkitに含まれているものや、myFoo.deで配布されているものがある。

Globus Toolkitに含まれているcommonj実装

 必要なパーツをうまく抽出できません ...orz

myFoo.deで配布されているcommonj実装

 Tomcat5.5を用い、<Context>(server.xml)およびweb.xmlで<Resource>設定をし、TimerManagerインスタンスの取得はできているようなのですが、java.lang.IllegalMonitorStateException が出まくります ...orz


添付ファイル: fileTimerTestServlet01.java 6972件 [詳細] fileTask01.java 6829件 [詳細]

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS