![]() ![]() ![]() ![]() |
この節では、Timer and Work Manager API の概要を説明し、これらをアプリケーション内に実装する方法を示します。
Timer and Work Manager API は、BEA Systems と IBM が共同作成した仕様で定義されています。この API を使用すると、J2EE アプリケーション内に EJB とサーブレットを同時にプログラミングできます。この API はしばしば CommonJ と呼ばれます。
CommonJ API には、次のコンポーネントが含まれます。
Timer API を使用すると、アプリケーション内に定義された特定のリスナに対し、アプリケーションでタイマー通知コールバックをスケジューリングして受信できます。タイマー機能を利用すると、特定の時刻または間隔において作業するようにスケジューリングおよび実行することが可能です。「Timer API の概要」を参照してください。
この API は、commonj.timer パッケージをインポートして実装します。
Work Manager API を使用すると、アプリケーションで EJB またはサーブレット内の作業の優先順位を決められます。アプリケーションは、複数の作業項目をコンテナ内部でプログラム的に実行できます。「Work Manager API とは」を参照してください。
この API は、commonj.work パッケージをインポートして実装します。
WebLogic Server には、CommonJ Work Manager API 以外にもサーバレベルのワーク マネージャが複数あり、優先順位の決定やスレッド管理を行えます。これらは、グローバルにコンフィグレーションすることも、アプリケーションの特定のモジュール用にコンフィグレーションすることも可能です。
commonj.timer と commonj.work は同じ API の一部ですが、それぞれ別の機能を提供します。どちらの API を実装するかは、アプリケーション固有のニーズによって決定します。CommonJ Timer API は、作業を特定の間隔でスケジューリングする場合に理想的です。たとえば、あるジョブを特定の時刻に実行する必要がある場合などです。CommonJ Work Manager API は、作業を優先順位に基づいて処理する場合に理想的です。たとえば、特定のジョブの発生時期をはっきりと予測できないが、発生した場合には高い (または低い) 優先順位を与える場合などです。
Timer API は次の 3 つのインタフェースで構成されています。
タイマー マネージャは、管理対象の環境においてタイマーを作成および使用するためのフレームワークを提供します。タイマー リスナは、タイマー通知を受信します。TimerManager.schedule() メソッドを使用して、TimerListener を特定の時刻または間隔において実行するようにスケジューリングします。
タイマーの実装方法の詳細については、「Timer API の使用」を参照してください。
TimerManager インタフェースは、アプリケーション内の全般的なスケジューリング フレームワークを提供します。管理対象の環境では、複数の TimerManager インスタンスをサポートできます。1 つのアプリケーション内に複数の TimerManager インスタンスを設定できます。
TimerManager は、デプロイ中にデプロイメント記述子でコンフィグレーションされます。TimerManager の定義には、実装固有の付加的なコンフィグレーション情報が含まれることもあります。
デプロイメント記述子に TimerManager が定義されると、そのインスタンスはローカル Java 環境で JNDI ルックアップを使用してアクセスできるようになります。JNDI lookup() で TimerManager を呼び出すたびに、TimerManager の新しい論理インスタンスが返されます。
TimerManager インタフェースはスレッドセーフです。
JNDI の使用方法の詳細については、『WebLogic JNDI プログラマーズ ガイド』を参照してください。
TimerManager は、suspend() メソッドおよび resume() メソッドを使用して中断および再開できます。TimerManager を中断すると、未処理のタイマーはすべて TimerManager が再開されるまで保留されます。
TimerManager は、stop() メソッドを使用すると停止できます。stop() が呼び出されると、アクティブなタイマーはすべて停止され、TimerManager インスタンスはすべての TimerListener インスタンスのモニタを停止します。
commonj.timers
パッケージを使用するすべてのアプリケーションは、TimerListener インタフェースを実装する必要があります。
Timer インタフェースのインスタンスは、TimerManager を介してタイマーがスケジューリングされたときに返されます。
この節では、アプリケーション内で Timer API を使用するために必要な手順を簡単に示します。
アプリケーションをデプロイする前に、タイマー マネージャへのリソース参照を含むデプロイメント記述子が作成済みであることを確認してください。
これにより、TimerManager が JNDI を介してアクセス可能になります。JNDI ルックアップの詳細については、『WebLogic JNDI プログラマーズ ガイド』を参照してください。
IntialContext inctxt = new InitialContext();
JNDI ルックアップの詳細については、『WebLogic JNDI プログラマーズ ガイド』を参照してください。
TimerManager mgr = (TimerManager)ctx.lookup(`java:comp/env/timer/MyTimer');
この文では JNDI ルックアップの結果が TimerManager にキャストされています。
TimerListener listener = new StockQuoteTimerListener(`abc', `example');
mgr.schedule(listener, 0, 1000*60)
schedule() メソッドは Timer オブジェクトを返します。
public void timerExpired(Timer timer) {
//このメソッド内で
//ビジネス ロジックが実行される
}
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 つが有効である限り、このタイマーは機能を続けます。この機能はジョブ スケジューラと呼ばれます。
各タイマーにはそれぞれメリットとデメリットがあります。ローカル タイマーでは、複数のジョブをより短い時間間隔で処理できます。ジョブ スケジューラでは、クラスタ内の永続性要件のために同様の精度ではジョブを処理できません。一方で、初めにタスクを作成したサーバが失敗した場合にもそのタスクを実行する必要がある場合には、ジョブ スケジューラの方が適しています。
この節では、アプリケーション内にジョブ スケジューラを実装し、それを利用するように WebLogic Server 環境をコンフィグレーションするための基本的な手順を簡単に示します。
永続性を保持し、タイマーがクラスタを認識できるようにするため、ジョブ スケジューラにはデータベース接続が必要です。ジョブ スケジューラ機能では、サーバの移行でサポートされるのと同じデータベース ベンダおよびバージョンがサポートされます。
便宜上、セッション永続性、サーバの移行などに使用されているのと同じデータベースを使用できます。
データベースには、以下のスキーマで WEBLOGIC_TIMERS というテーブルを作成する必要があります。
CREATE TABLE WEBLOGIC_TIMERS(
TIMER_ID NUMBER,
TIMER_INFO VARCHAR2(100),
TIMER_MANAGER_NAME VARCHAR2(100),
CLUSTER_NAME VARCHAR2(100),
DOMAIN_NAME VARCHAR2(100),
TIMER_LISTENER BLOB,
NEXT_EXECUTION_TIME NUMBER,
INTERVAL NUMBER);
必要なスキーマでテーブルを作成した後には、クラスタ コンフィグレーション内で参照されるデータ ソースを定義する必要があります。ジョブ スケジューラ機能は、クラスタ MBean の DataSourceForJobScheduler 属性に有効なデータ ソースが定義されている場合にのみ利用できます。これは、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>
クラスタ化されたタイマー内で 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 秒ごとにこのジョブを実行
commonj.timer API のメソッドおよびインタフェースの中には、ジョブ スケジューラ環境でサポートされていないものもあります。以下のメソッドおよびインタフェースはサポートの対象外です。
Work Manager (commonj.work
) API は、アプリケーションがコンテナ内で複数の作業項目を同時に実行できるようにするインタフェースを提供します。
基本的に、この API は java.lang.Thread API のコンテナ管理の代替機能を提供します。java.lang.Thread API は、管理対象の J2EE 環境でホストされるアプリケーション内では使用しないようにする必要があります。Work Manager API を使用するとコンテナが実行中のすべてのスレッドを認識および制御できるので、そうした環境では代わりに Work Manager API を使用するようお勧めします。
注意 : | Work Manager API では、フェイルオーバや永続性メカニズムは提供されません。管理対象サーバ環境が失敗または停止した場合、現在の作業はすべて失われます。 |
この節では、Work Manager API に定義されているインタフェースの全般的な概要を説明します。これらのインタフェースの詳細な使用方法については、commonj.work パッケージの javadoc を参照してください。
Work Manager API には以下のインタフェースがあります。
WorkManager はサーバ レベルでシステム管理者が定義します。WorkManager インスタンスは JNDI ルックアップを実行して取得します。管理対象の環境では、複数の WorkManager インスタンスをサポートできます。『WebLogic JNDI プログラマーズ ガイド』を参照してください。WorkManager はデプロイ中に resource-ref としてコンフィグレーションします。「ワーク マネージャのデプロイメント」を参照してください。
アプリケーション レベルでは、WorkManager の各インスタンスが WorkItem を返します。アプリケーション内に WorkManager を実装する方法の詳細については、WorkManager の javadoc を参照してください。
Work
インスタンスが WorkManager に送信された後で、WorkManager は WorkItem を返します。WorkItem は完了した Work インスタンスの状態の判断に使用されます。
WorkListener を使用すると Work 項目の現在の状態を判断できます。詳細については、WorkListener の javadoc を参照してください。
注意 : | WorkListener インスタンスは、WorkManager 経由で Work をスケジューリングするのに使用した元のスレッドと常に同じ JVM で実行されます。 |
ワーク マネージャは、サーバレベルで、適切なデプロイメント記述子の 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 j2ee 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");}
}
![]() ![]() ![]() |