レベル: 中級 Jeff Genender (jgenender@virtuas.com), Practice Leader, Virtuas Solutions
2005年 8月 02日 Geronimoは、そのユニークなGBean機能を利用して、サードパーティー・コンポーネントを統合することができます。GBeanを利用すれば、自分独自のアプリケーション・サーバーを構築することができ、しかも特定なコンポーネントをGeronimoにプラグインしたりGeronimoから取り外したりすることによって、サーバーを重量級にも軽量にもすることができます。この記事では、Apache Geronimoのチーム・メンバーでありコミッターでもあるJeff Genenderが、この機能について解説します。ここではOpenSymphonyのQuartzスケジューラーをGeronimoに中に統合するGBeanを使いながら、サードパーティーのオープンソース・プロジェクトを構築し、コンフィギュレーションを行います。この記事の内容を完全に理解するためには、Geronimoをダウンロードしてソースからビルドできるだけの力を持っている必要があります。
GBeanのアーキテクチャー
Apache Geronimoアプリケーション・サーバーは非常に巧妙なアーキテクチャーで設計されており、カーネルは、どのコンポーネントにも直接依存することがありません。カーネルは、サービスに関するフレームワークであり、サービスのライフサイクルとレジストリーを制御します。カーネルはJ2EE(Java™ 2 Platform, Enterprise Edition)に基づいてはおらず、サービスやコンポーネントと動作しながら、特定なコンフィギュレーションを構築します。その特定なコンフィギュレーションの1つが、完全なJ2EEスタックです。Geronimoのサービスの大部分は、GBeanを通して追加、コンフィギュレーションされ、アプリケーション・サーバー全体の一部となります。GBeanは、コンポーネントをカーネルに接続するためのインターフェースです。各GBeanは他のGBeanと共に状態を維持し、また他のGBeanに依存し、他のGBeanと相関関係を持ち、そしてカーネルや他のGBeanからのイベントに対して動作します。図1は、GeronimoカーネルとGBeanとの関係を図で表現したものです。
図1. GeronimoカーネルとGBeanとの関係
GBeanをカーネルにプラグインするには、プラン(plan)と呼ばれるコンフィギュレーション・ファイルでIoC(Inversion of Control)や依存性注入(dependency injection)を行います。これはつまり、GeronimoでGBeanを使うにはプランの中でXML宣言すること、またGBeanは他のGBeanへの依存関係(属性や参照によってコンフィギュレーションされます)を持っているかも知れない、ということを意味します。リスト1は、GBeanコンフィギュレーションの一例を示しています。
リスト1. GBeanコンフィギュレーションの例
<gbean name="DefaultThreadPool" class="org.apache.geronimo.pool.ThreadPool">
<attribute name="keepAliveTime">5000</attribute>
<attribute name="poolSize">30</attribute>
<attribute name="poolName">DefaultThreadPool</attribute>
</gbean>>
|
このアーキテクチャーで最も興味深い部分は、プラン・ファイルを編集し、また、GBeanのXML宣言を変更することによって、どんなコンポーネントでもGeronimoスタックに追加、削除できる、という点です。
多くのGBeanでは、JettyやTomcat、OpenEJBなど、他のオープンソース・プロジェクトやコードをGeronimoスタックの一部とすることができ、しかもこれらのコンポーネントに対してJSR-77ライフサイクル機能を提供することができます。Javaベースの強力なコンポーネントの一例が、OpenSymphonyのQuartzスケジューラーです。この記事では、Quartz GBeanを作成し、Geronimoの中にQuartsスケジューラーとして統合する方法について解説します。
Quartsスケジューラー
ほとんどのアプリケーション・サーバーは、出荷時にはcronジョブあるいはデーモン・ジョブを実行する機能が付いておらず、これらの機能を持たせるためには大幅な修正が必要です。一部のアプリケーション・サーバーにはデーモン風のアプリケーションを作成するためのAPIがありますが、表現力豊富で完全な機能セットを提供しているものは、ほとんどありません。
OpenSymphonyの開発によるQuartzは、オープンソースでJavaベースの強力なスケジューラーです。その機能の中には、カスタム化スケジューリング、スケジュール・パーシスタンス(多くのタイプのパーシスタンス機構で使用できます)、リモート・スケジューリング機能、フォールト・トレランス、クラスタリング、等々があります。Quartzは単独で実行することもできますが、その豊富な機能を考えると、J2EEアプリケーション・サーバー・スタックに含めるための候補として最適です。QuartzをGeronimoの中に統合するためには、スケジューラー・サービスを起動停止するGBeanを作ります。
GBeanを開発する
GBeanの開発は単純で、数ステップで行うことができます。GBeanを開発するためには、まだ不安定なM4(Milestone 4)ブランチからGeronimoソースコードをダウンロードする必要があり、また、Geronimoのビルド方法をよく知っている必要があります(これに関する詳しい情報を網羅したGeronimo Wikiへのリンクが参考文献にあります)。GBeanは、属性や参照、オペレーションを持つことができます。各GBeanは、少なくとも下記の指針に従っている必要があります。
- ライフサイクル・イベントを処理する場合には、org.apache.geronimo.gbean.GBeanLifecycleインターフェースを実装していること。
- コンストラクターを提供していること。
- doStart()やdoStop()、doFail() などのメソッドを実装していること。
- コンストラクターを記述したGBeanInfo静的イニシャライザーを提供していること。
- public static GBeanInfo getGBeanInfo() メソッドを実装していること。
- そのGBeanを使うためのプランを作成できること、または既存のプランを編集できること。
こうした指針を念頭に置くと、GBeanは、少なくともリスト2のようなスケルトン構造を持ったものになるはずです。
リスト2. GBeanスケルトンの例
/**
* Quartz GBean
*/
public class QuartzGBean implements GBeanLifecycle {
private static final Log log = LogFactory.getLog(QuartzGBean.class);
public QuartzGBean() {
}
public void doFail() {
log.info("Service failed");
//Insert failure code here
}
public void doStart() throws Exception {
log.info("Starting service");
//Insert startup code here
}
public void doStop() throws Exception {
log.info("Stopping service");
//Insert stopping code here
}
public static final GBeanInfo GBEAN_INFO;
static {
GBeanInfoBuilder infoFactory = new GBeanInfoBuilder("QuartzGBean",
QuartzGBean.class);
GBEAN_INFO = infoFactory.getBeanInfo();
}
public static GBeanInfo getGBeanInfo() {
return GBEAN_INFO;
}
}
|
私は何度も『少なくとも』と強調しました。これは、すべてのGBeanは、必ずリスト2に示すような宣言や実装を含む必要があるためです。もし、デフォルト以外のコンストラクターが使用される場合、あるいは属性や参照、呼び出し可能な(callable)オペレーションが必要な場合は、GBEAN_INFO静的イニシャライザーは、それぞれsetConstructor() やaddAttribute()、addReference()、addOperation() を呼ぶ必要があります。このインスタンスには、特別なコンストラクターやオペレーション、属性、参照などはないので、これらのコールは必要ありません。
Quartzで必要なことは、Geronimoアプリケーション・サーバーのライフサイクルに合わせて起動停止することだけなので、GBeanと統合するプロジェクトとしてQuartzは最適です。つまり、Geronimoが起動するとQuartzが起動し、Geronimoが停止したらQuartzも停止するようにする、ということです。
この例では簡単にするために、Quartzコンフィギュレーションとしては、Quartzのディストリビューションに付属しているデフォルトを使います。これらのデフォルトは、.jarファイルの一部であるquartz.propertiesファイルの中にあります。パーシスタンス・レイヤー用のデータベースや、リモート・スケジューリングなど、高度なオプションを使うようにQuartzをコンフィギュレーションするためには、カスタムのquartz.propertiesファイルを作成する必要があります。(これらのオプションのコンフィギュレーションに関する詳しい情報については、参考文献に挙げた、OpenSymphonyのWebサイトへのリンクを見てください。)
Quartzスケジューラーは、単にStdSchedulerFactory.getDefaultScheduler() を呼んでスケジューラー・オブジェクトを取得するだけなので、簡単に起動、停止することができます。Quartzを起動するには、Scheduler.startup() メソッドを実行します。Quartzを停止するには、Scheduler.shutdown() メソッドを実行します。QuartzのライフサイクルをGeronimoに追従するようにするためには、GBeanのdoStart() メソッドの中にstartup() コールを置き、GBeanのdoStop() メソッドの中にshutdown() コールを置きます。リスト3は、Quartzコードを追加した後の完全なGBeanを示しています。
リスト3. 新しいQuartzGBean
package org.apache.geronimo.quartz;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
/**
* Quartz GBean
*/
public class QuartzGBean implements GBeanLifecycle {
private static final Log log = LogFactory.getLog(QuartzGBean.class);
public QuartzGBean() {
}
public void doFail() {
log.info("Service failed");
try {
doStop();
} catch (Exception e) {
log.error("doStop() failed", e);
}
}
public void doStart() throws Exception {
log.info("Starting service");
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
}
public void doStop() throws Exception {
log.info("Stopping service");
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.shutdown();
} catch (SchedulerException se) {
log.error("Cannot shutdown scheduler.", se);
}
}
public static final GBeanInfo GBEAN_INFO;
static {
GBeanInfoBuilder infoFactory = new GBeanInfoBuilder("QuartzGBean",
QuartzGBean.class);
GBEAN_INFO = infoFactory.getBeanInfo();
}
public static GBeanInfo getGBeanInfo() {
return GBEAN_INFO;
}
}
|
 |
なぜMavenなのか
Mavenは、Antを新しいレベルにまで高める、強力なビルド・ツールです。Mavenを使うことによって、何千ラインものAntビルド・スクリプトを持つような大規模な開発作業を単純化することができます。Mavenは、管理可能な塊にプロジェクトを分割することによって、ビルドを管理します。Mavenを使用すると、皆さんのプロジェクトが既に使用しているAntビルド・スクリプトを使うことから始めることもできます。そして時間をかけながら、Mavenを使ったプロジェクト・ビルド管理に移行できるのです。Geronimoのようなプロジェクト(少なくとも53のサブ・モジュールから構成されています)では、Mavenはビルド管理の鍵と言うことができます。
|
|
QuartzGBeanコードは単純に見えるかも知れませんが、やはりコンパイルして適切な .jarファイルをビルドする必要があります。Geronimoはビルド・ツールとしてApache Mavenを使っているので、この例でもQuartz用のMavenモジュールを使っています(参考文献には、MavenのWebサイトへのリンクがあります)。Mavenモジュールを作成するには、project.xmlファイルとproject.propertiesファイル、maven.xmlファイル、そしてソースコードが必要です。この記事用のダウンロード・コードには、GeronimoでQuartzGBeanをコンパイルするための完全なMavenビルド・モジュールが含まれています。このコードのコンパイルは、下記の手順で行います。
- geronimo/modulesディレクトリーにアーカイブ・ファイルをダウンロードし、そこで解凍します。quratzディレクトリーが作られ、その下に、QuartzGBean.javaコードやユニット・テストなどを含んだ、ビルド用のインフラが作られます。
- geronimo/modules/quartzディレクトリーの中にいることを確認してから、コマンドラインでmavenをタイプします。これによってGBeanがコンパイルされ、ユニット・テストされ、そしてgeronimo-quartz-1.0-snapshot.jarファイル(Mavenリポジトリーの中に保存されています)の中にGBeanがパッケージされます。
GeronimoにQuartzGBeanを統合する
さて、.jarファイルは作成したので、このGBeanを使用するためにGeronimoビルドに少し変更を加える必要があります。GBeanを作成する際には、通常、GBeanをデプロイするためのプランを作成します。この場合では、サーバーが起動したらGBeanも起動するようにするために、既存ファイルの幾つかを編集します(手動でのコンフィギュレーションの起動、デプロイは行いません。)Geronimoが新しいQuartzGBeanを使うようにコンフィギュレーションするためには、下記のステップを行います。
- Mavenが自動的に適切なバージョンをダウンロードするように、GeronimoビルドにQuartzバージョンを追加します。geronimo/etcディレクトリーにあるproject.propertiesファイルを編集し、下記を追加します。
- Quratzと新しい .jarファイルを使うように、アセンブリー・モジュールを整えます。geronimo/modules/assemblyディレクトリーで、リスト4に太字で示すコードを、dependenciesセクションにあるproject.xmlファイルに追加します。
リスト4. アセンブリーのproject.xml依存関係
<dependencies>
.
.
.
<!--Quartz -->
<dependency>
<groupId>opensymphony</groupId>
<artifactId>quartz</artifactId>
<version>${quartz_version}</version>
<properties>
<repository>true</repository>
</properties>
</dependency>
<dependency>
<groupId>geronimo</groupId>
<artifactId>geronimo-quartz</artifactId>
<version>${pom.currentVersion}</version>
<properties>
<repository>true</repository>
</properties>
</dependency>
.
.
.
</dependencies> |
Geronimoビルドは<repository>true</repository>コードによって、最終のGeronimoアセンブリーに含まれる .jarリポジトリーの中に .jarファイルを追加します。これで指定の .jarファイルを持つGeronimoビルドができあがることになります。
- GBeanと依存関係をプランとして書き出します。自分で独自のプランを作成することもできますが、Geronimoが起動する時にQuartzGBeanも確実に起動するようにするためには、既存のプランを編集した方がずっと簡単です。そのためには、geronimo/modules/assembly/src/planディレクトリーにあるj2ee-server-plan.xmlファイルを編集します。最後の
</dependency>タグの後、かつ最初の<gbean>タグの前で、この依存関係をプランに追加します。これをリスト5に示します。 リスト5. j2ee-server-plan.xml依存関係を追加する
<!-- Quartz -->
<dependency>
<uri>opensymphony/jars/quartz-${quartz_version}.jar</uri>
</dependency>
<dependency>
<uri>geronimo/jars/geronimo-quartz-${geronimo_version}.jar</uri>
</dependency>
|
- 同じファイルにGBeanを追加します。ファイルの最後、最後の
</configuration>タグの前に、次のラインを追加します。
あとは、アセンブリー・モジュールを再ビルドするだけです。これによって新しいコンフィギュレーションと、Geronimoサーバーの更新プラン部分が作られます。アセンブリー・モジュールを再ビルドするには、ディレクトリーをgeronimo/modules/assemblyに変更し、コマンド・プロンプトでmavenをタイプします。アセンブリー・モジュールのビルドが終了すると、geronimo/modules/assembly/targetディレクトリーにgeronimo-assembly-1.0-SNAPSHOT.jarファイルができるはずです。Geronimoを実行するには、コマンドラインからjava -jar bin/server.jar-vを実行します。通常、-vはGeronimoを実行するためには必要ありませんが、ここでは何が起きているかを見られるように、ログ出力をターミナル・ウィンドウに送るために -v を含めています。
-vを付けてGeronimoを起動する際には、ログに注意して、新しいGBeanがQuartzを起動するのを見てください(リスト6)。
リスト6. GeronimoがQuartzGBeanによってログを起動する
14:53:13,462 INFO [QuartzGBean] Starting service
14:53:13,615 INFO [SimpleThreadPool] Job execution threads will use class loader of
thread: main
14:53:13,697 INFO [RAMJobStore] RAMJobStore initialized.
14:53:13,699 INFO [StdSchedulerFactory] Quartz scheduler 'DefaultQuartzScheduler'
initialized from default resource file in
Quartz package: 'quartz.properties'
14:53:13,699 INFO [StdSchedulerFactory] Quartz scheduler version: 1.4.5
14:53:13,701 INFO [QuartzScheduler] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED
started. |
Geronimoを停止する際には、ログの中にある違いに注意します。
リスト7. GeronimoがQuartzGBeanによってログを停止する
14:53:41,426 INFO [QuartzGBean] Stopping service
14:53:41,450 INFO [QuartzScheduler] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED
shutting down.
14:53:41,452 INFO [QuartzScheduler] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED
paused.
14:53:41,459 INFO [QuartzScheduler] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED
shutdown complete.
|
まとめ
大部分のオープンソース・プロジェクトの場合、GBeanを書くために必要なことは、幾つかの機能を実装し、幾つかのコンフィギュレーション・ファイルを編集するだけです。しかし、JettyやTomcat、OpenEJBなどを統合するための作業では、かなり多くのコーディング修正が必要になる場合があります。そうした統合では、複数のGBeanやコンフィギュレーション、フック(hooks)が必要です。しかしQuartzのようなアプリケーションは、単に起動、停止すればよいだけなので、容易な統合を行うための候補としては理想的です。そしてオープンソース・プロジェクトの中には、Quartzと同じくらい容易
謝辞
この記事の見直しをしてくださった、Apache GeronimoチームのBruce SnyderとDain Sundstromに感謝致します。
この記事は、IBM developerWorksとVirtuas Solutionsの両方に置かれています。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Quartz GBean Maven code module | quartzgbean.zip | 10KB |
FTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Jeff GenenderはVirtuas SolutionsのPractice Leaderであり、Javaアーキテクチャーやオープンソース・ソリューションの実装に関する企業指導を専門にしています。彼はApache Geronimoのコミッターであり、PMCメンバーです。著書にはEnterprise Java Servlets(2001年9月、Addison Wesley Longman刊)があり、現在はJBoss Live(SourceBeat Publishing刊予定)を執筆中です。 |
記事の評価
|